@@ -52,8 +52,10 @@ import (
52
52
"strings"
53
53
54
54
"golang.org/x/tools/go/types/objectpath"
55
+ "golang.org/x/tools/gopls/internal/util/bug"
55
56
"golang.org/x/tools/gopls/internal/util/frob"
56
57
"golang.org/x/tools/gopls/internal/util/safetoken"
58
+ "golang.org/x/tools/internal/typesinternal"
57
59
)
58
60
59
61
// An Index records the non-empty method sets of all package-level
@@ -223,16 +225,40 @@ func (b *indexBuilder) build(fset *token.FileSet, pkg *types.Package) *Index {
223
225
return
224
226
}
225
227
226
- m .Posn = objectPos (method )
227
- m .PkgPath = b .string (method .Pkg ().Path ())
228
-
229
228
// Instantiations of generic methods don't have an
230
229
// object path, so we use the generic.
231
- if p , err := objectpathFor (method .Origin ()); err != nil {
232
- panic (err ) // can't happen for a method of a package-level type
233
- } else {
234
- m .ObjectPath = b .string (string (p ))
230
+ p , err := objectpathFor (method .Origin ())
231
+ if err != nil {
232
+ // This should never happen for a method of a package-level type.
233
+ // ...but it does (golang/go#70418).
234
+ // Refine the crash into various bug reports.
235
+ report := func () {
236
+ bug .Reportf ("missing object path for %s" , method .FullName ())
237
+ }
238
+ sig := method .Signature ()
239
+ if sig .Recv () == nil {
240
+ report ()
241
+ return
242
+ }
243
+ _ , named := typesinternal .ReceiverNamed (sig .Recv ())
244
+ switch {
245
+ case named == nil :
246
+ report ()
247
+ case sig .TypeParams ().Len () > 0 :
248
+ report ()
249
+ case method .Origin () != method :
250
+ report () // instantiated?
251
+ case sig .RecvTypeParams ().Len () > 0 :
252
+ report () // generic?
253
+ default :
254
+ report ()
255
+ }
256
+ return
235
257
}
258
+
259
+ m .Posn = objectPos (method )
260
+ m .PkgPath = b .string (method .Pkg ().Path ())
261
+ m .ObjectPath = b .string (string (p ))
236
262
}
237
263
238
264
// We ignore aliases, though in principle they could define a
0 commit comments