// type and collect possible result types at the same time.
var rtypes []Type
var tildes []bool
- if !tp.Bound().is(func(typ Type, tilde bool) bool {
+ if !tp.iface().is(func(typ Type, tilde bool) bool {
if r := f(typ); r != nil {
rtypes = append(rtypes, r)
tildes = append(tildes, tilde)
var why string
if tpar := asTypeParam(x.typ); tpar != nil {
// Type parameter bounds don't specify fields, so don't mention "field".
- if tname := tpar.Bound().obj; tname != nil {
+ if tname := tpar.iface().obj; tname != nil {
why = check.sprintf("interface %s has no method %s", tname.name, sel)
} else {
why = check.sprintf("type bound for %s has no method %s", x.typ, sel)
// A suitable error is reported if the result is false.
// TODO(gri) This should be a method of interfaces or type sets.
func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap *substMap) bool {
- iface := tpar.Bound()
+ iface := tpar.iface()
if iface.Empty() {
return true // no type bound
}
// 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.Bound().typeSet().IsTop() {
+ if tpar := asTypeParam(targ); tpar != nil && tpar.iface().typeSet().IsTop() {
check.softErrorf(atPos(pos), _Todo, "%s has no constraints", targ)
return false
}
// 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 := asTypeParam(targ); targ != nil {
- targBound := targ.Bound()
+ targBound := targ.iface()
if targBound.typeSet().types == nil {
check.softErrorf(atPos(pos), _Todo, "%s does not satisfy %s (%s has no type constraints)", targ, tpar.bound, targ)
return false
}
case *TypeParam:
- if i, m := t.Bound().typeSet().LookupMethod(pkg, name); m != nil {
+ if i, m := t.iface().typeSet().LookupMethod(pkg, name); m != nil {
assert(m.typ != nil)
index = concat(e.index, i)
if obj != nil || e.multiples {
mset = mset.add(t.typeSet().methods, e.index, true, e.multiples)
case *TypeParam:
- mset = mset.add(t.Bound().typeSet().methods, e.index, true, e.multiples)
+ mset = mset.add(t.iface().typeSet().methods, e.index, true, e.multiples)
}
}
case *Array:
return comparable(t.elem, seen)
case *TypeParam:
- return t.Bound().IsComparable()
+ return t.iface().IsComparable()
}
return false
}
// for a type parameter list of the form:
// (type T interface { type T }).
// See also issue #39680.
- if a := t.Bound().typeSet().types; a != nil && a != typ {
+ if a := t.iface().typeSet().types; a != nil && a != typ {
// If we have a union with a single entry, ignore
// any tilde because under(~t) == under(t).
if u, _ := a.(*Union); u != nil && u.NumTerms() == 1 {
return t.bound
}
-// Bound returns the underlying type of the type parameter's
-// constraint.
-// Deprecated for external use. Use Constraint instead.
-func (t *TypeParam) Bound() *Interface {
- if iface, _ := under(t.Constraint()).(*Interface); iface != nil {
- return iface
+// SetConstraint sets the type constraint for t.
+func (t *TypeParam) SetConstraint(bound Type) {
+ if bound == nil {
+ panic("types2.TypeParam.SetConstraint: bound must not be nil")
}
- return &emptyInterface
+ t.bound = bound
}
-// TODO(rfindley): document the SetBound methods.
-
-func (t *TypeParam) SetBound(bound Type) {
- if bound == nil {
- panic("internal error: bound must not be nil")
+// iface returns the constraint interface of t.
+func (t *TypeParam) iface() *Interface {
+ if iface, _ := under(t.Constraint()).(*Interface); iface != nil {
+ return iface
}
- t.bound = bound
+ return &emptyInterface
}
func (t *TypeParam) Underlying() Type { return t }
// Implementation
func (t *TypeParam) underIs(f func(Type) bool) bool {
- return t.Bound().typeSet().underIs(f)
+ return t.iface().typeSet().underIs(f)
}