File tree Expand file tree Collapse file tree 4 files changed +36
-12
lines changed
go/analysis/passes/loopclosure Expand file tree Collapse file tree 4 files changed +36
-12
lines changed Original file line number Diff line number Diff line change @@ -59,10 +59,12 @@ func run(pass *analysis.Pass) (interface{}, error) {
59
59
}
60
60
inspect .Preorder (nodeFilter , func (n ast.Node ) {
61
61
// Find the variables updated by the loop statement.
62
- var vars []* ast. Ident
62
+ var vars []types. Object
63
63
addVar := func (expr ast.Expr ) {
64
- if id , ok := expr .(* ast.Ident ); ok {
65
- vars = append (vars , id )
64
+ if id , _ := expr .(* ast.Ident ); id != nil {
65
+ if obj := pass .TypesInfo .ObjectOf (id ); obj != nil {
66
+ vars = append (vars , obj )
67
+ }
66
68
}
67
69
}
68
70
var body * ast.BlockStmt
@@ -132,17 +134,16 @@ func run(pass *analysis.Pass) (interface{}, error) {
132
134
133
135
ast .Inspect (lit .Body , func (n ast.Node ) bool {
134
136
id , ok := n .(* ast.Ident )
135
- if ! ok || id . Obj == nil {
137
+ if ! ok {
136
138
return true
137
139
}
138
- if pass .TypesInfo .Types [id ]. Type == nil {
139
- // Not referring to a variable (e.g. struct field name)
140
+ obj := pass .TypesInfo .Uses [id ]
141
+ if obj == nil {
140
142
return true
141
143
}
142
144
for _ , v := range vars {
143
- if v .Obj == id .Obj {
144
- pass .ReportRangef (id , "loop variable %s captured by func literal" ,
145
- id .Name )
145
+ if v == obj {
146
+ pass .ReportRangef (id , "loop variable %s captured by func literal" , id .Name )
146
147
}
147
148
}
148
149
return true
Original file line number Diff line number Diff line change @@ -7,11 +7,10 @@ package loopclosure_test
7
7
import (
8
8
"testing"
9
9
10
- "golang.org/x/tools/internal/analysisinternal"
11
- "golang.org/x/tools/internal/typeparams"
12
-
13
10
"golang.org/x/tools/go/analysis/analysistest"
14
11
"golang.org/x/tools/go/analysis/passes/loopclosure"
12
+ "golang.org/x/tools/internal/analysisinternal"
13
+ "golang.org/x/tools/internal/typeparams"
15
14
)
16
15
17
16
func Test (t * testing.T ) {
Original file line number Diff line number Diff line change @@ -10,6 +10,8 @@ import (
10
10
"golang.org/x/sync/errgroup"
11
11
)
12
12
13
+ var A int
14
+
13
15
func _ () {
14
16
var s []int
15
17
for i , v := range s {
@@ -51,6 +53,19 @@ func _() {
51
53
println (i , v )
52
54
}()
53
55
}
56
+
57
+ // iteration variable declared outside the loop
58
+ for A = range s {
59
+ go func () {
60
+ println (A ) // want "loop variable A captured by func literal"
61
+ }()
62
+ }
63
+ // iteration variable declared in a different file
64
+ for B = range s {
65
+ go func () {
66
+ println (B ) // want "loop variable B captured by func literal"
67
+ }()
68
+ }
54
69
// If the key of the range statement is not an identifier
55
70
// the code should not panic (it used to).
56
71
var x [2 ]int
Original file line number Diff line number Diff line change
1
+ // Copyright 2022 The Go Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style
3
+ // license that can be found in the LICENSE file.
4
+
5
+ package testdata
6
+
7
+ // B is declared in a separate file to test that object resolution spans the
8
+ // entire package.
9
+ var B int
You can’t perform that action at this time.
0 commit comments