about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_lint/src/types/literal.rs31
-rw-r--r--tests/ui/lint/type-overflow.rs26
-rw-r--r--tests/ui/lint/type-overflow.stderr53
3 files changed, 94 insertions, 16 deletions
diff --git a/compiler/rustc_lint/src/types/literal.rs b/compiler/rustc_lint/src/types/literal.rs
index 83942918e3b..4b5163522f8 100644
--- a/compiler/rustc_lint/src/types/literal.rs
+++ b/compiler/rustc_lint/src/types/literal.rs
@@ -204,20 +204,35 @@ fn get_type_suggestion(t: Ty<'_>, val: u128, negative: bool) -> Option<&'static
     match t.kind() {
         ty::Uint(ty::UintTy::Usize) | ty::Int(ty::IntTy::Isize) => None,
         ty::Uint(_) => Some(Integer::fit_unsigned(val).uint_ty_str()),
-        ty::Int(_) if negative => Some(Integer::fit_signed(-(val as i128)).int_ty_str()),
-        ty::Int(int) => {
-            let signed = Integer::fit_signed(val as i128);
-            let unsigned = Integer::fit_unsigned(val);
-            Some(if Some(unsigned.size().bits()) == int.bit_width() {
-                unsigned.uint_ty_str()
+        ty::Int(_) => {
+            let signed = literal_to_i128(val, negative).map(Integer::fit_signed);
+            if negative {
+                signed.map(Integer::int_ty_str)
             } else {
-                signed.int_ty_str()
-            })
+                let unsigned = Integer::fit_unsigned(val);
+                Some(if let Some(signed) = signed {
+                    if unsigned.size() < signed.size() {
+                        unsigned.uint_ty_str()
+                    } else {
+                        signed.int_ty_str()
+                    }
+                } else {
+                    unsigned.uint_ty_str()
+                })
+            }
         }
         _ => None,
     }
 }
 
+fn literal_to_i128(val: u128, negative: bool) -> Option<i128> {
+    if negative {
+        (val <= i128::MAX as u128 + 1).then(|| val.wrapping_neg() as i128)
+    } else {
+        val.try_into().ok()
+    }
+}
+
 fn lint_int_literal<'tcx>(
     cx: &LateContext<'tcx>,
     type_limits: &TypeLimits,
diff --git a/tests/ui/lint/type-overflow.rs b/tests/ui/lint/type-overflow.rs
index 7239e1c9837..1e74a8925f6 100644
--- a/tests/ui/lint/type-overflow.rs
+++ b/tests/ui/lint/type-overflow.rs
@@ -3,20 +3,46 @@
 
 fn main() {
     let error = 255i8; //~WARNING literal out of range for `i8`
+    //~^ HELP consider using the type `u8` instead
 
     let ok = 0b1000_0001; // should be ok -> i32
     let ok = 0b0111_1111i8; // should be ok -> 127i8
 
     let fail = 0b1000_0001i8; //~WARNING literal out of range for `i8`
+    //~^ HELP consider using the type `u8` instead
+    //~| HELP consider using the type `u8` for the literal and cast it to `i8`
 
     let fail = 0x8000_0000_0000_0000i64; //~WARNING literal out of range for `i64`
+    //~^ HELP consider using the type `u64` instead
+    //~| HELP consider using the type `u64` for the literal and cast it to `i64`
 
     let fail = 0x1_FFFF_FFFFu32; //~WARNING literal out of range for `u32`
+    //~^ HELP consider using the type `u64` instead
 
     let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000;
     //~^ WARNING literal out of range for `i128`
+    //~| HELP consider using the type `u128` instead
+    //~| HELP consider using the type `u128` for the literal and cast it to `i128`
+
+    let fail = 0x8000_0000_0000_0000_0000_0000_0000_0000;
+    //~^ WARNING literal out of range for `i32`
+    //~| HELP consider using the type `u128` instead
+
+    let fail = -0x8000_0000_0000_0000_0000_0000_0000_0000; // issue #131849
+    //~^ WARNING literal out of range for `i32`
+    //~| HELP consider using the type `i128` instead
+
+    let fail = -0x8000_0000_0000_0000_0000_0000_0000_0001i128;
+    //~^ WARNING literal out of range for `i128`
+
+    let fail = 340282366920938463463374607431768211455i8;
+    //~^ WARNING literal out of range for `i8`
+    //~| HELP consider using the type `u128` instead
 
     let fail = 0x8FFF_FFFF_FFFF_FFFE; //~WARNING literal out of range for `i32`
+    //~| HELP consider using the type `u64` instead
+    //~| HELP
 
     let fail = -0b1111_1111i8; //~WARNING literal out of range for `i8`
+    //~| HELP consider using the type `i16` instead
 }
diff --git a/tests/ui/lint/type-overflow.stderr b/tests/ui/lint/type-overflow.stderr
index e7c90dcc81b..9fdb05ed1c0 100644
--- a/tests/ui/lint/type-overflow.stderr
+++ b/tests/ui/lint/type-overflow.stderr
@@ -13,7 +13,7 @@ LL | #![warn(overflowing_literals)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 warning: literal out of range for `i8`
-  --> $DIR/type-overflow.rs:10:16
+  --> $DIR/type-overflow.rs:11:16
    |
 LL |     let fail = 0b1000_0001i8;
    |                ^^^^^^^^^^^^^
@@ -29,7 +29,7 @@ LL |     let fail = 0b1000_0001u8 as i8;
    |                ~~~~~~~~~~~~~~~~~~~
 
 warning: literal out of range for `i64`
-  --> $DIR/type-overflow.rs:12:16
+  --> $DIR/type-overflow.rs:15:16
    |
 LL |     let fail = 0x8000_0000_0000_0000i64;
    |                ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -45,7 +45,7 @@ LL |     let fail = 0x8000_0000_0000_0000u64 as i64;
    |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 warning: literal out of range for `u32`
-  --> $DIR/type-overflow.rs:14:16
+  --> $DIR/type-overflow.rs:19:16
    |
 LL |     let fail = 0x1_FFFF_FFFFu32;
    |                ^^^^^^^^^^^^^^^^ help: consider using the type `u64` instead: `0x1_FFFF_FFFFu64`
@@ -53,7 +53,7 @@ LL |     let fail = 0x1_FFFF_FFFFu32;
    = note: the literal `0x1_FFFF_FFFFu32` (decimal `8589934591`) does not fit into the type `u32` and will become `4294967295u32`
 
 warning: literal out of range for `i128`
-  --> $DIR/type-overflow.rs:16:22
+  --> $DIR/type-overflow.rs:22:22
    |
 LL |     let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000;
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -66,20 +66,57 @@ LL |     let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000u128 as i128;
    |                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 warning: literal out of range for `i32`
-  --> $DIR/type-overflow.rs:19:16
+  --> $DIR/type-overflow.rs:27:16
+   |
+LL |     let fail = 0x8000_0000_0000_0000_0000_0000_0000_0000;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into the type `i32` and will become `0i32`
+   = help: consider using the type `u128` instead
+
+warning: literal out of range for `i32`
+  --> $DIR/type-overflow.rs:31:17
+   |
+LL |     let fail = -0x8000_0000_0000_0000_0000_0000_0000_0000; // issue #131849
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into the type `i32`
+   = note: and the value `-0x8000_0000_0000_0000_0000_0000_0000_0000` will become `0i32`
+   = help: consider using the type `i128` instead
+
+warning: literal out of range for `i128`
+  --> $DIR/type-overflow.rs:35:17
+   |
+LL |     let fail = -0x8000_0000_0000_0000_0000_0000_0000_0001i128;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0001i128` (decimal `170141183460469231731687303715884105729`) does not fit into the type `i128`
+   = note: and the value `-0x8000_0000_0000_0000_0000_0000_0000_0001i128` will become `170141183460469231731687303715884105727i128`
+
+warning: literal out of range for `i8`
+  --> $DIR/type-overflow.rs:38:16
+   |
+LL |     let fail = 340282366920938463463374607431768211455i8;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the literal `340282366920938463463374607431768211455i8` does not fit into the type `i8` whose range is `-128..=127`
+   = help: consider using the type `u128` instead
+
+warning: literal out of range for `i32`
+  --> $DIR/type-overflow.rs:42:16
    |
 LL |     let fail = 0x8FFF_FFFF_FFFF_FFFE;
    |                ^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the literal `0x8FFF_FFFF_FFFF_FFFE` (decimal `10376293541461622782`) does not fit into the type `i32` and will become `-2i32`
-   = help: consider using the type `i128` instead
+   = help: consider using the type `u64` instead
 help: to use as a negative number (decimal `-2`), consider using the type `u32` for the literal and cast it to `i32`
    |
 LL |     let fail = 0x8FFF_FFFF_FFFF_FFFEu32 as i32;
    |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 warning: literal out of range for `i8`
-  --> $DIR/type-overflow.rs:21:17
+  --> $DIR/type-overflow.rs:46:17
    |
 LL |     let fail = -0b1111_1111i8;
    |                 ^^^^^^^^^^^^^ help: consider using the type `i16` instead: `0b1111_1111i16`
@@ -87,5 +124,5 @@ LL |     let fail = -0b1111_1111i8;
    = note: the literal `0b1111_1111i8` (decimal `255`) does not fit into the type `i8`
    = note: and the value `-0b1111_1111i8` will become `1i8`
 
-warning: 7 warnings emitted
+warning: 11 warnings emitted