syntax.Shl: "shift",
}
-// 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 {
- typ = Unalias(typ)
- if tpar, _ := typ.(*TypeParam); tpar != nil {
- return tpar.underIs(f)
- }
- return f(under(typ))
-}
-
func (check *Checker) unary(x *operand, e *syntax.Operation) {
check.expr(nil, x, e.X)
if x.mode == invalid {
func (t *TypeParam) underIs(f func(Type) bool) bool {
return t.iface().typeSet().underIs(f)
}
+
+// typeset is an iterator over the (type/underlying type) pairs of the
+// specific type terms of t's constraint.
+// If there are no specific terms, typeset calls yield with (nil, nil).
+// In any case, typeset is guaranteed to call yield at least once.
+func (t *TypeParam) typeset(yield func(t, u Type) bool) {
+ t.iface().typeSet().typeset(yield)
+}
comparable bool // invariant: !comparable || terms.isAll()
}
-// IsEmpty reports whether type set s is the empty set.
+// IsEmpty reports whether s is the empty set.
func (s *_TypeSet) IsEmpty() bool { return s.terms.isEmpty() }
-// IsAll reports whether type set s is the set of all types (corresponding to the empty interface).
+// IsAll reports whether s is the set of all types (corresponding to the empty interface).
func (s *_TypeSet) IsAll() bool { return s.IsMethodSet() && len(s.methods) == 0 }
// IsMethodSet reports whether the interface t is fully described by its method set.
// NumMethods returns the number of methods available.
func (s *_TypeSet) NumMethods() int { return len(s.methods) }
-// Method returns the i'th method of type set s for 0 <= i < s.NumMethods().
+// Method returns the i'th method of s for 0 <= i < s.NumMethods().
// The methods are ordered by their unique ID.
func (s *_TypeSet) Method(i int) *Func { return s.methods[i] }
// ----------------------------------------------------------------------------
// Implementation
-// hasTerms reports whether the type set has specific type terms.
+// hasTerms reports whether s has specific type terms.
func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll() }
// subsetOf reports whether s1 ⊆ s2.
func (s1 *_TypeSet) subsetOf(s2 *_TypeSet) bool { return s1.terms.subsetOf(s2.terms) }
-// TODO(gri) TypeSet.is and TypeSet.underIs should probably also go into termlist.go
+// typeset is an iterator over the (type/underlying type) pairs in s.
+// If s has no specific terms, typeset calls yield with (nil, nil).
+// In any case, typeset is guaranteed to call yield at least once.
+func (s *_TypeSet) typeset(yield func(t, u Type) bool) {
+ if !s.hasTerms() {
+ yield(nil, nil)
+ return
+ }
+
+ for _, t := range s.terms {
+ assert(t.typ != nil)
+ // Unalias(x) == under(x) for ~x terms
+ u := Unalias(t.typ)
+ if !t.tilde {
+ u = under(u)
+ }
+ if debug {
+ assert(Identical(u, under(u)))
+ }
+ if !yield(t.typ, u) {
+ break
+ }
+ }
+}
// is calls f with the specific type terms of s and reports whether
// all calls to f returned true. If there are no specific terms, is
return t.Underlying()
}
+// 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 {
+ typ = Unalias(typ)
+ if tpar, _ := typ.(*TypeParam); tpar != nil {
+ return tpar.underIs(f)
+ }
+ return f(under(typ))
+}
+
+// typeset is an iterator over the (type/underlying type) pairs of the
+// specific type terms of the type set implied by t.
+// If t is a type parameter, the implied type set is the type set of t's constraint.
+// In that case, if there are no specific terms, typeset calls yield with (nil, nil).
+// If t is not a type parameter, the implied type set consists of just t.
+// In any case, typeset is guaranteed to call yield at least once.
+func typeset(t Type, yield func(t, u Type) bool) {
+ if p, _ := Unalias(t).(*TypeParam); p != nil {
+ p.typeset(yield)
+ return
+ }
+ yield(t, under(t))
+}
+
// If t is not a type parameter, coreType returns the underlying type.
// If t is a type parameter, coreType returns the single underlying
// type of all types in its type set if it exists, or nil otherwise. If the
token.SHL: "shift",
}
-// 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 {
- typ = Unalias(typ)
- if tpar, _ := typ.(*TypeParam); tpar != nil {
- return tpar.underIs(f)
- }
- return f(under(typ))
-}
-
// The unary expression e may be nil. It's passed in for better error messages only.
func (check *Checker) unary(x *operand, e *ast.UnaryExpr) {
check.expr(nil, x, e.X)
func (t *TypeParam) underIs(f func(Type) bool) bool {
return t.iface().typeSet().underIs(f)
}
+
+// typeset is an iterator over the (type/underlying type) pairs of the
+// specific type terms of t's constraint.
+// If there are no specific terms, typeset calls yield with (nil, nil).
+// In any case, typeset is guaranteed to call yield at least once.
+func (t *TypeParam) typeset(yield func(t, u Type) bool) {
+ t.iface().typeSet().typeset(yield)
+}
comparable bool // invariant: !comparable || terms.isAll()
}
-// IsEmpty reports whether type set s is the empty set.
+// IsEmpty reports whether s is the empty set.
func (s *_TypeSet) IsEmpty() bool { return s.terms.isEmpty() }
-// IsAll reports whether type set s is the set of all types (corresponding to the empty interface).
+// IsAll reports whether s is the set of all types (corresponding to the empty interface).
func (s *_TypeSet) IsAll() bool { return s.IsMethodSet() && len(s.methods) == 0 }
// IsMethodSet reports whether the interface t is fully described by its method set.
// NumMethods returns the number of methods available.
func (s *_TypeSet) NumMethods() int { return len(s.methods) }
-// Method returns the i'th method of type set s for 0 <= i < s.NumMethods().
+// Method returns the i'th method of s for 0 <= i < s.NumMethods().
// The methods are ordered by their unique ID.
func (s *_TypeSet) Method(i int) *Func { return s.methods[i] }
// ----------------------------------------------------------------------------
// Implementation
-// hasTerms reports whether the type set has specific type terms.
+// hasTerms reports whether s has specific type terms.
func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll() }
// subsetOf reports whether s1 ⊆ s2.
func (s1 *_TypeSet) subsetOf(s2 *_TypeSet) bool { return s1.terms.subsetOf(s2.terms) }
-// TODO(gri) TypeSet.is and TypeSet.underIs should probably also go into termlist.go
+// typeset is an iterator over the (type/underlying type) pairs in s.
+// If s has no specific terms, typeset calls yield with (nil, nil).
+// In any case, typeset is guaranteed to call yield at least once.
+func (s *_TypeSet) typeset(yield func(t, u Type) bool) {
+ if !s.hasTerms() {
+ yield(nil, nil)
+ return
+ }
+
+ for _, t := range s.terms {
+ assert(t.typ != nil)
+ // Unalias(x) == under(x) for ~x terms
+ u := Unalias(t.typ)
+ if !t.tilde {
+ u = under(u)
+ }
+ if debug {
+ assert(Identical(u, under(u)))
+ }
+ if !yield(t.typ, u) {
+ break
+ }
+ }
+}
// is calls f with the specific type terms of s and reports whether
// all calls to f returned true. If there are no specific terms, is
return t.Underlying()
}
+// 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 {
+ typ = Unalias(typ)
+ if tpar, _ := typ.(*TypeParam); tpar != nil {
+ return tpar.underIs(f)
+ }
+ return f(under(typ))
+}
+
+// typeset is an iterator over the (type/underlying type) pairs of the
+// specific type terms of the type set implied by t.
+// If t is a type parameter, the implied type set is the type set of t's constraint.
+// In that case, if there are no specific terms, typeset calls yield with (nil, nil).
+// If t is not a type parameter, the implied type set consists of just t.
+// In any case, typeset is guaranteed to call yield at least once.
+func typeset(t Type, yield func(t, u Type) bool) {
+ if p, _ := Unalias(t).(*TypeParam); p != nil {
+ p.typeset(yield)
+ return
+ }
+ yield(t, under(t))
+}
+
// If t is not a type parameter, coreType returns the underlying type.
// If t is a type parameter, coreType returns the single underlying
// type of all types in its type set if it exists, or nil otherwise. If the