mirror of
https://github.com/golang/go
synced 2024-11-23 00:30:07 -07:00
[dev.typeparams] go/types: conversions to type parameters are not constant
This is a port of CL 290471 to go/types. However, this change preserves the existing check for constant types in recordTypeAndValue, which uses is(..., isConstType) rather than the isConstType predicate. In types2, this code path is not hit with type parameters because convertUntyped walks the type list in order before calling updateExprType with the type parameter, at which point the expression type would have already been recorded as the first element of the type list -- probably something that should be corrected. Longer term, I believe we actually could allow const type parameters if the optype is a sum of constant types. Change-Id: Iaa91ffa740b5f08a5696bd96918a866bffd7aef6 Reviewed-on: https://go-review.googlesource.com/c/go/+/291323 Trust: Robert Findley <rfindley@google.com> Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Findley <rfindley@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
f5d0c653e6
commit
7b679617f3
@ -340,7 +340,9 @@ func (check *Checker) recordTypeAndValue(x ast.Expr, mode operandMode, typ Type,
|
||||
}
|
||||
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}
|
||||
|
@ -267,3 +267,20 @@ func _() {
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,12 @@ func isUntyped(typ Type) bool {
|
||||
}
|
||||
|
||||
func isOrdered(typ Type) bool { return is(typ, IsOrdered) }
|
||||
func isConstType(typ Type) bool { return is(typ, IsConstType) }
|
||||
|
||||
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 {
|
||||
|
Loading…
Reference in New Issue
Block a user