golang.org/x/tools@v0.21.0/go/analysis/passes/loopclosure/testdata/src/a/a.go (about)

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