go/analysis/passes/loopclosure: add typeparams test

testdata/src/typeparams is similar to testdata/src/a but
uses type parameters.

Change-Id: Ia92f146089da4b1a3743c265181127ca886a71ad
Reviewed-on: https://go-review.googlesource.com/c/tools/+/354701
Trust: Guodong Li <guodongli@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
diff --git a/go/analysis/passes/loopclosure/loopclosure_test.go b/go/analysis/passes/loopclosure/loopclosure_test.go
index 0916f5e..1498838 100644
--- a/go/analysis/passes/loopclosure/loopclosure_test.go
+++ b/go/analysis/passes/loopclosure/loopclosure_test.go
@@ -5,6 +5,7 @@
 package loopclosure_test
 
 import (
+	"golang.org/x/tools/internal/typeparams"
 	"testing"
 
 	"golang.org/x/tools/go/analysis/analysistest"
@@ -13,5 +14,9 @@
 
 func Test(t *testing.T) {
 	testdata := analysistest.TestData()
-	analysistest.Run(t, testdata, loopclosure.Analyzer, "a")
+	tests := []string{"a", "golang.org/..."}
+	if typeparams.Enabled {
+		tests = append(tests, "typeparams")
+	}
+	analysistest.Run(t, testdata, loopclosure.Analyzer, tests...)
 }
diff --git a/go/analysis/passes/loopclosure/testdata/src/typeparams/typeparams.go b/go/analysis/passes/loopclosure/testdata/src/typeparams/typeparams.go
new file mode 100644
index 0000000..55e129c
--- /dev/null
+++ b/go/analysis/passes/loopclosure/testdata/src/typeparams/typeparams.go
@@ -0,0 +1,60 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains tests for the loopclosure checker.
+
+//go:build go1.18
+
+package typeparams
+
+import "golang.org/x/sync/errgroup"
+
+func f[T any](data T) {
+	print(data)
+}
+
+func _[T any]() {
+	var s []T
+	for i, v := range s {
+		go func() {
+			f(i) // want "loop variable i captured by func literal"
+			f(v) // want "loop variable v captured by func literal"
+		}()
+	}
+}
+
+func loop[P interface{ Go(func() error) }](grp P) {
+	var s []int
+	for i, v := range s {
+		// The checker only matches on methods "(*...errgroup.Group).Go".
+		grp.Go(func() error {
+			print(i)
+			print(v)
+			return nil
+		})
+	}
+}
+
+func _() {
+	g := new(errgroup.Group)
+	loop(g) // the analyzer is not "type inter-procedural" so no findings are reported
+}
+
+type T[P any] struct {
+	a P
+}
+
+func (t T[P]) Go(func() error) { }
+
+func _(g T[errgroup.Group]) {
+	var s []int
+	for i, v := range s {
+		// "T.a" is method "(*...errgroup.Group).Go".
+		g.a.Go(func() error {
+			print(i)  // want "loop variable i captured by func literal"
+			print(v)  // want "loop variable v captured by func literal"
+			return nil
+		})
+	}
+}
\ No newline at end of file