aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTeddy Wing2024-03-10 16:10:36 +0100
committerTeddy Wing2024-03-10 16:10:36 +0100
commit1926d13444dbde1bcd221029ec44bd6bd30396a7 (patch)
tree1fef8a7fe16402fb21776d1b7b775229f411bbf7
parentba664a54c0e275c01709e393030aeeae607d0656 (diff)
downloadgocapturedrefrace-1926d13444dbde1bcd221029ec44bd6bd30396a7.tar.bz2
Clean up Go 1.22 tests and fix broken analysis under Go 1.22
* Remove my debugging tests from trying to understand the Go 1.22 problem. * Describe the problem caused by the change in 'go/types' starting in Go 1.22.0. The problem was caused by https://github.com/golang/go/commit/a27a525d1b4df74989ac9f6ad10394391fe3eb88, which resolved the following two issues related to 'gopls': * https://github.com/golang/go/issues/64292 * https://github.com/golang/go/issues/64295
-rw-r--r--capturedrefrace.go61
1 files changed, 32 insertions, 29 deletions
diff --git a/capturedrefrace.go b/capturedrefrace.go
index 6b5b1df..66b59e5 100644
--- a/capturedrefrace.go
+++ b/capturedrefrace.go
@@ -51,7 +51,6 @@
package capturedrefrace
import (
- "fmt"
"go/ast"
"go/token"
"go/types"
@@ -180,8 +179,6 @@ func checkClosure(pass *analysis.Pass, funcLit *ast.FuncLit) {
ast.Inspect(
funcLit,
func(node ast.Node) bool {
- // fmt.Printf("node: %#v\n", node)
-
ident, ok := node.(*ast.Ident)
if !ok {
return true
@@ -198,13 +195,40 @@ func checkClosure(pass *analysis.Pass, funcLit *ast.FuncLit) {
}
}
- // Idea: If ident is in funcLit signature, then short-circuit.
-
// Find out whether `ident` was defined in an outer scope.
- // scope, scopeObj := funcScope.LookupParent(ident.Name, ident.NamePos)
- // scope, scopeObj := funcScope.LookupParent(ident.Name, funcLit.Body.Lbrace)
+ //
+ // Starting in Go 1.22.0, function scopes in the 'go/types' package
+ // have changed:
+ //
+ // > The start position (Pos) of the lexical environment block
+ // > (Scope) that represents a function body has changed: it used
+ // > to start at the opening curly brace of the function body, but
+ // > now starts at the function's func token.
+ //
+ // (https://go.dev/doc/go1.22#go/types)
+ //
+ // This was caused by the following commit, which corrected
+ // behaviour for gopls:
+ //
+ // https://github.com/golang/go/commit/a27a525d1b4df74989ac9f6ad10394391fe3eb88
+ //
+ // As a result, we can no longer use `ident.NamePos` as the
+ // position for `funcScope.LookupParent`. Doing so causes false
+ // positives for function arguments, incorrectly finding them to be
+ // captured references from the outer scope.
+ //
+ // The commit message of a27a525d1b4df74989ac9f6ad10394391fe3eb88
+ // states:
+ //
+ // > set correct Var.scopePos for parameters/results
+ // >
+ // > Previously, its value was unset (NoPos), but the correct
+ // > value is a point after the signature (FuncType.End) and
+ // > before the body.
+ //
+ // We can restore the previous behaviour by using `token.NoPos`
+ // instead of `ident.NamePos`.
scope, scopeObj := funcScope.LookupParent(ident.Name, token.NoPos)
- // fmt.Printf("ident: %#v\n\t%#v\n\t%#v\n", ident, scope, scopeObj)
// Identifier is local to the closure.
if scope == nil && scopeObj == nil {
@@ -223,28 +247,7 @@ func checkClosure(pass *analysis.Pass, funcLit *ast.FuncLit) {
return true
}
- if ident.Name == "copied" {
- fmt.Printf("identifier: %#v, obj: %#v, decl: %#v\n", ident, ident.Obj, ident.Obj.Decl)
- fmt.Printf(" scope: %#v\n", scope)
- fmt.Printf(" Names: %#v\n", scope.Names())
- fmt.Printf(" funcScope: %#v\n", funcScope)
- fmt.Printf(" Names: %#v\n", funcScope.Names())
- fmt.Println()
- }
-
- // za := slices.Index(funcScope.Names(), ident.Name)
- // if za == -1 {
- // return true
- // }
- // zb := slices.Index(scope.Names(), ident.Name)
- // if zb == -1 {
- // return true
- // }
-
- // TODO: Broken by golang/go a27a525d1b4df74989ac9f6ad10394391fe3eb88
- // Test with golang.org/x/tools@v0.15.0
// Identifier was defined in a different scope.
- // if funcScope != scope {
if funcScope != scope {
pass.Reportf(
ident.Pos(),