]> Cypherpunks.ru repositories - gostls13.git/commitdiff
go/types, types2: more concise error if conversion fails due to integer overflow
authorRobert Griesemer <gri@golang.org>
Mon, 30 Oct 2023 20:51:04 +0000 (13:51 -0700)
committerGopher Robot <gobot@golang.org>
Tue, 31 Oct 2023 16:11:16 +0000 (16:11 +0000)
This change brings the error message for this case back in line
with the pre-Go1.18 error message.

Fixes #63563.

Change-Id: I3c6587d420907b34ee8a5f295ecb231e9f008380
Reviewed-on: https://go-review.googlesource.com/c/go/+/538058
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Run-TryBot: Robert Griesemer <gri@google.com>
TryBot-Bypass: Robert Griesemer <gri@google.com>
Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
src/cmd/compile/internal/types2/conversions.go
src/go/types/conversions.go
src/internal/types/testdata/check/const1.go
src/internal/types/testdata/check/constdecl.go
src/internal/types/testdata/check/expr0.go
src/internal/types/testdata/fixedbugs/issue63563.go [new file with mode: 0644]

index ef0094dc7090bc87996b7c8e06981f3c3466464f..8027092c6cd6d2a4595834a982b26bf6d6fa5647 100644 (file)
@@ -42,6 +42,14 @@ func (check *Checker) conversion(x *operand, T Type) {
        case constArg && isConstType(T):
                // constant conversion
                ok = constConvertibleTo(T, &x.val)
+               // A conversion from an integer constant to an integer type
+               // can only fail if there's overflow. Give a concise error.
+               // (go.dev/issue/63563)
+               if !ok && isInteger(x.typ) && isInteger(T) {
+                       check.errorf(x, InvalidConversion, "constant %s overflows %s", x.val, T)
+                       x.mode = invalid
+                       return
+               }
        case constArg && isTypeParam(T):
                // x is convertible to T if it is convertible
                // to each specific type in the type set of T.
@@ -58,7 +66,12 @@ func (check *Checker) conversion(x *operand, T Type) {
                                return true
                        }
                        if !constConvertibleTo(u, nil) {
-                               cause = check.sprintf("cannot convert %s to type %s (in %s)", x, u, T)
+                               if isInteger(x.typ) && isInteger(u) {
+                                       // see comment above on constant conversion
+                                       cause = check.sprintf("constant %s overflows %s (in %s)", x.val, u, T)
+                               } else {
+                                       cause = check.sprintf("cannot convert %s to type %s (in %s)", x, u, T)
+                               }
                                return false
                        }
                        return true
index 2fa3f92837c16cb65f437ac997eef1344135b562..2be17eeb1261b2146bd698ec7743df5272b0a289 100644 (file)
@@ -42,6 +42,14 @@ func (check *Checker) conversion(x *operand, T Type) {
        case constArg && isConstType(T):
                // constant conversion
                ok = constConvertibleTo(T, &x.val)
+               // A conversion from an integer constant to an integer type
+               // can only fail if there's overflow. Give a concise error.
+               // (go.dev/issue/63563)
+               if !ok && isInteger(x.typ) && isInteger(T) {
+                       check.errorf(x, InvalidConversion, "constant %s overflows %s", x.val, T)
+                       x.mode = invalid
+                       return
+               }
        case constArg && isTypeParam(T):
                // x is convertible to T if it is convertible
                // to each specific type in the type set of T.
@@ -58,7 +66,12 @@ func (check *Checker) conversion(x *operand, T Type) {
                                return true
                        }
                        if !constConvertibleTo(u, nil) {
-                               cause = check.sprintf("cannot convert %s to type %s (in %s)", x, u, T)
+                               if isInteger(x.typ) && isInteger(u) {
+                                       // see comment above on constant conversion
+                                       cause = check.sprintf("constant %s overflows %s (in %s)", x.val, u, T)
+                               } else {
+                                       cause = check.sprintf("cannot convert %s to type %s (in %s)", x, u, T)
+                               }
                                return false
                        }
                        return true
index c9128017cf72518f73adc4a535cc89f2418541db..80dde1af4c977224b8bb778525c1d12040f8a79c 100644 (file)
@@ -75,10 +75,10 @@ const (
        _ int8 = maxInt8 /* ERROR "overflows" */ + 1
        _ int8 = smallestFloat64 /* ERROR "truncated" */
 
-       _ = int8(minInt8 /* ERROR "cannot convert" */ - 1)
+       _ = int8(minInt8 /* ERROR "overflows" */ - 1)
        _ = int8(minInt8)
        _ = int8(maxInt8)
-       _ = int8(maxInt8 /* ERROR "cannot convert" */ + 1)
+       _ = int8(maxInt8 /* ERROR "overflows" */ + 1)
        _ = int8(smallestFloat64 /* ERROR "cannot convert" */)
 )
 
@@ -89,10 +89,10 @@ const (
        _ int16 = maxInt16 /* ERROR "overflows" */ + 1
        _ int16 = smallestFloat64 /* ERROR "truncated" */
 
-       _ = int16(minInt16 /* ERROR "cannot convert" */ - 1)
+       _ = int16(minInt16 /* ERROR "overflows" */ - 1)
        _ = int16(minInt16)
        _ = int16(maxInt16)
-       _ = int16(maxInt16 /* ERROR "cannot convert" */ + 1)
+       _ = int16(maxInt16 /* ERROR "overflows" */ + 1)
        _ = int16(smallestFloat64 /* ERROR "cannot convert" */)
 )
 
@@ -103,10 +103,10 @@ const (
        _ int32 = maxInt32 /* ERROR "overflows" */ + 1
        _ int32 = smallestFloat64 /* ERROR "truncated" */
 
-       _ = int32(minInt32 /* ERROR "cannot convert" */ - 1)
+       _ = int32(minInt32 /* ERROR "overflows" */ - 1)
        _ = int32(minInt32)
        _ = int32(maxInt32)
-       _ = int32(maxInt32 /* ERROR "cannot convert" */ + 1)
+       _ = int32(maxInt32 /* ERROR "overflows" */ + 1)
        _ = int32(smallestFloat64 /* ERROR "cannot convert" */)
 )
 
@@ -117,10 +117,10 @@ const (
        _ int64 = maxInt64 /* ERROR "overflows" */ + 1
        _ int64 = smallestFloat64 /* ERROR "truncated" */
 
-       _ = int64(minInt64 /* ERROR "cannot convert" */ - 1)
+       _ = int64(minInt64 /* ERROR "overflows" */ - 1)
        _ = int64(minInt64)
        _ = int64(maxInt64)
-       _ = int64(maxInt64 /* ERROR "cannot convert" */ + 1)
+       _ = int64(maxInt64 /* ERROR "overflows" */ + 1)
        _ = int64(smallestFloat64 /* ERROR "cannot convert" */)
 )
 
@@ -131,10 +131,10 @@ const (
        _ int = maxInt /* ERROR "overflows" */ + 1
        _ int = smallestFloat64 /* ERROR "truncated" */
 
-       _ = int(minInt /* ERROR "cannot convert" */ - 1)
+       _ = int(minInt /* ERROR "overflows" */ - 1)
        _ = int(minInt)
        _ = int(maxInt)
-       _ = int(maxInt /* ERROR "cannot convert" */ + 1)
+       _ = int(maxInt /* ERROR "overflows" */ + 1)
        _ = int(smallestFloat64 /* ERROR "cannot convert" */)
 )
 
@@ -145,10 +145,10 @@ const (
        _ uint8 = maxUint8 /* ERROR "overflows" */ + 1
        _ uint8 = smallestFloat64 /* ERROR "truncated" */
 
-       _ = uint8(0 /* ERROR "cannot convert" */ - 1)
+       _ = uint8(0 /* ERROR "overflows" */ - 1)
        _ = uint8(0)
        _ = uint8(maxUint8)
-       _ = uint8(maxUint8 /* ERROR "cannot convert" */ + 1)
+       _ = uint8(maxUint8 /* ERROR "overflows" */ + 1)
        _ = uint8(smallestFloat64 /* ERROR "cannot convert" */)
 )
 
@@ -159,10 +159,10 @@ const (
        _ uint16 = maxUint16 /* ERROR "overflows" */ + 1
        _ uint16 = smallestFloat64 /* ERROR "truncated" */
 
-       _ = uint16(0 /* ERROR "cannot convert" */ - 1)
+       _ = uint16(0 /* ERROR "overflows" */ - 1)
        _ = uint16(0)
        _ = uint16(maxUint16)
-       _ = uint16(maxUint16 /* ERROR "cannot convert" */ + 1)
+       _ = uint16(maxUint16 /* ERROR "overflows" */ + 1)
        _ = uint16(smallestFloat64 /* ERROR "cannot convert" */)
 )
 
@@ -173,10 +173,10 @@ const (
        _ uint32 = maxUint32 /* ERROR "overflows" */ + 1
        _ uint32 = smallestFloat64 /* ERROR "truncated" */
 
-       _ = uint32(0 /* ERROR "cannot convert" */ - 1)
+       _ = uint32(0 /* ERROR "overflows" */ - 1)
        _ = uint32(0)
        _ = uint32(maxUint32)
-       _ = uint32(maxUint32 /* ERROR "cannot convert" */ + 1)
+       _ = uint32(maxUint32 /* ERROR "overflows" */ + 1)
        _ = uint32(smallestFloat64 /* ERROR "cannot convert" */)
 )
 
@@ -187,10 +187,10 @@ const (
        _ uint64 = maxUint64 /* ERROR "overflows" */ + 1
        _ uint64 = smallestFloat64 /* ERROR "truncated" */
 
-       _ = uint64(0 /* ERROR "cannot convert" */ - 1)
+       _ = uint64(0 /* ERROR "overflows" */ - 1)
        _ = uint64(0)
        _ = uint64(maxUint64)
-       _ = uint64(maxUint64 /* ERROR "cannot convert" */ + 1)
+       _ = uint64(maxUint64 /* ERROR "overflows" */ + 1)
        _ = uint64(smallestFloat64 /* ERROR "cannot convert" */)
 )
 
@@ -201,10 +201,10 @@ const (
        _ uint = maxUint /* ERROR "overflows" */ + 1
        _ uint = smallestFloat64 /* ERROR "truncated" */
 
-       _ = uint(0 /* ERROR "cannot convert" */ - 1)
+       _ = uint(0 /* ERROR "overflows" */ - 1)
        _ = uint(0)
        _ = uint(maxUint)
-       _ = uint(maxUint /* ERROR "cannot convert" */ + 1)
+       _ = uint(maxUint /* ERROR "overflows" */ + 1)
        _ = uint(smallestFloat64 /* ERROR "cannot convert" */)
 )
 
@@ -215,10 +215,10 @@ const (
        _ uintptr = maxUintptr /* ERROR "overflows" */ + 1
        _ uintptr = smallestFloat64 /* ERROR "truncated" */
 
-       _ = uintptr(0 /* ERROR "cannot convert" */ - 1)
+       _ = uintptr(0 /* ERROR "overflows" */ - 1)
        _ = uintptr(0)
        _ = uintptr(maxUintptr)
-       _ = uintptr(maxUintptr /* ERROR "cannot convert" */ + 1)
+       _ = uintptr(maxUintptr /* ERROR "overflows" */ + 1)
        _ = uintptr(smallestFloat64 /* ERROR "cannot convert" */)
 )
 
index e7b871bfdf7ed1a8a5f2ec54df2566258c1098cc..9ace419a61b1a3984923d5998f1528f65e175ffc 100644 (file)
@@ -125,7 +125,7 @@ const (
        ok = byte(iota + 253)
        bad
        barn
-       bard // ERROR "cannot convert"
+       bard // ERROR "overflows"
 )
 
 const (
index eba991ecd3ce0f78af3a08d24be55fd1a5f35861..26dc58958fe7ad858b3f7af8561960e6b1cce90e 100644 (file)
@@ -28,7 +28,7 @@ var (
 
        // byte
        _ = byte(0)
-       _ = byte(- /* ERROR "cannot convert" */ 1)
+       _ = byte(- /* ERROR "overflows" */ 1)
        _ = - /* ERROR "-byte(1) (constant -1 of type byte) overflows byte" */ byte(1) // test for issue 11367
        _ = byte /* ERROR "overflows byte" */ (0) - byte(1)
        _ = ~ /* ERROR "cannot use ~ outside of interface or type constraint (use ^ for bitwise complement)" */ byte(0)
diff --git a/src/internal/types/testdata/fixedbugs/issue63563.go b/src/internal/types/testdata/fixedbugs/issue63563.go
new file mode 100644 (file)
index 0000000..b813485
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var (
+       _ = int8(1 /* ERROR "constant 255 overflows int8" */ <<8 - 1)
+       _ = int16(1 /* ERROR "constant 65535 overflows int16" */ <<16 - 1)
+       _ = int32(1 /* ERROR "constant 4294967295 overflows int32" */ <<32 - 1)
+       _ = int64(1 /* ERROR "constant 18446744073709551615 overflows int64" */ <<64 - 1)
+
+       _ = uint8(1 /* ERROR "constant 256 overflows uint8" */ << 8)
+       _ = uint16(1 /* ERROR "constant 65536 overflows uint16" */ << 16)
+       _ = uint32(1 /* ERROR "constant 4294967296 overflows uint32" */ << 32)
+       _ = uint64(1 /* ERROR "constant 18446744073709551616 overflows uint64" */ << 64)
+)
+
+func _[P int8 | uint8]() {
+       _ = P(0)
+       _ = P(1 /* ERROR "constant 255 overflows int8 (in P)" */ <<8 - 1)
+}
+
+func _[P int16 | uint16]() {
+       _ = P(0)
+       _ = P(1 /* ERROR "constant 65535 overflows int16 (in P)" */ <<16 - 1)
+}
+
+func _[P int32 | uint32]() {
+       _ = P(0)
+       _ = P(1 /* ERROR "constant 4294967295 overflows int32 (in P)" */ <<32 - 1)
+}
+
+func _[P int64 | uint64]() {
+       _ = P(0)
+       _ = P(1 /* ERROR "constant 18446744073709551615 overflows int64 (in P)" */ <<64 - 1)
+}