GoPLS Viewer

Home|gopls/go/analysis/passes/loopclosure/testdata/src/a/a.go
1// Copyright 2012 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// This file contains tests for the loopclosure checker.
6
7package testdata
8
9import (
10    "sync"
11
12    "golang.org/x/sync/errgroup"
13)
14
15var A int
16
17func _() {
18    var s []int
19    for iv := range s {
20        go func() {
21            println(i// want "loop variable i captured by func literal"
22            println(v// want "loop variable v captured by func literal"
23        }()
24    }
25    for iv := range s {
26        defer func() {
27            println(i// want "loop variable i captured by func literal"
28            println(v// want "loop variable v captured by func literal"
29        }()
30    }
31    for i := range s {
32        go func() {
33            println(i// want "loop variable i captured by func literal"
34        }()
35    }
36    for _v := range s {
37        go func() {
38            println(v// want "loop variable v captured by func literal"
39        }()
40    }
41    for iv := range s {
42        go func() {
43            println(iv)
44        }()
45        println("unfortunately, we don't catch the error above because of this statement")
46    }
47    for iv := range s {
48        go func(iv int) {
49            println(iv)
50        }(iv)
51    }
52    for iv := range s {
53        iv := iv
54        go func() {
55            println(iv)
56        }()
57    }
58
59    // iteration variable declared outside the loop
60    for A = range s {
61        go func() {
62            println(A// want "loop variable A captured by func literal"
63        }()
64    }
65    // iteration variable declared in a different file
66    for B = range s {
67        go func() {
68            println(B// want "loop variable B captured by func literal"
69        }()
70    }
71    // If the key of the range statement is not an identifier
72    // the code should not panic (it used to).
73    var x [2]int
74    var f int
75    for x[0], f = range s {
76        go func() {
77            _ = f // want "loop variable f captured by func literal"
78        }()
79    }
80    type T struct {
81        v int
82    }
83    for _v := range s {
84        go func() {
85            _ = T{v1}
86            _ = map[int]int{v1// want "loop variable v captured by func literal"
87        }()
88    }
89
90    // ordinary for-loops
91    for i := 0i < 10i++ {
92        go func() {
93            print(i// want "loop variable i captured by func literal"
94        }()
95    }
96    for ij := 01i < 100ij = ji+j {
97        go func() {
98            print(j// want "loop variable j captured by func literal"
99        }()
100    }
101    type cons struct {
102        car int
103        cdr *cons
104    }
105    var head *cons
106    for p := headp != nilp = p.cdr {
107        go func() {
108            print(p.car// want "loop variable p captured by func literal"
109        }()
110    }
111}
112
113// Cases that rely on recursively checking for last statements.
114func _() {
115
116    for i := range "outer" {
117        for j := range "inner" {
118            if j < 1 {
119                defer func() {
120                    print(i// want "loop variable i captured by func literal"
121                }()
122            } else if j < 2 {
123                go func() {
124                    print(i// want "loop variable i captured by func literal"
125                }()
126            } else {
127                go func() {
128                    print(i)
129                }()
130                println("we don't catch the error above because of this statement")
131            }
132        }
133    }
134
135    for i := 0i < 10i++ {
136        for j := 0j < 10j++ {
137            if j < 1 {
138                switch j {
139                case 0:
140                    defer func() {
141                        print(i// want "loop variable i captured by func literal"
142                    }()
143                default:
144                    go func() {
145                        print(i// want "loop variable i captured by func literal"
146                    }()
147                }
148            } else if j < 2 {
149                var a interface{} = j
150                switch a.(type) {
151                case int:
152                    defer func() {
153                        print(i// want "loop variable i captured by func literal"
154                    }()
155                default:
156                    go func() {
157                        print(i// want "loop variable i captured by func literal"
158                    }()
159                }
160            } else {
161                ch := make(chan string)
162                select {
163                case <-ch:
164                    defer func() {
165                        print(i// want "loop variable i captured by func literal"
166                    }()
167                default:
168                    go func() {
169                        print(i// want "loop variable i captured by func literal"
170                    }()
171                }
172            }
173        }
174    }
175}
176
177// Group is used to test that loopclosure only matches Group.Go when Group is
178// from the golang.org/x/sync/errgroup package.
179type Group struct{}
180
181func (g *GroupGo(func() error) {}
182
183func _() {
184    var s []int
185    // errgroup.Group.Go() invokes Go routines
186    g := new(errgroup.Group)
187    for iv := range s {
188        g.Go(func() error {
189            print(i// want "loop variable i captured by func literal"
190            print(v// want "loop variable v captured by func literal"
191            return nil
192        })
193    }
194
195    for iv := range s {
196        if i > 0 {
197            g.Go(func() error {
198                print(i// want "loop variable i captured by func literal"
199                return nil
200            })
201        } else {
202            g.Go(func() error {
203                print(v// want "loop variable v captured by func literal"
204                return nil
205            })
206        }
207    }
208
209    // Do not match other Group.Go cases
210    g1 := new(Group)
211    for iv := range s {
212        g1.Go(func() error {
213            print(i)
214            print(v)
215            return nil
216        })
217    }
218}
219
220// Real-world example from #16520, slightly simplified
221func _() {
222    var nodes []interface{}
223
224    critical := new(errgroup.Group)
225    others := sync.WaitGroup{}
226
227    isCritical := func(node interface{}) bool { return false }
228    run := func(node interface{}) error { return nil }
229
230    for _node := range nodes {
231        if isCritical(node) {
232            critical.Go(func() error {
233                return run(node// want "loop variable node captured by func literal"
234            })
235        } else {
236            others.Add(1)
237            go func() {
238                _ = run(node// want "loop variable node captured by func literal"
239                others.Done()
240            }()
241        }
242    }
243}
244
MembersX
_.BlockStmt.RangeStmt_4013.v
_.RangeStmt_1408.B
_.BlockStmt.RangeStmt_4534.v
_.RangeStmt_1121.v
_.T.v
_.head
_.BlockStmt.g1
errgroup
_.RangeStmt_1249.A
Group.Go
sync
_.RangeStmt_324.i
_.RangeStmt_1046.v
_.BlockStmt.RangeStmt_4207.v
_.BlockStmt.s
A
_.BlockStmt.RangeStmt_2451.i
_
_.RangeStmt_679.i
_.RangeStmt_1046.i
_.RangeStmt_1643.f
_.BlockStmt.RangeStmt_4207.i
_.RangeStmt_500.v
_.j
_.cons
_.BlockStmt.BlockStmt.j
_.BlockStmt.BlockStmt.BlockStmt.BlockStmt.ch
_.BlockStmt.RangeStmt_4534.i
_.RangeStmt_324.v
_.RangeStmt_1121.BlockStmt.v
_.T
Group.Go.g
_.RangeStmt_1779.v
Group
_.BlockStmt.g
_.RangeStmt_898.i
_.RangeStmt_898.v
_.BlockStmt.RangeStmt_4013.i
_.s
_.i
_.BlockStmt.i
_.RangeStmt_787.v
_.BlockStmt.RangeStmt_2451.BlockStmt.RangeStmt_2478.j
_.RangeStmt_500.i
_.x
_.f
_.cons.car
_.RangeStmt_1121.i
_.cons.cdr
_.p
_.RangeStmt_1121.BlockStmt.i
_.BlockStmt.critical
_.BlockStmt.others
_.BlockStmt.RangeStmt_4896.node
Members
X