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)