]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/types2: delay recording types of untyped operands when checking...
authorRobert Griesemer <gri@golang.org>
Wed, 17 Mar 2021 23:59:47 +0000 (16:59 -0700)
committerRobert Griesemer <gri@golang.org>
Thu, 18 Mar 2021 00:23:25 +0000 (00:23 +0000)
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>

src/cmd/compile/internal/types2/api_test.go
src/cmd/compile/internal/types2/check.go
src/cmd/compile/internal/types2/expr.go

index 9d23b5b2a6cea63cd766a1ea530bf53bd3746d25..a06a073f9768b59672b42758015f953e22408dfb 100644 (file)
@@ -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 {
index 7c1d4eae56706a492e4253743d3f9a1ec729079c..c65666e8026caf963426eb1653decf336248ab0c 100644 (file)
@@ -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}
index b89eb199eb2ce06e04e3d5c6d31398da8b8fde59..4cdec84604bbde78c55e9855a8e5638f2aa900dc 100644 (file)
@@ -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: