}
if mode == constant_ {
assert(val != nil)
- assert(typ == Typ[Invalid] || isConstType(typ))
+ // We check is(typ, IsConstType) here as constant expressions may be
+ // recorded as type parameters.
+ assert(typ == Typ[Invalid] || is(typ, IsConstType))
}
if m := check.Types; m != nil {
m[x] = TypeAndValue{mode, typ, val}
var _ comparable /* ERROR comparable */
var _ C /* ERROR comparable */
}
+
+// Type parameters are never const types, i.e., it's
+// not possible to declare a constant of type parameter type.
+// (If a type list contains just a single const type, we could
+// allow it, but such type lists don't make much sense in the
+// first place.)
+func _[T interface { type int, float64 }]() {
+ // not valid
+ const _ = T /* ERROR not constant */ (0)
+ const _ T /* ERROR invalid constant type T */ = 1
+
+ // valid
+ var _ = T(0)
+ var _ T = 1
+ _ = T(0)
+}
+
return !isTyped(typ)
}
-func isOrdered(typ Type) bool { return is(typ, IsOrdered) }
-func isConstType(typ Type) bool { return is(typ, IsConstType) }
+func isOrdered(typ Type) bool { return is(typ, IsOrdered) }
+
+func isConstType(typ Type) bool {
+ // Type parameters are never const types.
+ t, _ := under(typ).(*Basic)
+ return t != nil && t.info&IsConstType != 0
+}
// IsInterface reports whether typ is an interface type.
func IsInterface(typ Type) bool {