diff --git a/gopls/internal/regtest/completion/completion_test.go b/gopls/internal/regtest/completion/completion_test.go index 6e89c4f5c2..82f0757772 100644 --- a/gopls/internal/regtest/completion/completion_test.go +++ b/gopls/internal/regtest/completion/completion_test.go @@ -374,3 +374,40 @@ type S struct { } }) } + +func TestCompletion_Issue45510(t *testing.T) { + const files = ` +-- go.mod -- +module mod.com + +go 1.12 +-- main.go -- +package main + +func _() { + type a *a + var aaaa1, aaaa2 a + var _ a = aaaa + + type b a + var bbbb1, bbbb2 b + var _ b = bbbb +} +` + + Run(t, files, func(t *testing.T, env *Env) { + env.OpenFile("main.go") + + completions := env.Completion("main.go", env.RegexpSearch("main.go", `var _ a = aaaa()`)) + diff := compareCompletionResults([]string{"aaaa1", "aaaa2"}, completions.Items) + if diff != "" { + t.Fatal(diff) + } + + completions = env.Completion("main.go", env.RegexpSearch("main.go", `var _ b = bbbb()`)) + diff = compareCompletionResults([]string{"bbbb1", "bbbb2"}, completions.Items) + if diff != "" { + t.Fatal(diff) + } + }) +} diff --git a/internal/lsp/source/util.go b/internal/lsp/source/util.go index 690a781e04..d242c34dd5 100644 --- a/internal/lsp/source/util.go +++ b/internal/lsp/source/util.go @@ -221,12 +221,17 @@ func FormatNode(fset *token.FileSet, n ast.Node) string { // Deref returns a pointer's element type, traversing as many levels as needed. // Otherwise it returns typ. +// +// It can return a pointer type if the type refers to itself (see golang/go#45510). func Deref(typ types.Type) types.Type { for { p, ok := typ.Underlying().(*types.Pointer) if !ok { return typ } + if typ == p.Elem() { + return typ + } typ = p.Elem() } }