mirror of
https://github.com/golang/go
synced 2024-09-04 23:44:16 +00:00
[dev.typeparams] cmd/compile/internal/types2: eliminate need for unpack and asUnion functions
Change-Id: Iaa75b091d52f44939330e5945305aea323ba58f4 Reviewed-on: https://go-review.googlesource.com/c/go/+/323355 Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
848b58e473
commit
3c1d502a19
|
@ -749,14 +749,12 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type {
|
||||||
if tp := asTypeParam(x); tp != nil {
|
if tp := asTypeParam(x); tp != nil {
|
||||||
// Test if t satisfies the requirements for the argument
|
// Test if t satisfies the requirements for the argument
|
||||||
// type and collect possible result types at the same time.
|
// 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 rtypes []Type
|
||||||
var tilde []bool
|
var tildes []bool
|
||||||
if !tp.Bound().is(func(x Type) bool {
|
if !tp.Bound().is(func(typ Type, tilde bool) bool {
|
||||||
if r := f(x); r != nil {
|
if r := f(typ); r != nil {
|
||||||
rtypes = append(rtypes, r)
|
rtypes = append(rtypes, r)
|
||||||
tilde = append(tilde, true) // for now - see TODO above
|
tildes = append(tildes, tilde)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -772,7 +770,7 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type {
|
||||||
// construct a suitable new type parameter
|
// construct a suitable new type parameter
|
||||||
tpar := NewTypeName(nopos, nil /* = Universe pkg */, "<type parameter>", nil)
|
tpar := NewTypeName(nopos, nil /* = Universe pkg */, "<type parameter>", nil)
|
||||||
ptyp := check.NewTypeParam(tpar, 0, &emptyInterface) // assigns type to tpar as a side-effect
|
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}
|
ptyp.bound = &Interface{allMethods: markComplete, allTypes: tsum}
|
||||||
|
|
||||||
return ptyp
|
return ptyp
|
||||||
|
|
|
@ -328,7 +328,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return w.isParameterizedList(unpack(t.allTypes))
|
return w.isParameterized(t.allTypes)
|
||||||
}
|
}
|
||||||
|
|
||||||
return t.iterate(func(t *Interface) bool {
|
return t.iterate(func(t *Interface) bool {
|
||||||
|
@ -477,11 +477,14 @@ func (check *Checker) inferB(tparams []*TypeName, targs []Type, report bool) (ty
|
||||||
func (check *Checker) structuralType(constraint Type) Type {
|
func (check *Checker) structuralType(constraint Type) Type {
|
||||||
if iface, _ := under(constraint).(*Interface); iface != nil {
|
if iface, _ := under(constraint).(*Interface); iface != nil {
|
||||||
check.completeInterface(nopos, iface)
|
check.completeInterface(nopos, iface)
|
||||||
types := unpack(iface.allTypes)
|
if u, _ := iface.allTypes.(*Union); u != nil {
|
||||||
if len(types) == 1 {
|
if u.NumTerms() == 1 {
|
||||||
return types[0]
|
// TODO(gri) do we need to respect tilde?
|
||||||
|
return u.types[0]
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
return nil
|
return iface.allTypes
|
||||||
}
|
}
|
||||||
return constraint
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,14 +194,15 @@ func (check *Checker) satisfies(pos syntax.Pos, targ Type, tpar *TypeParam, smap
|
||||||
check.softErrorf(pos, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ)
|
check.softErrorf(pos, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for _, t := range unpack(targBound.allTypes) {
|
return iface.is(func(typ Type, tilde bool) bool {
|
||||||
if !iface.isSatisfiedBy(t) {
|
// TODO(gri) incorporate tilde information!
|
||||||
|
if !iface.isSatisfiedBy(typ) {
|
||||||
// TODO(gri) match this error message with the one below (or vice versa)
|
// TODO(gri) match this error message with the one below (or vice versa)
|
||||||
check.softErrorf(pos, "%s does not satisfy %s (%s type constraint %s not found in %s)", targ, tpar.bound, targ, t, iface.allTypes)
|
check.softErrorf(pos, "%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
|
||||||
return false
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, targ's type or underlying type must also be one of the interface types listed, if any.
|
// Otherwise, targ's type or underlying type must also be one of the interface types listed, if any.
|
||||||
|
|
|
@ -272,29 +272,17 @@ type Interface struct {
|
||||||
obj Object // type declaration defining this interface; or nil (for better error messages)
|
obj Object // type declaration defining this interface; or nil (for better error messages)
|
||||||
}
|
}
|
||||||
|
|
||||||
// unpack unpacks a type into a list of types.
|
// is reports whether interface t represents types that all satisfy f.
|
||||||
// TODO(gri) Try to eliminate the need for this function.
|
func (t *Interface) is(f func(Type, bool) bool) bool {
|
||||||
func unpack(typ Type) []Type {
|
switch t := t.allTypes.(type) {
|
||||||
if typ == nil {
|
case nil, *top:
|
||||||
return nil
|
// TODO(gri) should settle on top or nil to represent this case
|
||||||
}
|
|
||||||
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 {
|
|
||||||
return false // we must have at least one type! (was bug)
|
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 unpack(t.allTypes) {
|
|
||||||
if !pred(t) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// emptyInterface represents the empty (completed) interface
|
// emptyInterface represents the empty (completed) interface
|
||||||
|
@ -828,11 +816,6 @@ func asSignature(t Type) *Signature {
|
||||||
return op
|
return op
|
||||||
}
|
}
|
||||||
|
|
||||||
func asUnion(t Type) *Union {
|
|
||||||
op, _ := optype(t).(*Union)
|
|
||||||
return op
|
|
||||||
}
|
|
||||||
|
|
||||||
func asInterface(t Type) *Interface {
|
func asInterface(t Type) *Interface {
|
||||||
op, _ := optype(t).(*Interface)
|
op, _ := optype(t).(*Interface)
|
||||||
return op
|
return op
|
||||||
|
|
Loading…
Reference in a new issue