]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile/internal/types2: replace Named, TypeParam methods with...
authorRobert Griesemer <gri@golang.org>
Thu, 18 Feb 2021 01:06:53 +0000 (17:06 -0800)
committerRobert Griesemer <gri@golang.org>
Thu, 18 Feb 2021 20:47:11 +0000 (20:47 +0000)
This removes two more converter methods in favor of functions.
This further reduces the API surface of types2.Type and matches
the approach taken in go/types.

Change-Id: I3cdd54c5e0d1e7664a69f3697fc081a66315b969
Reviewed-on: https://go-review.googlesource.com/c/go/+/293292
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
13 files changed:
src/cmd/compile/internal/importer/support.go
src/cmd/compile/internal/types2/builtins.go
src/cmd/compile/internal/types2/call.go
src/cmd/compile/internal/types2/decl.go
src/cmd/compile/internal/types2/expr.go
src/cmd/compile/internal/types2/lookup.go
src/cmd/compile/internal/types2/operand.go
src/cmd/compile/internal/types2/predicates.go
src/cmd/compile/internal/types2/subst.go
src/cmd/compile/internal/types2/type.go
src/cmd/compile/internal/types2/typexpr.go
src/cmd/compile/internal/types2/unify.go
src/cmd/compile/internal/types2/universe.go

index cac87745fe20932cd18be6feb7eb3bcaf74604b5..b1439135830b01b1b8daad64421ac9e0a3e31454 100644 (file)
@@ -127,7 +127,3 @@ type anyType struct{}
 func (t anyType) Underlying() types2.Type { return t }
 func (t anyType) Under() types2.Type      { return t }
 func (t anyType) String() string          { return "any" }
-
-// types2.aType is not exported for now so we need to implemented these here.
-func (anyType) Named() *types2.Named         { return nil }
-func (anyType) TypeParam() *types2.TypeParam { return nil }
index 763122bc5bcd165beead7d82d8ef863c6d415630..16e294d2268e16a34f9a84cdf17471cddf1245b7 100644 (file)
@@ -577,7 +577,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
 
        case _Alignof:
                // unsafe.Alignof(x T) uintptr
-               if x.typ.TypeParam() != nil {
+               if asTypeParam(x.typ) != nil {
                        check.invalidOpf(call, "unsafe.Alignof undefined for %s", x)
                        return
                }
@@ -638,7 +638,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
 
        case _Sizeof:
                // unsafe.Sizeof(x T) uintptr
-               if x.typ.TypeParam() != nil {
+               if asTypeParam(x.typ) != nil {
                        check.invalidOpf(call, "unsafe.Sizeof undefined for %s", x)
                        return
                }
@@ -705,7 +705,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
 // applyTypeFunc returns nil.
 // If x is not a type parameter, the result is f(x).
 func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type {
-       if tp := x.TypeParam(); tp != nil {
+       if tp := asTypeParam(x); tp != nil {
                // Test if t satisfies the requirements for the argument
                // type and collect possible result types at the same time.
                var rtypes []Type
index 10db701324c3beec306204018a621a026789640a..67a76d14fbffc607c590d58d9b7360de22c96210 100644 (file)
@@ -563,7 +563,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) {
                        check.errorf(e.Sel, "cannot call pointer method %s on %s", sel, x.typ)
                default:
                        var why string
-                       if tpar := x.typ.TypeParam(); tpar != nil {
+                       if tpar := asTypeParam(x.typ); tpar != nil {
                                // Type parameter bounds don't specify fields, so don't mention "field".
                                switch obj := tpar.Bound().obj.(type) {
                                case nil:
index 59d0a112b1264b64f0cb4cc1730306759fdb0b8e..e9fc08df377746eefb332eb5e45f6a1555353e8b 100644 (file)
@@ -559,7 +559,7 @@ func (n0 *Named) Under() Type {
 
        // If the underlying type of a defined type is not a defined
        // type, then that is the desired underlying type.
-       n := u.Named()
+       n := asNamed(u)
        if n == nil {
                return u // common case
        }
@@ -573,7 +573,7 @@ func (n0 *Named) Under() Type {
                        u = Typ[Invalid]
                        break
                }
-               n1 := u.Named()
+               n1 := asNamed(u)
                if n1 == nil {
                        break // end of chain
                }
@@ -760,7 +760,7 @@ func (check *Checker) collectMethods(obj *TypeName) {
 
        // spec: "If the base type is a struct type, the non-blank method
        // and field names must be distinct."
-       base := obj.typ.Named() // shouldn't fail but be conservative
+       base := asNamed(obj.typ) // shouldn't fail but be conservative
        if base != nil {
                if t, _ := base.underlying.(*Struct); t != nil {
                        for _, fld := range t.fields {
index 07b23c9effeaf4d82bfe62d67115c11bb9459aea..57c8896e0d7283b8ce2301a44e736d9040e58e8b 100644 (file)
@@ -615,7 +615,7 @@ func (check *Checker) convertUntyped(x *operand, target Type) {
        // TODO(gri) We should not need this because we have the code
        // for Sum types in convertUntypedInternal. But at least one
        // test fails. Investigate.
-       if t := target.TypeParam(); t != nil {
+       if t := asTypeParam(target); t != nil {
                types := t.Bound().allTypes
                if types == nil {
                        goto Error
index df25c9cf701a6a17c26dde4575d7dd6da8ae0a59..e210850ba09438b35daf2494f96729c33f2c9dba 100644 (file)
@@ -54,7 +54,7 @@ func (check *Checker) lookupFieldOrMethod(T Type, addressable bool, pkg *Package
        // Thus, if we have a named pointer type, proceed with the underlying
        // pointer type but discard the result if it is a method since we would
        // not have found it for T (see also issue 8590).
-       if t := T.Named(); t != nil {
+       if t := asNamed(T); t != nil {
                if p, _ := t.underlying.(*Pointer); p != nil {
                        obj, index, indirect = check.rawLookupFieldOrMethod(p, false, pkg, name)
                        if _, ok := obj.(*Func); ok {
@@ -112,7 +112,7 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack
 
                        // If we have a named type, we may have associated methods.
                        // Look for those first.
-                       if named := typ.Named(); named != nil {
+                       if named := asNamed(typ); named != nil {
                                if seen[named] {
                                        // We have seen this type before, at a more shallow depth
                                        // (note that multiples of this type at the current depth
@@ -142,7 +142,7 @@ func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Pack
                                // continue with underlying type, but only if it's not a type parameter
                                // TODO(gri) is this what we want to do for type parameters? (spec question)
                                typ = named.Under()
-                               if typ.TypeParam() != nil {
+                               if asTypeParam(typ) != nil {
                                        continue
                                }
                        }
@@ -352,7 +352,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
 
        // A concrete type implements T if it implements all methods of T.
        Vd, _ := deref(V)
-       Vn := Vd.Named()
+       Vn := asNamed(Vd)
        for _, m := range T.allMethods {
                // TODO(gri) should this be calling lookupFieldOrMethod instead (and why not)?
                obj, _, _ := check.rawLookupFieldOrMethod(V, false, m.pkg, m.name)
index dcd29fbce0e27476ca5a7ded0cce2518763019e7..238c9b8ee0eba67d35c3480e49a45a4bcc09fcbc 100644 (file)
@@ -180,7 +180,7 @@ func operandString(x *operand, qf Qualifier) string {
                        switch {
                        case isGeneric(x.typ):
                                intro = " of generic type "
-                       case x.typ.TypeParam() != nil:
+                       case asTypeParam(x.typ) != nil:
                                intro = " of type parameter type "
                        default:
                                intro = " of type "
index a7972c6928b8e8b4e6d48b51534a194f58b4d244..a48e72b9c4fa3bc7b976f82ec66f8e5cae421390 100644 (file)
@@ -104,7 +104,7 @@ func comparable(T Type, seen map[Type]bool) bool {
        //     interface{ comparable; type []byte }
        //
        // is not comparable because []byte is not comparable.
-       if t := T.TypeParam(); t != nil && optype(t) == theTop {
+       if t := asTypeParam(T); t != nil && optype(t) == theTop {
                return t.Bound().IsComparable()
        }
 
index 27405d8f41e98240f61c15b6c403de5b13c22065..fc4b228e331ecaa0c5a01217ff9fa1d1772d6efb 100644 (file)
@@ -146,7 +146,7 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, poslis
                        // If the type argument is a pointer to a type parameter, the type argument's
                        // method set is empty.
                        // TODO(gri) is this what we want? (spec question)
-                       if base, isPtr := deref(targ); isPtr && base.TypeParam() != nil {
+                       if base, isPtr := deref(targ); isPtr && asTypeParam(base) != nil {
                                check.errorf(pos, "%s has no methods", targ)
                                break
                        }
@@ -179,7 +179,7 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, poslis
 
                // If targ is itself a type parameter, each of its possible types, but at least one, must be in the
                // list of iface types (i.e., the targ type list must be a non-empty subset of the iface types).
-               if targ := targ.TypeParam(); targ != nil {
+               if targ := asTypeParam(targ); targ != nil {
                        targBound := targ.Bound()
                        if targBound.allTypes == nil {
                                check.softErrorf(pos, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ)
index f90abba8da3399245168d596063f970b953fc821..4b6f507393ba5db36800b5f8f6e31c68cbb9ad49 100644 (file)
@@ -26,13 +26,6 @@ type Type interface {
 
        // String returns a string representation of a type.
        String() string
-
-       // If the receiver for Named and TypeParam is of
-       // the respective type (possibly after unpacking
-       // an instance type), these methods return that
-       // type. Otherwise the result is nil.
-       Named() *Named
-       TypeParam() *TypeParam
 }
 
 // aType implements default type behavior
@@ -43,9 +36,6 @@ func (aType) Underlying() Type { panic("unreachable") }
 func (aType) Under() Type      { panic("unreachable") }
 func (aType) String() string   { panic("unreachable") }
 
-func (aType) Named() *Named         { return nil }
-func (aType) TypeParam() *TypeParam { return nil }
-
 // BasicKind describes the kind of basic type.
 type BasicKind int
 
@@ -209,6 +199,9 @@ type Tuple struct {
        aType
 }
 
+// TODO(gri) Don't represent empty tuples with a (*Tuple)(nil) pointer;
+//           it's too subtle and causes problems. Use a singleton instead.
+
 // NewTuple returns a new tuple for the given variables.
 func NewTuple(x ...*Var) *Tuple {
        if len(x) > 0 {
@@ -217,16 +210,6 @@ func NewTuple(x ...*Var) *Tuple {
        return nil
 }
 
-// We cannot rely on the embedded X() *X methods because (*Tuple)(nil)
-// is a valid *Tuple value but (*Tuple)(nil).X() would panic without
-// these implementations. At the moment we only need X = Basic, Named,
-// but add all because missing one leads to very confusing bugs.
-// TODO(gri) Don't represent empty tuples with a (*Tuple)(nil) pointer;
-//           it's too subtle and causes problems.
-
-func (*Tuple) Named() *Named         { return nil }
-func (*Tuple) TypeParam() *TypeParam { return nil }
-
 // Len returns the number variables of tuple t.
 func (t *Tuple) Len() int {
        if t != nil {
@@ -730,9 +713,6 @@ func (check *Checker) NewNamed(obj *TypeName, underlying Type, methods []*Func)
 // Obj returns the type name for the named type t.
 func (t *Named) Obj() *TypeName { return t.obj }
 
-// func (t *Named) Named() *Named      // declared below
-func (t *Named) TypeParam() *TypeParam { return t.Under().TypeParam() }
-
 // TODO(gri) Come up with a better representation and API to distinguish
 //           between parameterized instantiated and non-instantiated types.
 
@@ -814,7 +794,7 @@ func (t *TypeParam) Bound() *Interface {
 // result may be the bottom or top type, but it is never
 // the incoming type parameter.
 func optype(typ Type) Type {
-       if t := typ.TypeParam(); t != nil {
+       if t := asTypeParam(typ); t != nil {
                // If the optype is typ, return the top type as we have
                // no information. It also prevents infinite recursion
                // via the TypeParam converter methods. This can happen
@@ -830,9 +810,6 @@ func optype(typ Type) Type {
        return typ.Under()
 }
 
-// func (t *TypeParam) Named() *Named         // Named does not unpack type parameters
-// func (t *TypeParam) TypeParam() *TypeParam // declared below
-
 // An instance represents an instantiated generic type syntactically
 // (without expanding the instantiation). Type instances appear only
 // during type-checking and are replaced by their fully instantiated
@@ -847,9 +824,6 @@ type instance struct {
        aType
 }
 
-func (t *instance) Named() *Named         { return t.expand().Named() }
-func (t *instance) TypeParam() *TypeParam { return t.expand().TypeParam() }
-
 // expand returns the instantiated (= expanded) type of t.
 // The result is either an instantiated *Named type, or
 // Typ[Invalid] if there was an error.
@@ -908,9 +882,6 @@ type top struct {
 // theTop is the singleton top type.
 var theTop = &top{}
 
-func (t *Named) Named() *Named             { return t }
-func (t *TypeParam) TypeParam() *TypeParam { return t }
-
 // Type-specific implementations of Underlying.
 func (t *Basic) Underlying() Type     { return t }
 func (t *Array) Underlying() Type     { return t }
@@ -1025,3 +996,17 @@ func asChan(t Type) *Chan {
        op, _ := optype(t).(*Chan)
        return op
 }
+
+// If the argument to asNamed and asTypeParam is of the respective types
+// (possibly after expanding an instance type), these methods return that type.
+// Otherwise the result is nil.
+
+func asNamed(t Type) *Named {
+       e, _ := expand(t).(*Named)
+       return e
+}
+
+func asTypeParam(t Type) *TypeParam {
+       u, _ := t.Under().(*TypeParam)
+       return u
+}
index 7ee28abac36c35c52381e03024f8a7ed830d77b7..cf9d7c0a40ae22a4e45d8b8e31dc412c8ae6ea8c 100644 (file)
@@ -302,7 +302,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []
                                // Also: Don't report an error via genericType since it will be reported
                                //       again when we type-check the signature.
                                // TODO(gri) maybe the receiver should be marked as invalid instead?
-                               if recv := check.genericType(rname, false).Named(); recv != nil {
+                               if recv := asNamed(check.genericType(rname, false)); recv != nil {
                                        recvTParams = recv.tparams
                                }
                        }
@@ -382,7 +382,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []
                // (ignore invalid types - error was reported before)
                if t := rtyp; t != Typ[Invalid] {
                        var err string
-                       if T := t.Named(); T != nil {
+                       if T := asNamed(t); T != nil {
                                // 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."
@@ -575,7 +575,7 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) {
                check.atEnd(func() {
                        if !Comparable(typ.key) {
                                var why string
-                               if typ.key.TypeParam() != nil {
+                               if asTypeParam(typ.key) != nil {
                                        why = " (missing comparable constraint)"
                                }
                                check.errorf(e.Key, "invalid map key type %s%s", typ.key, why)
@@ -644,7 +644,7 @@ func (check *Checker) instantiatedType(x syntax.Expr, targs []syntax.Expr, def *
        if b == Typ[Invalid] {
                return b // error already reported
        }
-       base := b.Named()
+       base := asNamed(b)
        if base == nil {
                unreachable() // should have been caught by genericType
        }
@@ -1045,7 +1045,7 @@ func (a byUniqueTypeName) Less(i, j int) bool { return sortName(a[i]) < sortName
 func (a byUniqueTypeName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
 
 func sortName(t Type) string {
-       if named := t.Named(); named != nil {
+       if named := asNamed(t); named != nil {
                return named.obj.Id()
        }
        return ""
index ab19c5a38bb803645ce62966e60ac354b86593ef..153df9d622b9652a4ca931cc1c47a4ee289ebcd7 100644 (file)
@@ -211,12 +211,12 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool {
                // match a type name against an unnamed type literal, consider
                // the underlying type of the named type.
                // (Subtle: We use isNamed to include any type with a name (incl.
-               // basic types and type parameters. We use Named() because we only
+               // basic types and type parameters. We use asNamed because we only
                // want *Named types.)
                switch {
-               case !isNamed(x) && y != nil && y.Named() != nil:
+               case !isNamed(x) && y != nil && asNamed(y) != nil:
                        return u.nify(x, y.Under(), p)
-               case x != nil && x.Named() != nil && !isNamed(y):
+               case x != nil && asNamed(x) != nil && !isNamed(y):
                        return u.nify(x.Under(), y, p)
                }
        }
index dc79902777d086c8893a00931f8ee54686b909c8..994e298a6c535b4d746d65f1ef309ce4cbc95710 100644 (file)
@@ -255,7 +255,7 @@ func def(obj Object) {
                return // nothing to do
        }
        // fix Obj link for named types
-       if typ := obj.Type().Named(); typ != nil {
+       if typ := asNamed(obj.Type()); typ != nil {
                typ.obj = obj.(*TypeName)
        }
        // exported identifiers go into package unsafe