go/types/objectpath: add encoder type, to amortize allocation
This change adds a new encoder type with For method, that
is functionally equivalent to the old For function but avoids
the surprising cost of repeated calls to Scope.Names and
canonicalize (now called namedMethods), both of which
allocate and sorts a slice.
The former canonicalize function was previously applied to
interface types too, but this was costly and unnecessary
as they are already sorted.
The public API change will have to wait for proposal 58668
to be accepted and thus fix issue 51017; this change uses
the linkname hack to expose the function to x/tools to fix a
pressing bug in gopls.
See golang/go#58668
Updates golang/go#51017
Change-Id: Id3e8726517d31371b9376b0e47e320f8b6c5e085
Reviewed-on: https://go-review.googlesource.com/c/tools/+/470679
TryBot-Result: Gopher Robot <gobot@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
Run-TryBot: Alan Donovan <adonovan@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
diff --git a/gopls/internal/lsp/source/methodsets/methodsets.go b/gopls/internal/lsp/source/methodsets/methodsets.go
index 2c02555..f297840 100644
--- a/gopls/internal/lsp/source/methodsets/methodsets.go
+++ b/gopls/internal/lsp/source/methodsets/methodsets.go
@@ -54,6 +54,7 @@
"golang.org/x/tools/go/types/objectpath"
"golang.org/x/tools/gopls/internal/lsp/safetoken"
"golang.org/x/tools/internal/typeparams"
+ "golang.org/x/tools/internal/typesinternal"
)
// An Index records the non-empty method sets of all package-level
@@ -202,6 +203,8 @@
return gobPosition{b.string(posn.Filename), posn.Offset, len(obj.Name())}
}
+ objectpathFor := typesinternal.NewObjectpathFunc()
+
// setindexInfo sets the (Posn, PkgPath, ObjectPath) fields for each method declaration.
setIndexInfo := func(m *gobMethod, method *types.Func) {
// error.Error has empty Position, PkgPath, and ObjectPath.
@@ -214,7 +217,7 @@
// Instantiations of generic methods don't have an
// object path, so we use the generic.
- if p, err := objectpath.For(typeparams.OriginMethod(method)); err != nil {
+ if p, err := objectpathFor(typeparams.OriginMethod(method)); err != nil {
panic(err) // can't happen for a method of a package-level type
} else {
m.ObjectPath = b.string(string(p))