diff --git a/src/cmd/compile/internal/types2/api_test.go b/src/cmd/compile/internal/types2/api_test.go index 9d23b5b2a6..a06a073f97 100644 --- a/src/cmd/compile/internal/types2/api_test.go +++ b/src/cmd/compile/internal/types2/api_test.go @@ -337,6 +337,9 @@ func TestTypesInfo(t *testing.T) { // 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]`}, + + // issue 45096 + {`package issue45096; func _[T interface{ type int8, int16, int32 }](x T) { _ = x < 0 }`, `0`, `T₁`}, } for _, test := range tests { diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go index 7c1d4eae56..c65666e802 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -335,7 +335,9 @@ func (check *Checker) recordTypeAndValue(x syntax.Expr, mode operandMode, typ Ty } 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} diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index b89eb199eb..4cdec84604 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -628,7 +628,7 @@ func (check *Checker) convertUntyped(x *operand, target Type) { for _, t := range unpack(types) { x := *x // make a copy; convertUntypedInternal modifies x - check.convertUntypedInternal(&x, t) + check.convertUntypedInternal(&x, t, false) if x.mode == invalid { goto Error } @@ -639,7 +639,7 @@ func (check *Checker) convertUntyped(x *operand, target Type) { return } - check.convertUntypedInternal(x, target) + check.convertUntypedInternal(x, target, true) return Error: @@ -649,7 +649,7 @@ Error: } // 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)) if x.isNil() { @@ -669,7 +669,9 @@ func (check *Checker) convertUntypedInternal(x *operand, target Type) { return } // expression value may have been rounded - update if needed - check.updateExprVal(x.expr, x.val) + if update { + check.updateExprVal(x.expr, x.val) + } } else { // Non-constant untyped values may appear as the // result of comparisons (untyped bool), intermediate @@ -694,7 +696,7 @@ func (check *Checker) convertUntypedInternal(x *operand, target Type) { } case *Sum: t.is(func(t Type) bool { - check.convertUntypedInternal(x, t) + check.convertUntypedInternal(x, t, false) return x.mode != invalid }) case *Interface: @@ -712,7 +714,9 @@ func (check *Checker) convertUntypedInternal(x *operand, target Type) { OK: x.typ = target - check.updateExprType(x.expr, target, true) + if update { + check.updateExprType(x.expr, target, true) + } return Error: