Lineage: #61519 (filed R69) -> #63343 (R77 refile, auto-expired closed/not_planned on 2026-10-02) -> this issue (R85 refile). Third time this exact bug has been filed with zero code change in between.
Bug
isBuiltinNil (pkg/linters/nilctxpassed/nilctxpassed.go:124-135) performs a bare type assertion with no ParenExpr unwrap first:
func isBuiltinNil(pass *analysis.Pass, expr ast.Expr) bool {
ident, ok := expr.(*ast.Ident)
if !ok || ident.Name != "nil" {
return false
}
...
}
A parenthesized nil literal passed as a context.Context argument, e.g. doSomething((nil)), is legal (if unusual) Go and is completely invisible to this linter since (nil) is an *ast.ParenExpr, not an *ast.Ident, and the assertion fails before TypesInfo is ever consulted.
Re-verified 2026-10-03: nilctxpassed.go:124-135 unchanged; zero occurrences of UnwrapParenExpr anywhere in the file.
CI enforcement: .github/workflows/cgo.yml LINTER_FLAGS include -nilctxpassed on both the native and wasm custom-linter steps with -test=false.
Live impact: no production false negative found (grepped for parenthesized nil-literal arguments in context-typed call positions across pkg/, none found) -- latent but genuinely untested, zero ParenExpr coverage in testdata.
Pattern class: paren_unwrap_gap -- the same recurring class already fixed via astutil.UnwrapParenExpr in walkfuncerrshadow.go, mapdeletecheck.go, and packagelevelmutableslicemap.go, and via astutil.TwoValueTypeAssertionOKIdent in typeassertionokdiscarded.go.
Recommendation
Wrap expr with astutil.UnwrapParenExpr(expr) before the *ast.Ident assertion in isBuiltinNil, matching the established fix idiom used elsewhere in this codebase.
Validation checklist
Effort: trivial -- one-line unwrap plus one testdata case.
Generated by 🤖 Sergo - Serena Go Expert · claude · agent · 317.8 AIC · ⌖ 7.26 AIC · ⊞ 5.3K · ◷
Lineage: #61519 (filed R69) -> #63343 (R77 refile, auto-expired closed/not_planned on 2026-10-02) -> this issue (R85 refile). Third time this exact bug has been filed with zero code change in between.
Bug
isBuiltinNil (pkg/linters/nilctxpassed/nilctxpassed.go:124-135) performs a bare type assertion with no ParenExpr unwrap first:
A parenthesized nil literal passed as a context.Context argument, e.g.
doSomething((nil)), is legal (if unusual) Go and is completely invisible to this linter since(nil)is an*ast.ParenExpr, not an*ast.Ident, and the assertion fails before TypesInfo is ever consulted.Re-verified 2026-10-03: nilctxpassed.go:124-135 unchanged; zero occurrences of UnwrapParenExpr anywhere in the file.
CI enforcement: .github/workflows/cgo.yml LINTER_FLAGS include -nilctxpassed on both the native and wasm custom-linter steps with -test=false.
Live impact: no production false negative found (grepped for parenthesized nil-literal arguments in context-typed call positions across pkg/, none found) -- latent but genuinely untested, zero ParenExpr coverage in testdata.
Pattern class: paren_unwrap_gap -- the same recurring class already fixed via astutil.UnwrapParenExpr in walkfuncerrshadow.go, mapdeletecheck.go, and packagelevelmutableslicemap.go, and via astutil.TwoValueTypeAssertionOKIdent in typeassertionokdiscarded.go.
Recommendation
Wrap expr with
astutil.UnwrapParenExpr(expr)before the*ast.Identassertion in isBuiltinNil, matching the established fix idiom used elsewhere in this codebase.Validation checklist
doSomething((nil))(parenthesized nil as a context.Context argument) expecting a diagnosticEffort: trivial -- one-line unwrap plus one testdata case.