gopls/internal/lsp/source: test references bug on struct{p.T}

This change adds a regression test for bug in gopls' references
operation applied to the T identifier in an embedded struct field
such as struct{p.T): instead of reporting references to T,
it reports references to package name p.

This is a consequence of go/types bug golang/go#60372,
which sets the position of the struct field types.Var to
that of the ast.Field syntax (p) not the type name (T).
The bug was fixed in go1.21.

Updates golang/go#60372
Fixes golang/go#60369

Change-Id: Ibabe885ea689b30d966dbf7e51f8c25e44a6ce1c
Reviewed-on: https://go-review.googlesource.com/c/tools/+/497495
gopls-CI: kokoro <noreply+kokoro@google.com>
Run-TryBot: Alan Donovan <adonovan@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
diff --git a/gopls/internal/lsp/source/references.go b/gopls/internal/lsp/source/references.go
index 939f01a..166c59d 100644
--- a/gopls/internal/lsp/source/references.go
+++ b/gopls/internal/lsp/source/references.go
@@ -224,6 +224,7 @@
 	}
 
 	// Find the selected object (declaration or reference).
+	// For struct{T}, we choose the field (Def) over the type (Use).
 	pos, err := pgf.PositionPos(pp)
 	if err != nil {
 		return nil, err
@@ -649,6 +650,13 @@
 				targets[obj] = leaf
 			}
 		} else {
+			// Note: prior to go1.21, go/types issue #60372 causes the position
+			// a field Var T created for struct{*p.T} to be recorded at the
+			// start of the field type ("*") not the location of the T.
+			// This affects references and other gopls operations (issue #60369).
+			// TODO(adonovan): delete this comment when we drop support for go1.20.
+
+			// For struct{T}, we prefer the defined field Var over the used TypeName.
 			obj := info.ObjectOf(leaf)
 			if obj == nil {
 				return nil, nil, fmt.Errorf("%w for %q", errNoObjectFound, leaf.Name)
diff --git a/gopls/internal/regtest/marker/testdata/references/issue60369.txt b/gopls/internal/regtest/marker/testdata/references/issue60369.txt
new file mode 100644
index 0000000..c363f35
--- /dev/null
+++ b/gopls/internal/regtest/marker/testdata/references/issue60369.txt
@@ -0,0 +1,27 @@
+Regression test for 'references' bug golang/go#60369: a references
+query on the embedded type name T in struct{p.T} instead reports all
+references to the package name p.
+
+The bug was fixed in release go1.21 of go/types.
+
+-- flags --
+-min_go=go1.21
+
+-- go.mod --
+module example.com
+go 1.12
+
+-- a/a.go --
+package a
+
+type A struct{}
+const C = 0
+
+-- b/b.go --
+package b
+
+import a "example.com/a" //@loc(adef, "a")
+type s struct { a.A } //@loc(Aref1, "A"), loc(aref1, "a"), refs(Aref1, Aref1, Aref3), refs(aref1, adef, aref1, aref2, aref3)
+var _ a.A //@loc(aref2, re" (a)"), loc(Aref2, "A")
+var _ = s{}.A //@loc(Aref3, "A")
+const c = a.C //@loc(aref3, "a")