diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go index eafe6e9eb82..da2dcf54aa3 100644 --- a/src/cmd/compile/internal/types2/builtins.go +++ b/src/cmd/compile/internal/types2/builtins.go @@ -46,7 +46,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) ( default: // make argument getter xlist, _ := check.exprList(call.ArgList, false) - arg = func(x *operand, i int) { *x = *xlist[i]; x.typ = expand(x.typ) } + arg = func(x *operand, i int) { *x = *xlist[i] } nargs = len(xlist) // evaluate first argument, if present if nargs > 0 { diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 008c2446fcd..3c2b10cd7e0 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -682,7 +682,6 @@ func (check *Checker) convertUntyped(x *operand, target Type) { // If x is a constant operand, the returned constant.Value will be the // representation of x in this context. func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, constant.Value, errorCode) { - target = expand(target) if x.mode == invalid || isTyped(x.typ) || target == Typ[Invalid] { return x.typ, nil, 0 } diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index 14e073bfaeb..e0996604819 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -279,12 +279,3 @@ func (n *Named) expand() { n.instance = nil } } - -// expand expands uninstantiated named types and leaves all other types alone. -// expand does not recurse. -func expand(typ Type) Type { - if t, _ := typ.(*Named); t != nil { - t.expand() - } - return typ -} diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index afef488b964..1541b3f416d 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -140,10 +140,6 @@ func (p *ifacePair) identical(q *ifacePair) bool { // For changes to this code the corresponding changes should be made to unifier.nify. func identical(x, y Type, cmpTags bool, p *ifacePair) bool { - // types must be expanded for comparison - x = expand(x) - y = expand(y) - if x == y { return true } @@ -306,6 +302,8 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool { // Two named types are identical if their type names originate // in the same type declaration. if y, ok := y.(*Named); ok { + x.expand() + y.expand() // TODO(gri) Why is x == y not sufficient? And if it is, // we can just return false here because x == y // is caught in the very beginning of this function. diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index 14112462e18..48b11b289cd 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -208,7 +208,6 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] // TODO(gri) We should delay rtyp expansion to when we actually need the // receiver; thus all checks here should be delayed to later. rtyp, _ := deref(recv.typ) - rtyp = expand(rtyp) // spec: "The receiver type must be of the form T or *T where T is a type name." // (ignore invalid types - error was reported before) @@ -216,6 +215,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] var err string switch T := rtyp.(type) { case *Named: + T.expand() // spec: "The type denoted by T is called the receiver base type; it must not // be a pointer or interface type and it must be declared in the same package // as the method." diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 7ae2db3412d..637829613b1 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -114,7 +114,10 @@ func asInterface(t Type) *Interface { } func asNamed(t Type) *Named { - e, _ := expand(t).(*Named) + e, _ := t.(*Named) + if e != nil { + e.expand() + } return e } diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index fa4a1638b6c..6a9eacd31df 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -446,8 +446,7 @@ func (check *Checker) instantiatedType(x syntax.Expr, targsx []syntax.Expr, def // make sure we check instantiation works at least once // and that the resulting type is valid check.later(func() { - t := expand(typ) - check.validType(t, nil) + check.validType(typ, nil) }) return typ diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index 75b9a121979..ae81382fb0e 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -229,10 +229,6 @@ func (u *unifier) nifyEq(x, y Type, p *ifacePair) bool { // code the corresponding changes should be made here. // Must not be called directly from outside the unifier. func (u *unifier) nify(x, y Type, p *ifacePair) bool { - // types must be expanded for comparison - x = expand(x) - y = expand(y) - if !u.exact { // If exact unification is known to fail because we attempt to // match a type name against an unnamed type literal, consider @@ -436,6 +432,8 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool { // return x.obj == y.obj // } if y, ok := y.(*Named); ok { + x.expand() + y.expand() // TODO(gri) This is not always correct: two types may have the same names // in the same package if one of them is nested in a function. // Extremely unlikely but we need an always correct solution. diff --git a/src/cmd/compile/internal/types2/union.go b/src/cmd/compile/internal/types2/union.go index 85aa3d91040..f61c37a6afd 100644 --- a/src/cmd/compile/internal/types2/union.go +++ b/src/cmd/compile/internal/types2/union.go @@ -68,8 +68,7 @@ func parseUnion(check *Checker, tlist []syntax.Expr) Type { // Note: This is a quadratic algorithm, but unions tend to be short. check.later(func() { for i, t := range terms { - typ := expand(t.typ) - if typ == Typ[Invalid] { + if t.typ == Typ[Invalid] { continue } @@ -85,16 +84,16 @@ func parseUnion(check *Checker, tlist []syntax.Expr) Type { } } - u := under(typ) + u := under(t.typ) f, _ := u.(*Interface) if t.tilde { if f != nil { - check.errorf(x, "invalid use of ~ (%s is an interface)", typ) + check.errorf(x, "invalid use of ~ (%s is an interface)", t.typ) continue // don't report another error for t } - if !Identical(u, typ) { - check.errorf(x, "invalid use of ~ (underlying type of %s is %s)", typ, u) + if !Identical(u, t.typ) { + check.errorf(x, "invalid use of ~ (underlying type of %s is %s)", t.typ, u) continue // don't report another error for t } }