}
xs := make([]*types2.TypeParam, n)
for i := range xs {
- typ := r.typ()
- xs[i] = types2.AsTypeParam(typ)
+ xs[i] = r.typ().(*types2.TypeParam)
}
return xs
}
// the argument types must be of floating-point type
// (applyTypeFunc never calls f with a type parameter)
f := func(typ Type) Type {
- assert(asTypeParam(typ) == nil)
+ assert(!isTypeParam(typ))
if t, _ := under(typ).(*Basic); t != nil {
switch t.kind {
case Float32:
// the argument must be of complex type
// (applyTypeFunc never calls f with a type parameter)
f := func(typ Type) Type {
- assert(asTypeParam(typ) == nil)
+ assert(!isTypeParam(typ))
if t, _ := under(typ).(*Basic); t != nil {
switch t.kind {
case Complex64:
// applyTypeFunc returns nil.
// If x is not a type parameter, the result is f(x).
func (check *Checker) applyTypeFunc(f func(Type) Type, x Type) Type {
- if tp := asTypeParam(x); tp != nil {
+ if tp, _ := x.(*TypeParam); tp != nil {
// Test if t satisfies the requirements for the argument
// type and collect possible result types at the same time.
var terms []*Term
check.errorf(e.Sel, "cannot call pointer method %s on %s", sel, x.typ)
default:
var why string
- if tpar := asTypeParam(x.typ); tpar != nil {
+ if tpar, _ := x.typ.(*TypeParam); tpar != nil {
// Type parameter bounds don't specify fields, so don't mention "field".
if tname := tpar.iface().obj; tname != nil {
why = check.sprintf("interface %s has no method %s", tname.name, sel)
return u
}
-// If t is a type parameter, AsTypeParam returns that type, otherwise it returns nil.
-func AsTypeParam(t Type) *TypeParam {
- u, _ := t.Underlying().(*TypeParam)
- return u
-}
-
// If typ is a type parameter, structuralType returns the single underlying
// type of all types in the corresponding type constraint if it exists, or
// nil otherwise. If the type set contains only unrestricted and restricted
// If T's type set is empty, or if it doesn't
// have specific types, constant x cannot be
// converted.
- ok = under(T).(*TypeParam).underIs(func(u Type) bool {
+ ok = T.(*TypeParam).underIs(func(u Type) bool {
// t is nil if there are no specific type terms
if u == nil {
cause = check.sprintf("%s does not contain specific types", T)
}
// optimization: if we don't have type parameters, we're done
- Vp, _ := Vu.(*TypeParam)
- Tp, _ := Tu.(*TypeParam)
+ Vp, _ := V.(*TypeParam)
+ Tp, _ := T.(*TypeParam)
if Vp == nil && Tp == nil {
return false
}
}
// Disallow a lone type parameter as the RHS of a type declaration (issue #45639).
- // We can look directly at named.underlying because even if it is still a *Named
- // type (underlying not fully resolved yet) it cannot become a type parameter due
- // to this very restriction.
- if tpar, _ := named.underlying.(*TypeParam); tpar != nil {
+ // We don't need this restriction anymore if we make the underlying type of a type
+ // parameter its constraint interface: if the RHS is a lone type parameter, we will
+ // use its underlying type (like we do for any RHS in a type declaration), and its
+ // underlying type is an interface and the type declaration is well defined.
+ if isTypeParam(rhs) {
check.error(tdecl.Type, "cannot use a type parameter as RHS in type declaration")
named.underlying = Typ[Invalid]
}
check.later(func() {
for i, bound := range bounds {
- if _, ok := under(bound).(*TypeParam); ok {
+ if isTypeParam(bound) {
check.error(posers[i], "cannot use a type parameter as constraint")
}
}
// 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 {
- u := under(typ)
- if tpar, _ := u.(*TypeParam); tpar != nil {
+ if tpar, _ := typ.(*TypeParam); tpar != nil {
return tpar.underIs(f)
}
- return f(u)
+ return f(under(typ))
}
func (check *Checker) unary(x *operand, e *syntax.Operation) {
// A type argument that is a type parameter with an empty type set satisfies any constraint.
// (The empty set is a subset of any set.)
- if targ := asTypeParam(targ); targ != nil && targ.iface().typeSet().IsEmpty() {
+ if targ, _ := targ.(*TypeParam); targ != nil && targ.iface().typeSet().IsEmpty() {
return nil
}
// 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.iface().typeSet().IsAll() {
+ if tpar, _ := targ.(*TypeParam); tpar != nil && tpar.iface().typeSet().IsAll() {
return errorf("%s has no constraints", targ)
}
return errorf("%s does not satisfy comparable", targ)
// If the type argument is a pointer to a type parameter, the type argument's
// method set is empty.
// TODO(gri) is this what we want? (spec question)
- if base, isPtr := deref(targ); isPtr && asTypeParam(base) != nil {
+ if base, isPtr := deref(targ); isPtr && isTypeParam(base) {
return errorf("%s has no methods", targ)
}
if m, wrong := check.missingMethod(targ, iface, true); m != nil {
// If targ is itself a type parameter, each of its possible types must be in the set
// of iface types (i.e., the targ type set must be a subset of the iface type set).
// Type arguments with empty type sets were already excluded above.
- if targ := asTypeParam(targ); targ != nil {
+ if targ, _ := targ.(*TypeParam); targ != nil {
targBound := targ.iface()
if !targBound.typeSet().subsetOf(iface.typeSet()) {
// TODO(gri) report which type is missing
continue // we can't have a matching field or interface method
}
- // continue with underlying type, but only if it's not a type parameter
- // TODO(gri) is this what we want to do for type parameters? (spec question)
+ // continue with underlying type
typ = named.under()
- if asTypeParam(typ) != nil {
- continue
- }
}
tpar = nil
}
buf.WriteString(intro)
WriteType(&buf, x.typ, qf)
- if tpar := asTypeParam(x.typ); tpar != nil {
+ if tpar, _ := x.typ.(*TypeParam); tpar != nil {
buf.WriteString(" constrained by ")
WriteType(&buf, tpar.bound, qf) // do not compute interface type sets here
}
Vu := under(V)
Tu := under(T)
- Vp, _ := Vu.(*TypeParam)
- Tp, _ := Tu.(*TypeParam)
+ Vp, _ := V.(*TypeParam)
+ Tp, _ := T.(*TypeParam)
// x is an untyped value representable by a value of type T.
if isUntyped(Vu) {
// isTypeParam reports whether t is a type parameter.
func isTypeParam(t Type) bool {
- _, ok := under(t).(*TypeParam)
+ _, ok := t.(*TypeParam)
return ok
}
}
return e
}
-
-// If t is a type parameter, asTypeParam returns that type, otherwise it returns nil.
-func asTypeParam(t Type) *TypeParam {
- u, _ := under(t).(*TypeParam)
- return u
-}
continue // ignore invalid unions
}
terms = tset.terms
- case *TypeParam:
- // Embedding stand-alone type parameters is not permitted.
- // Union parsing reports a (delayed) error, so we can ignore this entry.
- continue
default:
if u == Typ[Invalid] {
continue
switch u := under(t.typ).(type) {
case *Interface:
terms = computeInterfaceTypeSet(check, pos, u).terms
- case *TypeParam:
- // A stand-alone type parameters is not permitted as union term.
- // Union parsing reports a (delayed) error, so we can ignore this entry.
- continue
default:
if t.typ == Typ[Invalid] {
continue
check.later(func() {
if !Comparable(typ.key) {
var why string
- if asTypeParam(typ.key) != nil {
+ if isTypeParam(typ.key) {
why = " (missing comparable constraint)"
}
check.errorf(e.Key, "invalid map key type %s%s", typ.key, why)
}
typ = check.typ(x)
// Embedding stand-alone type parameters is not permitted (issue #47127).
- // Do this check later because it requires computation of the underlying type (see also issue #46461).
- // Note: If an underlying type cannot be a type parameter, the call to
- // under() will not be needed and then we don't need to delay this
- // check to later and could return Typ[Invalid] instead.
- check.later(func() {
- if _, ok := under(typ).(*TypeParam); ok {
- check.error(x, "cannot embed a type parameter")
- }
- })
+ // We don't need this restriction anymore if we make the underlying type of a type
+ // parameter its constraint interface: if we embed a lone type parameter, we will
+ // simply use its underlying type (like we do for other named, embedded interfaces),
+ // and since the underlying type is an interface the embedding is well defined.
+ if isTypeParam(typ) {
+ check.error(x, "cannot embed a type parameter")
+ typ = Typ[Invalid]
+ }
return
}