]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/types2: use correct types when checking generic conversions
authorRobert Griesemer <gri@golang.org>
Wed, 20 Oct 2021 19:18:40 +0000 (12:18 -0700)
committerRobert Griesemer <gri@golang.org>
Wed, 20 Oct 2021 19:30:13 +0000 (19:30 +0000)
Iterate through the actual, possibly defined types of constraints
when type-checking generic conversions, not the underlying types.

For #47150.

Change-Id: Ia7af313bf46d6f6b0ad5292ff793b030b8e2d3d8
Reviewed-on: https://go-review.googlesource.com/c/go/+/357333
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/types2/conversions.go
src/cmd/compile/internal/types2/testdata/examples/conversions.go2

index 8cd74b8f9a342040b5bb91a4ce2f802694022c6a..112d7281884a3c47bd0e72e53b481aff0dfce59f 100644 (file)
@@ -98,21 +98,21 @@ func (x *operand) convertibleTo(check *Checker, T Type) bool {
        switch {
        case Vp != nil && Tp != nil:
                x := *x // don't modify outer x
-               return Vp.underIs(func(V Type) bool {
-                       x.typ = V
-                       return Tp.underIs(func(T Type) bool {
-                               return x.convertibleToImpl(check, T)
+               return Vp.is(func(V *term) bool {
+                       x.typ = V.typ
+                       return Tp.is(func(T *term) bool {
+                               return x.convertibleToImpl(check, T.typ)
                        })
                })
        case Vp != nil:
                x := *x // don't modify outer x
-               return Vp.underIs(func(V Type) bool {
-                       x.typ = V
+               return Vp.is(func(V *term) bool {
+                       x.typ = V.typ
                        return x.convertibleToImpl(check, T)
                })
        case Tp != nil:
-               return Tp.underIs(func(T Type) bool {
-                       return x.convertibleToImpl(check, T)
+               return Tp.is(func(T *term) bool {
+                       return x.convertibleToImpl(check, T.typ)
                })
        }
 
index 7e9e9745bbbe26842ec3dcb19242b2294c8bfab4..5c1b30a2b5e6146bc85cea438c0ca5975ac70b0d 100644 (file)
@@ -31,6 +31,20 @@ func _[X ~*Foo|~*Bar, T ~*Bar](x X) T { return T(x) }
 func _[X ~*Foo, T ~*Foo|~*Bar](x X) T { return T(x) }
 func _[X ~*Foo, T ~*Far](x X) T { return T(x /* ERROR cannot convert */ ) }
 
+// Verify that the defined types in constraints are considered for the rule above.
+
+type (
+       B int
+       C int
+       X0 *B
+       T0 *C
+)
+
+func _(x X0) T0 { return T0(x /* ERROR cannot convert */ ) } // non-generic reference
+func _[X X0, T T0](x X) T { return T(x /* ERROR cannot convert */ ) }
+func _[T T0](x X0) T { return T(x /* ERROR cannot convert */ ) }
+func _[X X0](x X) T0 { return T0(x /* ERROR cannot convert */ ) }
+
 // "x's type and T are both integer or floating point types"
 
 func _[X Integer, T Integer](x X) T { return T(x) }