cmd/compile/internal/typecheck: record whether an interface is implicit

In preparation for capturing the implicit interface bit in export data,
thread through the IsImplicit property from types2 into typecheck.

Change-Id: I9b46fe73de102935a127e6ececaacd76738b557e
Reviewed-on: https://go-review.googlesource.com/c/go/+/357109
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go
index 48f4368..0bc9135 100644
--- a/src/cmd/compile/internal/noder/reader.go
+++ b/src/cmd/compile/internal/noder/reader.go
@@ -466,7 +466,7 @@
 	if len(fields) == 0 {
 		return types.Types[types.TINTER] // empty interface
 	}
-	return types.NewInterface(tpkg, fields)
+	return types.NewInterface(tpkg, fields, false)
 }
 
 func (r *reader) structType() *types.Type {
diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go
index 592de70..474a059 100644
--- a/src/cmd/compile/internal/noder/stencil.go
+++ b/src/cmd/compile/internal/noder/stencil.go
@@ -881,7 +881,7 @@
 		cond := ir.NewBinaryExpr(pos, ir.ONE, want, got)
 		typed(types.Types[types.TBOOL], cond)
 		panicArg := ir.NewNilExpr(pos)
-		typed(types.NewInterface(types.LocalPkg, nil), panicArg)
+		typed(types.NewInterface(types.LocalPkg, nil, false), panicArg)
 		then := ir.NewUnaryExpr(pos, ir.OPANIC, panicArg)
 		then.SetTypecheck(1)
 		x := ir.NewIfStmt(pos, cond, []ir.Node{then}, nil)
diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go
index 1a7cef4..f035e0d 100644
--- a/src/cmd/compile/internal/noder/types.go
+++ b/src/cmd/compile/internal/noder/types.go
@@ -213,7 +213,7 @@
 			methods[i] = types.NewField(g.pos(m), g.selector(m), mtyp)
 		}
 
-		return types.NewInterface(g.tpkg(typ), append(embeddeds, methods...))
+		return types.NewInterface(g.tpkg(typ), append(embeddeds, methods...), typ.IsImplicit())
 
 	case *types2.TypeParam:
 		// Save the name of the type parameter in the sym of the type.
diff --git a/src/cmd/compile/internal/test/abiutils_test.go b/src/cmd/compile/internal/test/abiutils_test.go
index f26cb89..12b4a0c 100644
--- a/src/cmd/compile/internal/test/abiutils_test.go
+++ b/src/cmd/compile/internal/test/abiutils_test.go
@@ -313,7 +313,7 @@
 	fldt := mkFuncType(types.FakeRecvType(), []*types.Type{},
 		[]*types.Type{types.Types[types.TSTRING]})
 	field := types.NewField(src.NoXPos, typecheck.Lookup("F"), fldt)
-	nei := types.NewInterface(types.LocalPkg, []*types.Field{field})
+	nei := types.NewInterface(types.LocalPkg, []*types.Field{field}, false)
 	i16 := types.Types[types.TINT16]
 	tb := types.Types[types.TBOOL]
 	s1 := mkstruct([]*types.Type{i16, i16, tb})
diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go
index cb1e56b..fcfadc1 100644
--- a/src/cmd/compile/internal/typecheck/iimport.go
+++ b/src/cmd/compile/internal/typecheck/iimport.go
@@ -815,7 +815,7 @@
 			return types.Types[types.TINTER]
 		}
 
-		t := types.NewInterface(r.currPkg, append(embeddeds, methods...))
+		t := types.NewInterface(r.currPkg, append(embeddeds, methods...), false)
 
 		// Ensure we expand the interface in the frontend (#25055).
 		types.CheckSize(t)
diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go
index b4d5302..9ebd8f1 100644
--- a/src/cmd/compile/internal/typecheck/subr.go
+++ b/src/cmd/compile/internal/typecheck/subr.go
@@ -1369,7 +1369,7 @@
 			// For an empty interface, we need to return a new type,
 			// since it may now be fully instantiated (HasTParam
 			// becomes false).
-			return types.NewInterface(t.Pkg(), nil)
+			return types.NewInterface(t.Pkg(), nil, false)
 		}
 		return t
 	}
@@ -1390,7 +1390,7 @@
 		}
 	}
 	if newfields != nil {
-		return types.NewInterface(t.Pkg(), newfields)
+		return types.NewInterface(t.Pkg(), newfields, false)
 	}
 	return t
 }
diff --git a/src/cmd/compile/internal/typecheck/type.go b/src/cmd/compile/internal/typecheck/type.go
index af694c2..c4c1ef5 100644
--- a/src/cmd/compile/internal/typecheck/type.go
+++ b/src/cmd/compile/internal/typecheck/type.go
@@ -108,7 +108,7 @@
 	methods := tcFields(n.Methods, nil)
 	base.Pos = lno
 
-	n.SetOTYPE(types.NewInterface(types.LocalPkg, methods))
+	n.SetOTYPE(types.NewInterface(types.LocalPkg, methods, false))
 	return n
 }
 
diff --git a/src/cmd/compile/internal/types/sizeof_test.go b/src/cmd/compile/internal/types/sizeof_test.go
index 7349e52..d37c173 100644
--- a/src/cmd/compile/internal/types/sizeof_test.go
+++ b/src/cmd/compile/internal/types/sizeof_test.go
@@ -26,7 +26,7 @@
 		{Forward{}, 20, 32},
 		{Func{}, 28, 48},
 		{Struct{}, 16, 32},
-		{Interface{}, 4, 8},
+		{Interface{}, 8, 16},
 		{Chan{}, 8, 16},
 		{Array{}, 12, 16},
 		{FuncArgs{}, 4, 8},
diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go
index 392c54b..ec17fe8 100644
--- a/src/cmd/compile/internal/types/type.go
+++ b/src/cmd/compile/internal/types/type.go
@@ -417,7 +417,8 @@
 
 // Interface contains Type fields specific to interface types.
 type Interface struct {
-	pkg *Pkg
+	pkg      *Pkg
+	implicit bool
 }
 
 // Typeparam contains Type fields specific to typeparam types.
@@ -1820,7 +1821,7 @@
 
 // NewInterface returns a new interface for the given methods and
 // embedded types. Embedded types are specified as fields with no Sym.
-func NewInterface(pkg *Pkg, methods []*Field) *Type {
+func NewInterface(pkg *Pkg, methods []*Field, implicit bool) *Type {
 	t := newType(TINTER)
 	t.SetInterface(methods)
 	for _, f := range methods {
@@ -1838,6 +1839,7 @@
 		t.SetBroke(true)
 	}
 	t.extra.(*Interface).pkg = pkg
+	t.extra.(*Interface).implicit = implicit
 	return t
 }
 
@@ -1875,6 +1877,13 @@
 	return t.extra.(*Typeparam).bound
 }
 
+// IsImplicit reports whether an interface is implicit (i.e. elided from a type
+// parameter constraint).
+func (t *Type) IsImplicit() bool {
+	t.wantEtype(TINTER)
+	return t.extra.(*Interface).implicit
+}
+
 // NewUnion returns a new union with the specified set of terms (types). If
 // tildes[i] is true, then terms[i] represents ~T, rather than just T.
 func NewUnion(terms []*Type, tildes []bool) *Type {
diff --git a/src/cmd/compile/internal/types/universe.go b/src/cmd/compile/internal/types/universe.go
index 8fa4b7c..d5239eb 100644
--- a/src/cmd/compile/internal/types/universe.go
+++ b/src/cmd/compile/internal/types/universe.go
@@ -58,7 +58,7 @@
 	}
 
 	Types[TANY] = newType(TANY)
-	Types[TINTER] = NewInterface(LocalPkg, nil)
+	Types[TINTER] = NewInterface(LocalPkg, nil, false)
 
 	defBasic := func(kind Kind, pkg *Pkg, name string) *Type {
 		typ := newType(kind)
@@ -111,7 +111,7 @@
 	if base.Flag.G > 0 {
 		DeferCheckSize()
 		AnyType = defBasic(TFORW, BuiltinPkg, "any")
-		AnyType.SetUnderlying(NewInterface(NoPkg, []*Field{}))
+		AnyType.SetUnderlying(NewInterface(NoPkg, []*Field{}, false))
 		ResumeCheckSize()
 	}
 
@@ -145,11 +145,11 @@
 		NewField(src.NoXPos, nil, Types[TSTRING]),
 	})
 	method := NewField(src.NoXPos, LocalPkg.Lookup("Error"), sig)
-	return NewInterface(NoPkg, []*Field{method})
+	return NewInterface(NoPkg, []*Field{method}, false)
 }
 
 func makeComparableInterface() *Type {
 	sig := NewSignature(NoPkg, FakeRecv(), nil, nil, nil)
 	method := NewField(src.NoXPos, LocalPkg.Lookup("=="), sig)
-	return NewInterface(NoPkg, []*Field{method})
+	return NewInterface(NoPkg, []*Field{method}, false)
 }