return
}
+// adjCoreType returns the core type of tpar unless the
+// type parameter embeds a single, possibly named type,
+// in which case it returns that single type instead.
+// (The core type is always the underlying type of that
+// single type.)
func adjCoreType(tpar *TypeParam) Type {
- // If the type parameter embeds a single, possibly named
- // type, use that one instead of the core type (which is
- // always the underlying type of that single type).
- if single := tpar.singleType(); single != nil {
+ var single *term
+ if tpar.is(func(t *term) bool {
+ if single == nil && t != nil {
+ single = t
+ return true
+ }
+ return false // zero or more than one terms
+ }) {
if debug {
- assert(under(single) == coreType(tpar))
+ assert(under(single.typ) == coreType(tpar))
}
- return single
+ return single.typ
}
return coreType(tpar)
}
return rl
}
-// If the type set represented by xl is specified by a single (non-𝓤) term,
-// singleType returns that type. Otherwise it returns nil.
-func (xl termlist) singleType() Type {
- if nl := xl.norm(); len(nl) == 1 {
- return nl[0].typ // if nl.isAll() then typ is nil, which is ok
- }
- return nil
-}
-
// union returns the union xl ∪ yl.
func (xl termlist) union(yl termlist) termlist {
return append(xl, yl...).norm()
}
}
-func TestTermlistSingleType(t *testing.T) {
- // helper to deal with nil types
- tstring := func(typ Type) string {
- if typ == nil {
- return "nil"
- }
- return typ.String()
- }
-
- for test, want := range map[string]string{
- "∅": "nil",
- "𝓤": "nil",
- "int": "int",
- "myInt": "myInt",
- "~int": "int",
- "~int ∪ string": "nil",
- "~int ∪ myInt": "int",
- "∅ ∪ int": "int",
- "∅ ∪ ~int": "int",
- "∅ ∪ ~int ∪ string": "nil",
- } {
- xl := maketl(test)
- got := tstring(xl.singleType())
- if got != want {
- t.Errorf("(%v).singleType() == %v; want %v", test, got, want)
- }
- }
-}
-
func TestTermlistUnion(t *testing.T) {
for _, test := range []struct {
xl, yl, want string
return ityp
}
-// singleType returns the single type of the type parameter constraint; or nil.
-func (t *TypeParam) singleType() Type {
- return t.iface().typeSet().singleType()
-}
-
-// hasTerms reports whether the type parameter constraint has specific type terms.
-func (t *TypeParam) hasTerms() bool {
- return t.iface().typeSet().hasTerms()
-}
-
// is calls f with the specific type terms of t's constraint and reports whether
// all calls to f returned true. If there are no specific terms, is
// returns the result of f(nil).
// hasTerms reports whether the type set has specific type terms.
func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll() }
-// singleType returns the single type in s if there is exactly one; otherwise the result is nil.
-func (s *_TypeSet) singleType() Type { return s.terms.singleType() }
-
// subsetOf reports whether s1 ⊆ s2.
func (s1 *_TypeSet) subsetOf(s2 *_TypeSet) bool { return s1.terms.subsetOf(s2.terms) }
return
}
+// adjCoreType returns the core type of tpar unless the
+// type parameter embeds a single, possibly named type,
+// in which case it returns that single type instead.
+// (The core type is always the underlying type of that
+// single type.)
func adjCoreType(tpar *TypeParam) Type {
- // If the type parameter embeds a single, possibly named
- // type, use that one instead of the core type (which is
- // always the underlying type of that single type).
- if single := tpar.singleType(); single != nil {
+ var single *term
+ if tpar.is(func(t *term) bool {
+ if single == nil && t != nil {
+ single = t
+ return true
+ }
+ return false // zero or more than one terms
+ }) {
if debug {
- assert(under(single) == coreType(tpar))
+ assert(under(single.typ) == coreType(tpar))
}
- return single
+ return single.typ
}
return coreType(tpar)
}
return rl
}
-// If the type set represented by xl is specified by a single (non-𝓤) term,
-// singleType returns that type. Otherwise it returns nil.
-func (xl termlist) singleType() Type {
- if nl := xl.norm(); len(nl) == 1 {
- return nl[0].typ // if nl.isAll() then typ is nil, which is ok
- }
- return nil
-}
-
// union returns the union xl ∪ yl.
func (xl termlist) union(yl termlist) termlist {
return append(xl, yl...).norm()
}
}
-func TestTermlistSingleType(t *testing.T) {
- // helper to deal with nil types
- tstring := func(typ Type) string {
- if typ == nil {
- return "nil"
- }
- return typ.String()
- }
-
- for test, want := range map[string]string{
- "∅": "nil",
- "𝓤": "nil",
- "int": "int",
- "myInt": "myInt",
- "~int": "int",
- "~int ∪ string": "nil",
- "~int ∪ myInt": "int",
- "∅ ∪ int": "int",
- "∅ ∪ ~int": "int",
- "∅ ∪ ~int ∪ string": "nil",
- } {
- xl := maketl(test)
- got := tstring(xl.singleType())
- if got != want {
- t.Errorf("(%v).singleType() == %v; want %v", test, got, want)
- }
- }
-}
-
func TestTermlistUnion(t *testing.T) {
for _, test := range []struct {
xl, yl, want string
return ityp
}
-// singleType returns the single type of the type parameter constraint; or nil.
-func (t *TypeParam) singleType() Type {
- return t.iface().typeSet().singleType()
-}
-
-// hasTerms reports whether the type parameter constraint has specific type terms.
-func (t *TypeParam) hasTerms() bool {
- return t.iface().typeSet().hasTerms()
-}
-
// is calls f with the specific type terms of t's constraint and reports whether
// all calls to f returned true. If there are no specific terms, is
// returns the result of f(nil).
// hasTerms reports whether the type set has specific type terms.
func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll() }
-// singleType returns the single type in s if there is exactly one; otherwise the result is nil.
-func (s *_TypeSet) singleType() Type { return s.terms.singleType() }
-
// subsetOf reports whether s1 ⊆ s2.
func (s1 *_TypeSet) subsetOf(s2 *_TypeSet) bool { return s1.terms.subsetOf(s2.terms) }