diff --git a/gopls/internal/regtest/misc/references_test.go b/gopls/internal/regtest/misc/references_test.go index f3a23e436f5..768251680f9 100644 --- a/gopls/internal/regtest/misc/references_test.go +++ b/gopls/internal/regtest/misc/references_test.go @@ -42,3 +42,42 @@ func main() { } }) } + +// This reproduces and tests golang/go#48400. +func TestReferencesPanicOnError(t *testing.T) { + const files = ` +-- go.mod -- +module mod.com + +go 1.12 +-- main.go -- +package main + +type t interface { + error +} + +type s struct{} + +func (*s) Error() string { + return "" +} + +func _() { + var s s + _ = s.Error() +} +` + Run(t, files, func(t *testing.T, env *Env) { + env.OpenFile("main.go") + file, pos := env.GoToDefinition("main.go", env.RegexpSearch("main.go", `Error`)) + refs, err := env.Editor.References(env.Ctx, file, pos) + if err == nil { + t.Fatalf("expected error for references, instead got %v", refs) + } + wantErr := "no position for func (error).Error() string" + if err.Error() != wantErr { + t.Fatalf("expected error with message %s, instead got %s", wantErr, err.Error()) + } + }) +} diff --git a/internal/lsp/source/references.go b/internal/lsp/source/references.go index 1cd9a40abcc..993b9f8a14f 100644 --- a/internal/lsp/source/references.go +++ b/internal/lsp/source/references.go @@ -6,6 +6,7 @@ package source import ( "context" + "fmt" "go/ast" "go/token" "go/types" @@ -68,7 +69,11 @@ func references(ctx context.Context, snapshot Snapshot, qos []qualifiedObject, i seen = make(map[token.Pos]bool) ) - filename := snapshot.FileSet().Position(qos[0].obj.Pos()).Filename + pos := qos[0].obj.Pos() + if pos == token.NoPos { + return nil, fmt.Errorf("no position for %s", qos[0].obj) + } + filename := snapshot.FileSet().Position(pos).Filename pgf, err := qos[0].pkg.File(span.URIFromPath(filename)) if err != nil { return nil, err