1
0
mirror of https://github.com/golang/go synced 2024-11-26 07:27:59 -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:
Rob Findley 2021-02-11 11:54:46 -05:00 committed by Robert Findley
parent f5d0c653e6
commit 7b679617f3
3 changed files with 27 additions and 3 deletions

View File

@ -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}

View File

@ -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)
}

View File

@ -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 {