]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] go/types: eliminate need for unpack and asUnion functions
authorRob Findley <rfindley@google.com>
Wed, 9 Jun 2021 22:41:19 +0000 (18:41 -0400)
committerRobert Findley <rfindley@google.com>
Thu, 17 Jun 2021 02:08:57 +0000 (02:08 +0000)
This is a straightforward port of CL 323355 to go/types, adjusted for
the different error reporting API in go/types.

Change-Id: I0f9d7ca0e0959e1e214ecd61eb85cc311e6409a2
Reviewed-on: https://go-review.googlesource.com/c/go/+/326679
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>
src/go/types/builtins.go
src/go/types/infer.go
src/go/types/subst.go
src/go/types/type.go

index 92807ed44a1622d0c0d1e54b775576bcaf629ac1..cfaeab611b0bd126a7e7b3a949d1f46851ed5a35 100644 (file)
@@ -768,14 +768,12 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type {
        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.
-               // TODO(gri) This needs to consider the ~ information if we
-               //           have a union type.
                var rtypes []Type
-               var tilde []bool
-               if !tp.Bound().is(func(x Type) bool {
-                       if r := f(x); r != nil {
+               var tildes []bool
+               if !tp.Bound().is(func(typ Type, tilde bool) bool {
+                       if r := f(typ); r != nil {
                                rtypes = append(rtypes, r)
-                               tilde = append(tilde, true)
+                               tildes = append(tildes, tilde)
                                return true
                        }
                        return false
@@ -786,7 +784,7 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type {
                // construct a suitable new type parameter
                tpar := NewTypeName(token.NoPos, nil /* = Universe pkg */, "<type parameter>", nil)
                ptyp := check.newTypeParam(tpar, 0, &emptyInterface) // assigns type to tpar as a side-effect
-               tsum := newUnion(rtypes, tilde)
+               tsum := newUnion(rtypes, tildes)
                ptyp.bound = &Interface{allMethods: markComplete, allTypes: tsum}
 
                return ptyp
index ddf02a3942a786f9a496dede6b91ef6894c78dd4..5a4f939bb131a7a1fe69c5cfeab76e89be80a144 100644 (file)
@@ -323,7 +323,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) {
                                        return true
                                }
                        }
-                       return w.isParameterizedList(unpackType(t.allTypes))
+                       return w.isParameterized(t.allTypes)
                }
 
                return t.iterate(func(t *Interface) bool {
@@ -472,11 +472,14 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty
 func (check *Checker) structuralType(constraint Type) Type {
        if iface, _ := under(constraint).(*Interface); iface != nil {
                check.completeInterface(token.NoPos, iface)
-               types := unpackType(iface.allTypes)
-               if len(types) == 1 {
-                       return types[0]
+               if u, _ := iface.allTypes.(*Union); u != nil {
+                       if u.NumTerms() == 1 {
+                               // TODO(gri) do we need to respect tilde?
+                               return u.types[0]
+                       }
+                       return nil
                }
-               return nil
+               return iface.allTypes
        }
-       return constraint
+       return nil
 }
index 24108993efa95dd45782ed4b0340135ab08f2a36..025eba0f8c3b3cb202480f4f8f2b28a6e10a6136 100644 (file)
@@ -198,14 +198,15 @@ func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *_TypeParam, smap
                        check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ)
                        return false
                }
-               for _, t := range unpackType(targBound.allTypes) {
-                       if !iface.isSatisfiedBy(t) {
+               return iface.is(func(typ Type, tilde bool) bool {
+                       // TODO(gri) incorporate tilde information!
+                       if !iface.isSatisfiedBy(typ) {
                                // TODO(gri) match this error message with the one below (or vice versa)
-                               check.softErrorf(atPos(pos), 0, "%s does not satisfy %s (%s type constraint %s not found in %s)", targ, tpar.bound, targ, t, iface.allTypes)
+                               check.softErrorf(atPos(pos), 0, "%s does not satisfy %s (%s type constraint %s not found in %s)", targ, tpar.bound, targ, typ, iface.allTypes)
                                return false
                        }
-               }
-               return false
+                       return true
+               })
        }
 
        // Otherwise, targ's type or underlying type must also be one of the interface types listed, if any.
index 8a4544e4971903e55c38290873f831dc4152b69c..7429056865e81ef67ae5fa0931165bc5349c3b2d 100644 (file)
@@ -266,29 +266,17 @@ type Interface struct {
        obj Object // type declaration defining this interface; or nil (for better error messages)
 }
 
-// unpack unpacks a type into a list of types.
-// TODO(gri) Try to eliminate the need for this function.
-func unpackType(typ Type) []Type {
-       if typ == nil {
-               return nil
-       }
-       if u := asUnion(typ); u != nil {
-               return u.types
-       }
-       return []Type{typ}
-}
-
-// is reports whether interface t represents types that all satisfy pred.
-func (t *Interface) is(pred func(Type) bool) bool {
-       if t.allTypes == nil {
+// is reports whether interface t represents types that all satisfy f.
+func (t *Interface) is(f func(Type, bool) bool) bool {
+       switch t := t.allTypes.(type) {
+       case nil, *top:
+               // TODO(gri) should settle on top or nil to represent this case
                return false // we must have at least one type! (was bug)
+       case *Union:
+               return t.is(func(typ Type, tilde bool) bool { return f(typ, tilde) })
+       default:
+               return f(t, false)
        }
-       for _, t := range unpackType(t.allTypes) {
-               if !pred(t) {
-                       return false
-               }
-       }
-       return true
 }
 
 // emptyInterface represents the empty (completed) interface
@@ -824,11 +812,6 @@ func asSignature(t Type) *Signature {
        return op
 }
 
-func asUnion(t Type) *Union {
-       op, _ := optype(t).(*Union)
-       return op
-}
-
 func asInterface(t Type) *Interface {
        op, _ := optype(t).(*Interface)
        return op