]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: remove asTypeParam and simplify some code
authorRobert Findley <rfindley@google.com>
Tue, 16 Nov 2021 04:39:22 +0000 (23:39 -0500)
committerRobert Findley <rfindley@google.com>
Tue, 16 Nov 2021 15:35:52 +0000 (15:35 +0000)
This is a port of CL 363438 from types2 to go/types.

Change-Id: I87c76d31b398b9ce406f96b0030ee458619b3dbe
Reviewed-on: https://go-review.googlesource.com/c/go/+/364235
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
13 files changed:
src/go/types/builtins.go
src/go/types/call.go
src/go/types/conversions.go
src/go/types/decl.go
src/go/types/expr.go
src/go/types/instantiate.go
src/go/types/lookup.go
src/go/types/operand.go
src/go/types/predicates.go
src/go/types/type.go
src/go/types/typeset.go
src/go/types/typexpr.go
src/go/types/union.go

index c1932232aaf757c0b55327613a04948b86663c8a..5418d66aebfcc8f9fc113ebed69abfe33083bd1a 100644 (file)
@@ -298,7 +298,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                // the argument types must be of floating-point type
                // (applyTypeFunc never calls f with a type parameter)
                f := func(typ Type) Type {
-                       assert(asTypeParam(typ) == nil)
+                       assert(!isTypeParam(typ))
                        if t, _ := under(typ).(*Basic); t != nil {
                                switch t.kind {
                                case Float32:
@@ -441,7 +441,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
                // the argument must be of complex type
                // (applyTypeFunc never calls f with a type parameter)
                f := func(typ Type) Type {
-                       assert(asTypeParam(typ) == nil)
+                       assert(!isTypeParam(typ))
                        if t, _ := under(typ).(*Basic); t != nil {
                                switch t.kind {
                                case Complex64:
@@ -822,7 +822,7 @@ func hasVarSize(t Type) bool {
 // 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 := asTypeParam(x); tp != nil {
+       if tp, _ := x.(*TypeParam); tp != nil {
                // Test if t satisfies the requirements for the argument
                // type and collect possible result types at the same time.
                var terms []*Term
index dfd7142094e023d8025a16a8efe52caaf2ca6d0a..7cb6027f3bcc8386d44ef98ca8c26fafe8da3b85 100644 (file)
@@ -531,7 +531,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
                        check.errorf(e.Sel, _InvalidMethodExpr, "cannot call pointer method %s on %s", sel, x.typ)
                default:
                        var why string
-                       if tpar := asTypeParam(x.typ); tpar != nil {
+                       if tpar, _ := x.typ.(*TypeParam); tpar != nil {
                                // Type parameter bounds don't specify fields, so don't mention "field".
                                if tname := tpar.iface().obj; tname != nil {
                                        why = check.sprintf("interface %s has no method %s", tname.name, sel)
index 18d24e404c832ce1d83abfa557d33ac0f136d1a6..eadc923f5e287c8030071253df4e22fe43b08b0b 100644 (file)
@@ -47,7 +47,7 @@ func (check *Checker) conversion(x *operand, T Type) {
                // If T's type set is empty, or if it doesn't
                // have specific types, constant x cannot be
                // converted.
-               ok = under(T).(*TypeParam).underIs(func(u Type) bool {
+               ok = T.(*TypeParam).underIs(func(u Type) bool {
                        // t is nil if there are no specific type terms
                        if u == nil {
                                cause = check.sprintf("%s does not contain specific types", T)
@@ -186,8 +186,8 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool {
        }
 
        // optimization: if we don't have type parameters, we're done
-       Vp, _ := Vu.(*TypeParam)
-       Tp, _ := Tu.(*TypeParam)
+       Vp, _ := V.(*TypeParam)
+       Tp, _ := T.(*TypeParam)
        if Vp == nil && Tp == nil {
                return false
        }
index e12961416e3fead5928c75e89989e5b8eed3c346..2108cf6b0551ff0e52cf0b9463eef7fa8da689f1 100644 (file)
@@ -669,10 +669,11 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) {
        }
 
        // Disallow a lone type parameter as the RHS of a type declaration (issue #45639).
-       // We can look directly at named.underlying because even if it is still a *Named
-       // type (underlying not fully resolved yet) it cannot become a type parameter due
-       // to this very restriction.
-       if tpar, _ := named.underlying.(*TypeParam); tpar != nil {
+       // We don't need this restriction anymore if we make the underlying type of a type
+       // parameter its constraint interface: if the RHS is a lone type parameter, we will
+       // use its underlying type (like we do for any RHS in a type declaration), and its
+       // underlying type is an interface and the type declaration is well defined.
+       if isTypeParam(rhs) {
                check.error(tdecl.Type, _MisplacedTypeParam, "cannot use a type parameter as RHS in type declaration")
                named.underlying = Typ[Invalid]
        }
@@ -723,7 +724,7 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list *ast.FieldList
 
        check.later(func() {
                for i, bound := range bounds {
-                       if _, ok := under(bound).(*TypeParam); ok {
+                       if isTypeParam(bound) {
                                check.error(posns[i], _MisplacedTypeParam, "cannot use a type parameter as constraint")
                        }
                }
index 6eeb431b736ad0112f8ac04325fb683b7c7f95fb..660c92de3b3dc0745060ed112a7a354ea7651059 100644 (file)
@@ -147,11 +147,10 @@ var op2str2 = [...]string{
 // If typ is a type parameter, underIs returns the result of typ.underIs(f).
 // Otherwise, underIs returns the result of f(under(typ)).
 func underIs(typ Type, f func(Type) bool) bool {
-       u := under(typ)
-       if tpar, _ := u.(*TypeParam); tpar != nil {
+       if tpar, _ := typ.(*TypeParam); tpar != nil {
                return tpar.underIs(f)
        }
-       return f(u)
+       return f(under(typ))
 }
 
 // The unary expression e may be nil. It's passed in for better error messages only.
index 13d6e3114d6b12ef3e76b9f23d82fc6c48570f2c..c9ce6f6ae1e485b23fca4e3d8bdce017a23416f5 100644 (file)
@@ -157,7 +157,7 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap
 
        // A type argument that is a type parameter with an empty type set satisfies any constraint.
        // (The empty set is a subset of any set.)
-       if targ := asTypeParam(targ); targ != nil && targ.iface().typeSet().IsEmpty() {
+       if targ, _ := targ.(*TypeParam); targ != nil && targ.iface().typeSet().IsEmpty() {
                return nil
        }
 
@@ -186,7 +186,7 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap
        // if iface is comparable, targ must be comparable
        // TODO(gri) the error messages needs to be better, here
        if iface.IsComparable() && !Comparable(targ) {
-               if tpar := asTypeParam(targ); tpar != nil && tpar.iface().typeSet().IsAll() {
+               if tpar, _ := targ.(*TypeParam); tpar != nil && tpar.iface().typeSet().IsAll() {
                        return errorf("%s has no constraints", targ)
                }
                return errorf("%s does not satisfy comparable", targ)
@@ -198,7 +198,7 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap
                // 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 && asTypeParam(base) != nil {
+               if base, isPtr := deref(targ); isPtr && isTypeParam(base) {
                        return errorf("%s has no methods", targ)
                }
                if m, wrong := check.missingMethod(targ, iface, true); m != nil {
@@ -227,7 +227,7 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap
        // If targ is itself a type parameter, each of its possible types must be in the set
        // of iface types (i.e., the targ type set must be a subset of the iface type set).
        // Type arguments with empty type sets were already excluded above.
-       if targ := asTypeParam(targ); targ != nil {
+       if targ, _ := targ.(*TypeParam); targ != nil {
                targBound := targ.iface()
                if !targBound.typeSet().subsetOf(iface.typeSet()) {
                        // TODO(gri) report which type is missing
index aae6fa206df03e4bd7984fb502512eef45c17c32..98af6bfcd74c28b80d26bdfb133742e4000096b9 100644 (file)
@@ -134,14 +134,8 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
                                        continue // we can't have a matching field or interface method
                                }
 
-                               // 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)
-                               // TODO(#45639) the error message produced as a result of skipping an
-                               //              underlying type parameter should be improved.
+                               // continue with underlying type
                                typ = named.under()
-                               if asTypeParam(typ) != nil {
-                                       continue
-                               }
                        }
 
                        tpar = nil
index 8b76e939b6773c3b1bba6dc6a73158047dd88fa8..6f902e974932bae5962344ba2426a2140495590e 100644 (file)
@@ -166,7 +166,7 @@ func operandString(x *operand, qf Qualifier) string {
                        }
                        buf.WriteString(intro)
                        WriteType(&buf, x.typ, qf)
-                       if tpar := asTypeParam(x.typ); tpar != nil {
+                       if tpar, _ := x.typ.(*TypeParam); tpar != nil {
                                buf.WriteString(" constrained by ")
                                WriteType(&buf, tpar.bound, qf) // do not compute interface type sets here
                        }
@@ -241,8 +241,8 @@ func (x *operand) assignableTo(check *Checker, T Type, reason *string) (bool, er
 
        Vu := under(V)
        Tu := under(T)
-       Vp, _ := Vu.(*TypeParam)
-       Tp, _ := Tu.(*TypeParam)
+       Vp, _ := V.(*TypeParam)
+       Tp, _ := T.(*TypeParam)
 
        // x is an untyped value representable by a value of type T.
        if isUntyped(Vu) {
index 2d9b9c4c079cba66326a9411b786e5e318e75f2f..d0697b1ad7028a43869df24978e73a501e384ed8 100644 (file)
@@ -92,7 +92,7 @@ func IsInterface(t Type) bool {
 
 // isTypeParam reports whether t is a type parameter.
 func isTypeParam(t Type) bool {
-       _, ok := under(t).(*TypeParam)
+       _, ok := t.(*TypeParam)
        return ok
 }
 
index e26d8189d17f1f6146d5afea010e8a426e578bfa..555eb9e8b9934383fc53a6e7a9abe63d42947ffd 100644 (file)
@@ -88,9 +88,3 @@ func asNamed(t Type) *Named {
        }
        return e
 }
-
-// If t is a type parameter, asTypeParam returns that type, otherwise it returns nil.
-func asTypeParam(t Type) *TypeParam {
-       u, _ := under(t).(*TypeParam)
-       return u
-}
index 1e6b9dd3906932efeb3e9a22606ce68d90112226..d0464aeaa0c22bc8a23c910aa19e163923b23a61 100644 (file)
@@ -289,10 +289,6 @@ func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_T
                                continue // ignore invalid unions
                        }
                        terms = tset.terms
-               case *TypeParam:
-                       // Embedding stand-alone type parameters is not permitted.
-                       // Union parsing reports a (delayed) error, so we can ignore this entry.
-                       continue
                default:
                        if u == Typ[Invalid] {
                                continue
@@ -370,10 +366,6 @@ func computeUnionTypeSet(check *Checker, pos token.Pos, utyp *Union) *_TypeSet {
                switch u := under(t.typ).(type) {
                case *Interface:
                        terms = computeInterfaceTypeSet(check, pos, u).terms
-               case *TypeParam:
-                       // A stand-alone type parameters is not permitted as union term.
-                       // Union parsing reports a (delayed) error, so we can ignore this entry.
-                       continue
                default:
                        if t.typ == Typ[Invalid] {
                                continue
index 5828c2e7c356ea97c34bc50f2b606643ad9abf83..89264ee9eb52e92dbeee46a44767271a7cb901c7 100644 (file)
@@ -337,7 +337,7 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) {
                check.later(func() {
                        if !Comparable(typ.key) {
                                var why string
-                               if asTypeParam(typ.key) != nil {
+                               if isTypeParam(typ.key) {
                                        why = " (missing comparable constraint)"
                                }
                                check.errorf(e.Key, _IncomparableMapKey, "incomparable map key type %s%s", typ.key, why)
index bb0817472849f0b8363abf82f428bb6fca3cd699..2a65ca4d8e0b531a83c7adf2239e3796c98529a4 100644 (file)
@@ -118,15 +118,14 @@ func parseTilde(check *Checker, x ast.Expr) (tilde bool, typ Type) {
        }
        typ = check.typ(x)
        // Embedding stand-alone type parameters is not permitted (issue #47127).
-       // Do this check later because it requires computation of the underlying type (see also issue #46461).
-       // Note: If an underlying type cannot be a type parameter, the call to
-       //       under() will not be needed and then we don't need to delay this
-       //       check to later and could return Typ[Invalid] instead.
-       check.later(func() {
-               if _, ok := under(typ).(*TypeParam); ok {
-                       check.error(x, _MisplacedTypeParam, "cannot embed a type parameter")
-               }
-       })
+       // We don't need this restriction anymore if we make the underlying type of a type
+       // parameter its constraint interface: if we embed a lone type parameter, we will
+       // simply use its underlying type (like we do for other named, embedded interfaces),
+       // and since the underlying type is an interface the embedding is well defined.
+       if isTypeParam(typ) {
+               check.error(x, _MisplacedTypeParam, "cannot embed a type parameter")
+               typ = Typ[Invalid]
+       }
        return
 }