go/internal/gcimporter: allow reusing empty interfaces on the RHS of
type decls

This is a port of CL 367851 to x/tools. The test set-up is slightly
different; I added a TODO to converge.

Updates golang/go#49888

Change-Id: I31a63c1fc8f9a78526d8eea05fd01dae35770b5f
Reviewed-on: https://go-review.googlesource.com/c/tools/+/368354
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
diff --git a/go/internal/gcimporter/iexport_go118_test.go b/go/internal/gcimporter/iexport_go118_test.go
index 2dc5cc1..5fc1f86 100644
--- a/go/internal/gcimporter/iexport_go118_test.go
+++ b/go/internal/gcimporter/iexport_go118_test.go
@@ -23,10 +23,13 @@
 	"golang.org/x/tools/go/internal/gcimporter"
 )
 
+// TODO(rfindley): migrate this to testdata, as has been done in the standard library.
 func TestGenericExport(t *testing.T) {
 	const src = `
 package generic
 
+type Any any
+
 type T[A, B any] struct { Left A; Right B }
 
 var X T[int, string] = T[int, string]{1, "hi"}
diff --git a/go/internal/gcimporter/iimport.go b/go/internal/gcimporter/iimport.go
index 3e31874..cdb332c 100644
--- a/go/internal/gcimporter/iimport.go
+++ b/go/internal/gcimporter/iimport.go
@@ -331,7 +331,7 @@
 }
 
 func (p *iimporter) typAt(off uint64, base *types.Named) types.Type {
-	if t, ok := p.typCache[off]; ok && (base == nil || !isInterface(t)) {
+	if t, ok := p.typCache[off]; ok && canReuse(base, t) {
 		return t
 	}
 
@@ -343,12 +343,30 @@
 	r.declReader.Reset(p.declData[off-predeclReserved:])
 	t := r.doType(base)
 
-	if base == nil || !isInterface(t) {
+	if canReuse(base, t) {
 		p.typCache[off] = t
 	}
 	return t
 }
 
+// canReuse reports whether the type rhs on the RHS of the declaration for def
+// may be re-used.
+//
+// Specifically, if def is non-nil and rhs is an interface type with methods, it
+// may not be re-used because we have a convention of setting the receiver type
+// for interface methods to def.
+func canReuse(def *types.Named, rhs types.Type) bool {
+	if def == nil {
+		return true
+	}
+	iface, _ := rhs.(*types.Interface)
+	if iface == nil {
+		return true
+	}
+	// Don't use iface.Empty() here as iface may not be complete.
+	return iface.NumEmbeddeds() == 0 && iface.NumExplicitMethods() == 0
+}
+
 type importReader struct {
 	p          *iimporter
 	declReader bytes.Reader