diff options
author | Teddy Wing | 2024-03-10 16:10:36 +0100 |
---|---|---|
committer | Teddy Wing | 2024-03-10 16:10:36 +0100 |
commit | 1926d13444dbde1bcd221029ec44bd6bd30396a7 (patch) | |
tree | 1fef8a7fe16402fb21776d1b7b775229f411bbf7 | |
parent | ba664a54c0e275c01709e393030aeeae607d0656 (diff) | |
download | gocapturedrefrace-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.go | 61 |
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(), |