go/types/objectpath: remove use of linkname for gopls back doors
Use internal variables as back doors for gopls into the objectpath
package, rather than linkname. Using linkname breaks x/tools vendoring.
See golang/go#61443 for background as to why this back door is
necessary.
Change-Id: Iabf6e825d169ac1c4080dc326eccc661eaae7ec6
Reviewed-on: https://go-review.googlesource.com/c/tools/+/517737
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
diff --git a/go/types/objectpath/objectpath.go b/go/types/objectpath/objectpath.go
index c725d83..fa5834b 100644
--- a/go/types/objectpath/objectpath.go
+++ b/go/types/objectpath/objectpath.go
@@ -32,6 +32,7 @@
_ "unsafe"
"golang.org/x/tools/internal/typeparams"
+ "golang.org/x/tools/internal/typesinternal"
)
// A Path is an opaque name that identifies a types.Object
@@ -127,12 +128,15 @@
skipMethodSorting bool
}
-// Exposed to gopls via golang.org/x/tools/internal/typesinternal
-// TODO(golang/go#61443): eliminate this parameter one way or the other.
+// Expose back doors so that gopls can avoid method sorting, which can dominate
+// analysis on certain repositories.
//
-//go:linkname skipMethodSorting
-func skipMethodSorting(enc *Encoder) {
- enc.skipMethodSorting = true
+// TODO(golang/go#61443): remove this.
+func init() {
+ typesinternal.SkipEncoderMethodSorting = func(enc interface{}) {
+ enc.(*Encoder).skipMethodSorting = true
+ }
+ typesinternal.ObjectpathObject = object
}
// For returns the path to an object relative to its package,
@@ -572,17 +576,16 @@
// Object returns the object denoted by path p within the package pkg.
func Object(pkg *types.Package, p Path) (types.Object, error) {
- return object(pkg, p, false)
+ return object(pkg, string(p), false)
}
// Note: the skipMethodSorting parameter must match the value of
// Encoder.skipMethodSorting used during encoding.
-func object(pkg *types.Package, p Path, skipMethodSorting bool) (types.Object, error) {
- if p == "" {
+func object(pkg *types.Package, pathstr string, skipMethodSorting bool) (types.Object, error) {
+ if pathstr == "" {
return nil, fmt.Errorf("empty path")
}
- pathstr := string(p)
var pkgobj, suffix string
if dot := strings.IndexByte(pathstr, opType); dot < 0 {
pkgobj = pathstr
diff --git a/internal/facts/facts.go b/internal/facts/facts.go
index 44c0605..ec11d5e 100644
--- a/internal/facts/facts.go
+++ b/internal/facts/facts.go
@@ -247,7 +247,7 @@
key := key{pkg: factPkg, t: reflect.TypeOf(f.Fact)}
if f.Object != "" {
// object fact
- obj, err := typesinternal.ObjectpathObject(factPkg, f.Object, skipMethodSorting)
+ obj, err := typesinternal.ObjectpathObject(factPkg, string(f.Object), skipMethodSorting)
if err != nil {
// (most likely due to unexported object)
// TODO(adonovan): audit for other possibilities.
diff --git a/internal/typesinternal/objectpath.go b/internal/typesinternal/objectpath.go
new file mode 100644
index 0000000..5e96e89
--- /dev/null
+++ b/internal/typesinternal/objectpath.go
@@ -0,0 +1,24 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package typesinternal
+
+import "go/types"
+
+// This file contains back doors that allow gopls to avoid method sorting when
+// using the objectpath package.
+//
+// This is performance-critical in certain repositories, but changing the
+// behavior of the objectpath package is still being discussed in
+// golang/go#61443. If we decide to remove the sorting in objectpath we can
+// simply delete these back doors. Otherwise, we should add a new API to
+// objectpath that allows controlling the sorting.
+
+// SkipEncoderMethodSorting marks enc (which must be an *objectpath.Encoder) as
+// not requiring sorted methods.
+var SkipEncoderMethodSorting func(enc interface{})
+
+// ObjectpathObject is like objectpath.Object, but allows suppressing method
+// sorting.
+var ObjectpathObject func(pkg *types.Package, p string, skipMethodSorting bool) (types.Object, error)
diff --git a/internal/typesinternal/types.go b/internal/typesinternal/types.go
index 66e8b09..ce7d435 100644
--- a/internal/typesinternal/types.go
+++ b/internal/typesinternal/types.go
@@ -11,8 +11,6 @@
"go/types"
"reflect"
"unsafe"
-
- "golang.org/x/tools/go/types/objectpath"
)
func SetUsesCgo(conf *types.Config) bool {
@@ -52,17 +50,3 @@
}
var SetGoVersion = func(conf *types.Config, version string) bool { return false }
-
-// SkipEncoderMethodSorting marks the encoder as not requiring sorted methods,
-// as an optimization for gopls (which guarantees the order of parsed source files).
-//
-// TODO(golang/go#61443): eliminate this parameter one way or the other.
-//
-//go:linkname SkipEncoderMethodSorting golang.org/x/tools/go/types/objectpath.skipMethodSorting
-func SkipEncoderMethodSorting(enc *objectpath.Encoder)
-
-// ObjectpathObject is like objectpath.Object, but allows suppressing method
-// sorting (which is not necessary for gopls).
-//
-//go:linkname ObjectpathObject golang.org/x/tools/go/types/objectpath.object
-func ObjectpathObject(pkg *types.Package, p objectpath.Path, skipMethodSorting bool) (types.Object, error)