mirror of
https://github.com/golang/go
synced 2024-11-18 05:04:47 -07:00
cmd/compile/internal/types2: delay recording types of untyped operands when checking against type parameters
Don't eagerly record the target type for an untyped operand if the target type is just one of possibly many types in the type list of a type parameter. Instead, record expression type only after we checked that all types in the type list are ok. Also, update assertion in Checker.recordTypeAndValue since (currently), a type parameter is not considered a const type. We may change that, eventually. This is a temporary (but working) solution. Eventually we should copy the approach taken in go/types. Fixes #45096. Change-Id: Icf61ee893aca6ead32bfc45ee5831572e672357b Reviewed-on: https://go-review.googlesource.com/c/go/+/302755 Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com> TryBot-Result: Go Bot <gobot@golang.org>
This commit is contained in:
parent
2583c1b4df
commit
51e4bb236c
@ -337,6 +337,9 @@ func TestTypesInfo(t *testing.T) {
|
|||||||
|
|
||||||
// instantiated types must be sanitized
|
// instantiated types must be sanitized
|
||||||
{`package g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `g0.t[int]`},
|
{`package g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `g0.t[int]`},
|
||||||
|
|
||||||
|
// issue 45096
|
||||||
|
{`package issue45096; func _[T interface{ type int8, int16, int32 }](x T) { _ = x < 0 }`, `0`, `T₁`},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
@ -335,7 +335,9 @@ func (check *Checker) recordTypeAndValue(x syntax.Expr, mode operandMode, typ Ty
|
|||||||
}
|
}
|
||||||
if mode == constant_ {
|
if mode == constant_ {
|
||||||
assert(val != nil)
|
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 {
|
if m := check.Types; m != nil {
|
||||||
m[x] = TypeAndValue{mode, typ, val}
|
m[x] = TypeAndValue{mode, typ, val}
|
||||||
|
@ -628,7 +628,7 @@ func (check *Checker) convertUntyped(x *operand, target Type) {
|
|||||||
|
|
||||||
for _, t := range unpack(types) {
|
for _, t := range unpack(types) {
|
||||||
x := *x // make a copy; convertUntypedInternal modifies x
|
x := *x // make a copy; convertUntypedInternal modifies x
|
||||||
check.convertUntypedInternal(&x, t)
|
check.convertUntypedInternal(&x, t, false)
|
||||||
if x.mode == invalid {
|
if x.mode == invalid {
|
||||||
goto Error
|
goto Error
|
||||||
}
|
}
|
||||||
@ -639,7 +639,7 @@ func (check *Checker) convertUntyped(x *operand, target Type) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
check.convertUntypedInternal(x, target)
|
check.convertUntypedInternal(x, target, true)
|
||||||
return
|
return
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
@ -649,7 +649,7 @@ Error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// convertUntypedInternal should only be called by convertUntyped.
|
// convertUntypedInternal should only be called by convertUntyped.
|
||||||
func (check *Checker) convertUntypedInternal(x *operand, target Type) {
|
func (check *Checker) convertUntypedInternal(x *operand, target Type, update bool) {
|
||||||
assert(isTyped(target))
|
assert(isTyped(target))
|
||||||
|
|
||||||
if x.isNil() {
|
if x.isNil() {
|
||||||
@ -669,7 +669,9 @@ func (check *Checker) convertUntypedInternal(x *operand, target Type) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// expression value may have been rounded - update if needed
|
// expression value may have been rounded - update if needed
|
||||||
check.updateExprVal(x.expr, x.val)
|
if update {
|
||||||
|
check.updateExprVal(x.expr, x.val)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Non-constant untyped values may appear as the
|
// Non-constant untyped values may appear as the
|
||||||
// result of comparisons (untyped bool), intermediate
|
// result of comparisons (untyped bool), intermediate
|
||||||
@ -694,7 +696,7 @@ func (check *Checker) convertUntypedInternal(x *operand, target Type) {
|
|||||||
}
|
}
|
||||||
case *Sum:
|
case *Sum:
|
||||||
t.is(func(t Type) bool {
|
t.is(func(t Type) bool {
|
||||||
check.convertUntypedInternal(x, t)
|
check.convertUntypedInternal(x, t, false)
|
||||||
return x.mode != invalid
|
return x.mode != invalid
|
||||||
})
|
})
|
||||||
case *Interface:
|
case *Interface:
|
||||||
@ -712,7 +714,9 @@ func (check *Checker) convertUntypedInternal(x *operand, target Type) {
|
|||||||
|
|
||||||
OK:
|
OK:
|
||||||
x.typ = target
|
x.typ = target
|
||||||
check.updateExprType(x.expr, target, true)
|
if update {
|
||||||
|
check.updateExprType(x.expr, target, true)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
|
|
||||||
Error:
|
Error:
|
||||||
|
Loading…
Reference in New Issue
Block a user