Skip to content

Commit

Permalink
gopls/internal/cache/methodsets: refine crash for missing object path
Browse files Browse the repository at this point in the history
We can't reproduce the crash observed in golang/go#70418, where a method
on a package level type name has no object path.

In any case, downgrade this crash to a bug report, and refine the report
to clarify some conditions potentially related to the crash.

For golang/go#70418

Change-Id: If6ab38e2189accf881e84da568525e2228c757fb
Reviewed-on: https://go-review.googlesource.com/c/tools/+/631778
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
  • Loading branch information
findleyr committed Nov 26, 2024
1 parent 07a58bc commit 0edd1ab
Showing 1 changed file with 33 additions and 7 deletions.
40 changes: 33 additions & 7 deletions gopls/internal/cache/methodsets/methodsets.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,10 @@ import (
"strings"

"golang.org/x/tools/go/types/objectpath"
"golang.org/x/tools/gopls/internal/util/bug"
"golang.org/x/tools/gopls/internal/util/frob"
"golang.org/x/tools/gopls/internal/util/safetoken"
"golang.org/x/tools/internal/typesinternal"
)

// An Index records the non-empty method sets of all package-level
Expand Down Expand Up @@ -223,16 +225,40 @@ func (b *indexBuilder) build(fset *token.FileSet, pkg *types.Package) *Index {
return
}

m.Posn = objectPos(method)
m.PkgPath = b.string(method.Pkg().Path())

// Instantiations of generic methods don't have an
// object path, so we use the generic.
if p, err := objectpathFor(method.Origin()); err != nil {
panic(err) // can't happen for a method of a package-level type
} else {
m.ObjectPath = b.string(string(p))
p, err := objectpathFor(method.Origin())
if err != nil {
// This should never happen for a method of a package-level type.
// ...but it does (golang/go#70418).
// Refine the crash into various bug reports.
report := func() {
bug.Reportf("missing object path for %s", method.FullName())
}
sig := method.Signature()
if sig.Recv() == nil {
report()
return
}
_, named := typesinternal.ReceiverNamed(sig.Recv())
switch {
case named == nil:
report()
case sig.TypeParams().Len() > 0:
report()
case method.Origin() != method:
report() // instantiated?
case sig.RecvTypeParams().Len() > 0:
report() // generic?
default:
report()
}
return
}

m.Posn = objectPos(method)
m.PkgPath = b.string(method.Pkg().Path())
m.ObjectPath = b.string(string(p))
}

// We ignore aliases, though in principle they could define a
Expand Down

0 comments on commit 0edd1ab

Please sign in to comment.