internal/lsp: fix panic in find references on Error

Our find references don't support (error).Error, but in this case, find
references actually panicked.

Fixes golang/go#48400

Change-Id: I68d6ea93528dc5425f59f0e952f03081c5a7847a
Reviewed-on: https://go-review.googlesource.com/c/tools/+/350132
Trust: Rebecca Stambler <rstambler@golang.org>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
diff --git a/gopls/internal/regtest/misc/references_test.go b/gopls/internal/regtest/misc/references_test.go
index f3a23e4..7682516 100644
--- a/gopls/internal/regtest/misc/references_test.go
+++ b/gopls/internal/regtest/misc/references_test.go
@@ -42,3 +42,42 @@
 		}
 	})
 }
+
+// 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 1cd9a40..993b9f8 100644
--- a/internal/lsp/source/references.go
+++ b/internal/lsp/source/references.go
@@ -6,6 +6,7 @@
 
 import (
 	"context"
+	"fmt"
 	"go/ast"
 	"go/token"
 	"go/types"
@@ -68,7 +69,11 @@
 		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