Skip to content

Commit

Permalink
gopls/internal/lsp/source: reinstate equalOrigin for references check
Browse files Browse the repository at this point in the history
This logic was dropped in CL 464902, but is necessary for correctly
resolving references to variables.

Fixes golang/go#61618

Change-Id: Iebe46339e5f6ac0230f7376e742d786bae2a7438
Reviewed-on: https://go-review.googlesource.com/c/tools/+/513780
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
  • Loading branch information
findleyr committed Jul 28, 2023
1 parent 1561060 commit 82861e0
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 3 deletions.
16 changes: 13 additions & 3 deletions gopls/internal/lsp/source/references.go
Original file line number Diff line number Diff line change
Expand Up @@ -580,9 +580,12 @@ func localReferences(pkg Package, targets map[types.Object]bool, correspond bool
// matches reports whether obj either is or corresponds to a target.
// (Correspondence is defined as usual for interface methods.)
matches := func(obj types.Object) bool {
if targets[obj] {
return true
} else if methodRecvs != nil && obj.Name() == methodName {
for target := range targets {
if equalOrigin(obj, target) {
return true
}
}
if methodRecvs != nil && obj.Name() == methodName {
if orecv := effectiveReceiver(obj); orecv != nil {
for _, mrecv := range methodRecvs {
if concreteImplementsIntf(orecv, mrecv) {
Expand All @@ -608,6 +611,13 @@ func localReferences(pkg Package, targets map[types.Object]bool, correspond bool
return nil
}

// equalOrigin reports whether obj1 and obj2 have equivalent origin object.
// This may be the case even if obj1 != obj2, if one or both of them is
// instantiated.
func equalOrigin(obj1, obj2 types.Object) bool {
return obj1.Pkg() == obj2.Pkg() && obj1.Pos() == obj2.Pos() && obj1.Name() == obj2.Name()
}

// effectiveReceiver returns the effective receiver type for method-set
// comparisons for obj, if it is a method, or nil otherwise.
func effectiveReceiver(obj types.Object) types.Type {
Expand Down
39 changes: 39 additions & 0 deletions gopls/internal/regtest/marker/testdata/references/issue61618.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
Regression test for 'references' bug golang/go#61618:
references to instantiated fields were missing.

-- flags --
-min_go=go1.18

-- go.mod --
module example.com
go 1.18

-- a.go --
package a

// This file is adapted from the example in the issue.

type builder[S ~[]F, F ~string] struct {
name string
elements S //@loc(def, "elements"), refs(def, def, assign, use)
elemData map[F][]ElemData[F]
}

type ElemData[F ~string] struct {
Name F
}

type BuilderImpl[S ~[]F, F ~string] struct{ builder[S, F] }

func NewBuilderImpl[S ~[]F, F ~string](name string) *BuilderImpl[S, F] {
impl := &BuilderImpl[S,F]{
builder[S, F]{
name: name,
elements: S{}, //@loc(assign, "elements"), refs(assign, def, assign, use)
elemData: map[F][]ElemData[F]{},
},
}

_ = impl.elements //@loc(use, "elements"), refs(use, def, assign, use)
return impl
}

0 comments on commit 82861e0

Please sign in to comment.