summaryrefslogtreecommitdiffstats
path: root/tests/ui/numbers-arithmetic
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:13 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:13 +0000
commit218caa410aa38c29984be31a5229b9fa717560ee (patch)
treec54bd55eeb6e4c508940a30e94c0032fbd45d677 /tests/ui/numbers-arithmetic
parentReleasing progress-linux version 1.67.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-218caa410aa38c29984be31a5229b9fa717560ee.tar.xz
rustc-218caa410aa38c29984be31a5229b9fa717560ee.zip
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/ui/numbers-arithmetic')
-rw-r--r--tests/ui/numbers-arithmetic/arith-unsigned.rs26
-rw-r--r--tests/ui/numbers-arithmetic/div-mod.rs19
-rw-r--r--tests/ui/numbers-arithmetic/divide-by-zero.rs9
-rw-r--r--tests/ui/numbers-arithmetic/float-int-invalid-const-cast.rs48
-rw-r--r--tests/ui/numbers-arithmetic/float-literal-inference.rs13
-rw-r--r--tests/ui/numbers-arithmetic/float-nan.rs82
-rw-r--r--tests/ui/numbers-arithmetic/float-signature.rs9
-rw-r--r--tests/ui/numbers-arithmetic/float.rs9
-rw-r--r--tests/ui/numbers-arithmetic/float2.rs26
-rw-r--r--tests/ui/numbers-arithmetic/float_math.rs21
-rw-r--r--tests/ui/numbers-arithmetic/floatlits.rs12
-rw-r--r--tests/ui/numbers-arithmetic/i128.rs107
-rw-r--r--tests/ui/numbers-arithmetic/i32-sub.rs6
-rw-r--r--tests/ui/numbers-arithmetic/i8-incr.rs12
-rw-r--r--tests/ui/numbers-arithmetic/int-abs-overflow.rs14
-rw-r--r--tests/ui/numbers-arithmetic/int.rs7
-rw-r--r--tests/ui/numbers-arithmetic/integer-literal-radix.rs19
-rw-r--r--tests/ui/numbers-arithmetic/integer-literal-suffix-inference-2.rs9
-rw-r--r--tests/ui/numbers-arithmetic/integer-literal-suffix-inference-3.rs4
-rw-r--r--tests/ui/numbers-arithmetic/integer-literal-suffix-inference.rs60
-rw-r--r--tests/ui/numbers-arithmetic/issue-8460-const.noopt.stderr148
-rw-r--r--tests/ui/numbers-arithmetic/issue-8460-const.opt.stderr148
-rw-r--r--tests/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr148
-rw-r--r--tests/ui/numbers-arithmetic/issue-8460-const.rs59
-rw-r--r--tests/ui/numbers-arithmetic/issue-8460.rs52
-rw-r--r--tests/ui/numbers-arithmetic/mod-zero.rs9
-rw-r--r--tests/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs27
-rw-r--r--tests/ui/numbers-arithmetic/next-power-of-two-overflow-ndebug.rs14
-rw-r--r--tests/ui/numbers-arithmetic/not-suggest-float-literal.rs53
-rw-r--r--tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr160
-rw-r--r--tests/ui/numbers-arithmetic/num-wrapping.rs448
-rw-r--r--tests/ui/numbers-arithmetic/numeric-method-autoexport.rs25
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-add.rs10
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-lsh-1.rs9
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-lsh-1.stderr14
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-lsh-2.rs9
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-lsh-2.stderr14
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-lsh-3.rs9
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-lsh-3.stderr14
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-lsh-4.rs24
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-lsh-4.stderr14
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-mul.rs10
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-neg.rs10
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-pow-signed.rs8
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-pow-unsigned.rs8
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-rsh-1.rs9
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-rsh-1.stderr14
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-rsh-2.rs9
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-rsh-2.stderr14
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-rsh-3.rs9
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-rsh-3.stderr14
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-rsh-4.rs24
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-rsh-4.stderr14
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-rsh-5.rs9
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-rsh-5.stderr14
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-rsh-6.rs9
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-rsh-6.stderr14
-rw-r--r--tests/ui/numbers-arithmetic/overflowing-sub.rs10
-rw-r--r--tests/ui/numbers-arithmetic/promoted_overflow.rs13
-rw-r--r--tests/ui/numbers-arithmetic/promoted_overflow_opt.rs8
-rw-r--r--tests/ui/numbers-arithmetic/saturating-float-casts-impl.rs503
-rw-r--r--tests/ui/numbers-arithmetic/saturating-float-casts-wasm.rs13
-rw-r--r--tests/ui/numbers-arithmetic/saturating-float-casts.rs12
-rw-r--r--tests/ui/numbers-arithmetic/shift-near-oflo.rs100
-rw-r--r--tests/ui/numbers-arithmetic/shift-various-types.rs48
-rw-r--r--tests/ui/numbers-arithmetic/shift.rs76
-rw-r--r--tests/ui/numbers-arithmetic/signed-shift-const-eval.rs8
-rw-r--r--tests/ui/numbers-arithmetic/suggest-float-literal.fixed37
-rw-r--r--tests/ui/numbers-arithmetic/suggest-float-literal.rs37
-rw-r--r--tests/ui/numbers-arithmetic/suggest-float-literal.stderr139
-rw-r--r--tests/ui/numbers-arithmetic/u128-as-f32.rs46
-rw-r--r--tests/ui/numbers-arithmetic/u128.rs119
-rw-r--r--tests/ui/numbers-arithmetic/u32-decr.rs10
-rw-r--r--tests/ui/numbers-arithmetic/u8-incr-decr.rs19
-rw-r--r--tests/ui/numbers-arithmetic/u8-incr.rs15
-rw-r--r--tests/ui/numbers-arithmetic/uint.rs7
-rw-r--r--tests/ui/numbers-arithmetic/unary-minus-suffix-inference.rs23
77 files changed, 3352 insertions, 0 deletions
diff --git a/tests/ui/numbers-arithmetic/arith-unsigned.rs b/tests/ui/numbers-arithmetic/arith-unsigned.rs
new file mode 100644
index 000000000..ad57d9f86
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/arith-unsigned.rs
@@ -0,0 +1,26 @@
+// run-pass
+#![allow(unused_comparisons)]
+
+// Unsigned integer operations
+pub fn main() {
+ assert!((0u8 < 255u8));
+ assert!((0u8 <= 255u8));
+ assert!((255u8 > 0u8));
+ assert!((255u8 >= 0u8));
+ assert_eq!(250u8 / 10u8, 25u8);
+ assert_eq!(255u8 % 10u8, 5u8);
+ assert!((0u16 < 60000u16));
+ assert!((0u16 <= 60000u16));
+ assert!((60000u16 > 0u16));
+ assert!((60000u16 >= 0u16));
+ assert_eq!(60000u16 / 10u16, 6000u16);
+ assert_eq!(60005u16 % 10u16, 5u16);
+ assert!((0u32 < 4000000000u32));
+ assert!((0u32 <= 4000000000u32));
+ assert!((4000000000u32 > 0u32));
+ assert!((4000000000u32 >= 0u32));
+ assert_eq!(4000000000u32 / 10u32, 400000000u32);
+ assert_eq!(4000000005u32 % 10u32, 5u32);
+ // 64-bit numbers have some flakiness yet. Not tested
+
+}
diff --git a/tests/ui/numbers-arithmetic/div-mod.rs b/tests/ui/numbers-arithmetic/div-mod.rs
new file mode 100644
index 000000000..acb92a7df
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/div-mod.rs
@@ -0,0 +1,19 @@
+// run-pass
+
+
+
+
+pub fn main() {
+ let x: isize = 15;
+ let y: isize = 5;
+ assert_eq!(x / 5, 3);
+ assert_eq!(x / 4, 3);
+ assert_eq!(x / 3, 5);
+ assert_eq!(x / y, 3);
+ assert_eq!(15 / y, 3);
+ assert_eq!(x % 5, 0);
+ assert_eq!(x % 4, 3);
+ assert_eq!(x % 3, 0);
+ assert_eq!(x % y, 0);
+ assert_eq!(15 % y, 0);
+}
diff --git a/tests/ui/numbers-arithmetic/divide-by-zero.rs b/tests/ui/numbers-arithmetic/divide-by-zero.rs
new file mode 100644
index 000000000..30e0e6c1b
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/divide-by-zero.rs
@@ -0,0 +1,9 @@
+// run-fail
+// error-pattern:attempt to divide by zero
+// ignore-emscripten no processes
+
+#[allow(unconditional_panic)]
+fn main() {
+ let y = 0;
+ let _z = 1 / y;
+}
diff --git a/tests/ui/numbers-arithmetic/float-int-invalid-const-cast.rs b/tests/ui/numbers-arithmetic/float-int-invalid-const-cast.rs
new file mode 100644
index 000000000..260281d75
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/float-int-invalid-const-cast.rs
@@ -0,0 +1,48 @@
+// run-pass
+
+// Forces evaluation of constants, triggering hard error
+fn force<T>(_: T) {}
+
+fn main() {
+ { const X: u16 = -1. as u16; force(X); }
+ { const X: u128 = -100. as u128; force(X); }
+
+ { const X: i8 = f32::NAN as i8; force(X); }
+ { const X: i32 = f32::NAN as i32; force(X); }
+ { const X: u64 = f32::NAN as u64; force(X); }
+ { const X: u128 = f32::NAN as u128; force(X); }
+
+ { const X: i8 = f32::INFINITY as i8; force(X); }
+ { const X: u32 = f32::INFINITY as u32; force(X); }
+ { const X: i128 = f32::INFINITY as i128; force(X); }
+ { const X: u128 = f32::INFINITY as u128; force(X); }
+
+ { const X: u8 = f32::NEG_INFINITY as u8; force(X); }
+ { const X: u16 = f32::NEG_INFINITY as u16; force(X); }
+ { const X: i64 = f32::NEG_INFINITY as i64; force(X); }
+ { const X: i128 = f32::NEG_INFINITY as i128; force(X); }
+
+ { const X: i8 = f64::NAN as i8; force(X); }
+ { const X: i32 = f64::NAN as i32; force(X); }
+ { const X: u64 = f64::NAN as u64; force(X); }
+ { const X: u128 = f64::NAN as u128; force(X); }
+
+ { const X: i8 = f64::INFINITY as i8; force(X); }
+ { const X: u32 = f64::INFINITY as u32; force(X); }
+ { const X: i128 = f64::INFINITY as i128; force(X); }
+ { const X: u128 = f64::INFINITY as u128; force(X); }
+
+ { const X: u8 = f64::NEG_INFINITY as u8; force(X); }
+ { const X: u16 = f64::NEG_INFINITY as u16; force(X); }
+ { const X: i64 = f64::NEG_INFINITY as i64; force(X); }
+ { const X: i128 = f64::NEG_INFINITY as i128; force(X); }
+
+ { const X: u8 = 256. as u8; force(X); }
+ { const X: i8 = -129. as i8; force(X); }
+ { const X: i8 = 128. as i8; force(X); }
+ { const X: i32 = 2147483648. as i32; force(X); }
+ { const X: i32 = -2147483904. as i32; force(X); }
+ { const X: u32 = 4294967296. as u32; force(X); }
+ { const X: u128 = 1e40 as u128; force(X); }
+ { const X: i128 = 1e40 as i128; force(X); }
+}
diff --git a/tests/ui/numbers-arithmetic/float-literal-inference.rs b/tests/ui/numbers-arithmetic/float-literal-inference.rs
new file mode 100644
index 000000000..c4645e4f8
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/float-literal-inference.rs
@@ -0,0 +1,13 @@
+// run-pass
+struct S {
+ z: f64
+}
+
+pub fn main() {
+ let x: f32 = 4.0;
+ println!("{}", x);
+ let y: f64 = 64.0;
+ println!("{}", y);
+ let z = S { z: 1.0 };
+ println!("{}", z.z);
+}
diff --git a/tests/ui/numbers-arithmetic/float-nan.rs b/tests/ui/numbers-arithmetic/float-nan.rs
new file mode 100644
index 000000000..0cc6473e5
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/float-nan.rs
@@ -0,0 +1,82 @@
+// run-pass
+
+pub fn main() {
+ let nan: f64 = f64::NAN;
+ assert!((nan).is_nan());
+
+ let inf: f64 = f64::INFINITY;
+ let neg_inf: f64 = -f64::INFINITY;
+ assert_eq!(-inf, neg_inf);
+
+ assert!( nan != nan);
+ assert!( nan != -nan);
+ assert!(-nan != -nan);
+ assert!(-nan != nan);
+
+ assert!( nan != 1.);
+ assert!( nan != 0.);
+ assert!( nan != inf);
+ assert!( nan != -inf);
+
+ assert!( 1. != nan);
+ assert!( 0. != nan);
+ assert!( inf != nan);
+ assert!(-inf != nan);
+
+ assert!(!( nan == nan));
+ assert!(!( nan == -nan));
+ assert!(!( nan == 1.));
+ assert!(!( nan == 0.));
+ assert!(!( nan == inf));
+ assert!(!( nan == -inf));
+ assert!(!( 1. == nan));
+ assert!(!( 0. == nan));
+ assert!(!( inf == nan));
+ assert!(!(-inf == nan));
+ assert!(!(-nan == nan));
+ assert!(!(-nan == -nan));
+
+ assert!(!( nan > nan));
+ assert!(!( nan > -nan));
+ assert!(!( nan > 0.));
+ assert!(!( nan > inf));
+ assert!(!( nan > -inf));
+ assert!(!( 0. > nan));
+ assert!(!( inf > nan));
+ assert!(!(-inf > nan));
+ assert!(!(-nan > nan));
+
+ assert!(!(nan < 0.));
+ assert!(!(nan < 1.));
+ assert!(!(nan < -1.));
+ assert!(!(nan < inf));
+ assert!(!(nan < -inf));
+ assert!(!(nan < nan));
+ assert!(!(nan < -nan));
+
+ assert!(!( 0. < nan));
+ assert!(!( 1. < nan));
+ assert!(!( -1. < nan));
+ assert!(!( inf < nan));
+ assert!(!(-inf < nan));
+ assert!(!(-nan < nan));
+
+ assert!((nan + inf).is_nan());
+ assert!((nan + -inf).is_nan());
+ assert!((nan + 0.).is_nan());
+ assert!((nan + 1.).is_nan());
+ assert!((nan * 1.).is_nan());
+ assert!((nan / 1.).is_nan());
+ assert!((nan / 0.).is_nan());
+ assert!((0.0/0.0f64).is_nan());
+ assert!((-inf + inf).is_nan());
+ assert!((inf - inf).is_nan());
+
+ assert!(!(-1.0f64).is_nan());
+ assert!(!(0.0f64).is_nan());
+ assert!(!(0.1f64).is_nan());
+ assert!(!(1.0f64).is_nan());
+ assert!(!(inf).is_nan());
+ assert!(!(-inf).is_nan());
+ assert!(!(1./-inf).is_nan());
+}
diff --git a/tests/ui/numbers-arithmetic/float-signature.rs b/tests/ui/numbers-arithmetic/float-signature.rs
new file mode 100644
index 000000000..d47280ea2
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/float-signature.rs
@@ -0,0 +1,9 @@
+// run-pass
+
+
+pub fn main() {
+ fn foo(n: f64) -> f64 { return n + 0.12345; }
+ let n: f64 = 0.1;
+ let m: f64 = foo(n);
+ println!("{}", m);
+}
diff --git a/tests/ui/numbers-arithmetic/float.rs b/tests/ui/numbers-arithmetic/float.rs
new file mode 100644
index 000000000..d55c05857
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/float.rs
@@ -0,0 +1,9 @@
+// run-pass
+pub fn main() {
+ let pi = 3.1415927f64;
+ println!("{}", -pi * (pi + 2.0 / pi) - pi * 5.0);
+ if pi == 5.0 || pi < 10.0 || pi <= 2.0 || pi != 22.0 / 7.0 || pi >= 10.0
+ || pi > 1.0 {
+ println!("yes");
+ }
+}
diff --git a/tests/ui/numbers-arithmetic/float2.rs b/tests/ui/numbers-arithmetic/float2.rs
new file mode 100644
index 000000000..b1bcf8da5
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/float2.rs
@@ -0,0 +1,26 @@
+// run-pass
+
+
+
+pub fn main() {
+ let a = 1.5e6f64;
+ let b = 1.5E6f64;
+ let c = 1e6f64;
+ let d = 1E6f64;
+ let e = 3.0f32;
+ let f = 5.9f64;
+ let g = 1e6f32;
+ let h = 1.0e7f64;
+ let i = 1.0E7f64;
+ let j = 3.1e+9f64;
+ let k = 3.2e-10f64;
+ assert_eq!(a, b);
+ assert!((c < b));
+ assert_eq!(c, d);
+ assert!((e < g));
+ assert!((f < h));
+ assert_eq!(g, 1000000.0f32);
+ assert_eq!(h, i);
+ assert!((j > k));
+ assert!((k < a));
+}
diff --git a/tests/ui/numbers-arithmetic/float_math.rs b/tests/ui/numbers-arithmetic/float_math.rs
new file mode 100644
index 000000000..a2902ee56
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/float_math.rs
@@ -0,0 +1,21 @@
+// run-pass
+#![feature(core_intrinsics)]
+
+use std::intrinsics::{fadd_fast, fsub_fast, fmul_fast, fdiv_fast, frem_fast};
+
+#[inline(never)]
+pub fn test_operations(a: f64, b: f64) {
+ // make sure they all map to the correct operation
+ unsafe {
+ assert_eq!(fadd_fast(a, b), a + b);
+ assert_eq!(fsub_fast(a, b), a - b);
+ assert_eq!(fmul_fast(a, b), a * b);
+ assert_eq!(fdiv_fast(a, b), a / b);
+ assert_eq!(frem_fast(a, b), a % b);
+ }
+}
+
+fn main() {
+ test_operations(1., 2.);
+ test_operations(10., 5.);
+}
diff --git a/tests/ui/numbers-arithmetic/floatlits.rs b/tests/ui/numbers-arithmetic/floatlits.rs
new file mode 100644
index 000000000..07049af31
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/floatlits.rs
@@ -0,0 +1,12 @@
+// run-pass
+
+
+
+pub fn main() {
+ let f = 4.999999999999f64;
+ assert!((f > 4.90f64));
+ assert!((f < 5.0f64));
+ let g = 4.90000000001e-10f64;
+ assert!((g > 5e-11f64));
+ assert!((g < 5e-9f64));
+}
diff --git a/tests/ui/numbers-arithmetic/i128.rs b/tests/ui/numbers-arithmetic/i128.rs
new file mode 100644
index 000000000..d61a1ab03
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/i128.rs
@@ -0,0 +1,107 @@
+// run-pass
+#![allow(overflowing_literals)]
+
+#![feature(test)]
+
+extern crate test;
+use test::black_box as b;
+
+fn main() {
+ let x: i128 = -1;
+ assert_eq!(0, !x);
+ let y: i128 = -2;
+ assert_eq!(!1, y);
+ let z: i128 = 0xABCD_EF;
+ assert_eq!(z * z, 0x734C_C2F2_A521);
+ assert_eq!(z * z * z * z, 0x33EE_0E2A_54E2_59DA_A0E7_8E41);
+ assert_eq!(-z * -z, 0x734C_C2F2_A521);
+ assert_eq!(-z * -z * -z * -z, 0x33EE_0E2A_54E2_59DA_A0E7_8E41);
+ assert_eq!(-z + -z + -z + -z, -0x2AF3_7BC);
+ let k: i128 = -0x1234_5678_9ABC_DEFF_EDCB_A987_6543_210;
+ assert_eq!(k + k, -0x2468_ACF1_3579_BDFF_DB97_530E_CA86_420);
+ assert_eq!(0, k - k);
+ assert_eq!(-0x1234_5678_9ABC_DEFF_EDCB_A987_5A86_421, k + z);
+ assert_eq!(-0x1000_0000_0000_0000_0000_0000_0000_000,
+ k + 0x234_5678_9ABC_DEFF_EDCB_A987_6543_210);
+ assert_eq!(-0x6EF5_DE4C_D3BC_2AAA_3BB4_CC5D_D6EE_8, k / 42);
+ assert_eq!(-k, k / -1);
+ assert_eq!(-0x91A2_B3C4_D5E6_F8, k >> 65);
+ assert_eq!(-0xFDB9_7530_ECA8_6420_0000_0000_0000_0000, k << 65);
+ assert!(k < z);
+ assert!(y > k);
+ assert!(y < x);
+ assert_eq!(x as i64, -1);
+ assert_eq!(z as i64, 0xABCD_EF);
+ assert_eq!(k as i64, -0xFEDC_BA98_7654_3210);
+ assert_eq!(k as u128, 0xFEDC_BA98_7654_3210_0123_4567_89AB_CDF0);
+ assert_eq!(-k as u128, 0x1234_5678_9ABC_DEFF_EDCB_A987_6543_210);
+ assert_eq!((-z as f64) as i128, -z);
+ assert_eq!((-z as f32) as i128, -z);
+ assert_eq!((-z as f64 * 16.0) as i128, -z * 16);
+ assert_eq!((-z as f32 * 16.0) as i128, -z * 16);
+ // Same stuff as above, but blackboxed, to force use of intrinsics
+ let x: i128 = b(-1);
+ assert_eq!(0, !x);
+ let y: i128 = b(-2);
+ assert_eq!(!1, y);
+ let z: i128 = b(0xABCD_EF);
+ assert_eq!(z * z, 0x734C_C2F2_A521);
+ assert_eq!(z * z * z * z, 0x33EE_0E2A_54E2_59DA_A0E7_8E41);
+ assert_eq!(-z * -z, 0x734C_C2F2_A521);
+ assert_eq!(-z * -z * -z * -z, 0x33EE_0E2A_54E2_59DA_A0E7_8E41);
+ assert_eq!(-z + -z + -z + -z, -0x2AF3_7BC);
+ let k: i128 = b(-0x1234_5678_9ABC_DEFF_EDCB_A987_6543_210);
+ assert_eq!(k + k, -0x2468_ACF1_3579_BDFF_DB97_530E_CA86_420);
+ assert_eq!(0, k - k);
+ assert_eq!(-0x1234_5678_9ABC_DEFF_EDCB_A987_5A86_421, k + z);
+ assert_eq!(-0x1000_0000_0000_0000_0000_0000_0000_000,
+ k + 0x234_5678_9ABC_DEFF_EDCB_A987_6543_210);
+ assert_eq!(-0x6EF5_DE4C_D3BC_2AAA_3BB4_CC5D_D6EE_8, k / 42);
+ assert_eq!(-k, k / -1);
+ assert_eq!(-0x91A2_B3C4_D5E6_F8, k >> 65);
+ assert_eq!(-0xFDB9_7530_ECA8_6420_0000_0000_0000_0000, k << 65);
+ assert!(k < z);
+ assert!(y > k);
+ assert!(y < x);
+ assert_eq!(x as i64, -1);
+ assert_eq!(z as i64, 0xABCD_EF);
+ assert_eq!(k as i64, -0xFEDC_BA98_7654_3210);
+ assert_eq!(k as u128, 0xFEDC_BA98_7654_3210_0123_4567_89AB_CDF0);
+ assert_eq!(-k as u128, 0x1234_5678_9ABC_DEFF_EDCB_A987_6543_210);
+ assert_eq!((-z as f64) as i128, -z);
+ assert_eq!((-z as f32) as i128, -z);
+ assert_eq!((-z as f64 * 16.0) as i128, -z * 16);
+ assert_eq!((-z as f32 * 16.0) as i128, -z * 16);
+ // formatting
+ let j: i128 = -(1 << 67);
+ assert_eq!("-147573952589676412928", format!("{}", j));
+ assert_eq!("fffffffffffffff80000000000000000", format!("{:x}", j));
+ assert_eq!("3777777777777777777760000000000000000000000", format!("{:o}", j));
+ assert_eq!("1111111111111111111111111111111111111111111111111111111111111\
+ 0000000000000000000000000000000000000000000000000000000000000000000",
+ format!("{:b}", j));
+ assert_eq!("-147573952589676412928", format!("{:?}", j));
+ // common traits
+ assert_eq!(x, b(x.clone()));
+ // overflow checks
+ assert_eq!((-z).checked_mul(-z), Some(0x734C_C2F2_A521));
+ assert_eq!((z).checked_mul(z), Some(0x734C_C2F2_A521));
+ assert_eq!((k).checked_mul(k), None);
+ let l: i128 = b(i128::MIN);
+ let o: i128 = b(17);
+ assert_eq!(l.checked_sub(b(2)), None);
+ assert_eq!(l.checked_add(l), None);
+ assert_eq!((-(l + 1)).checked_add(2), None);
+ assert_eq!(l.checked_sub(l), Some(0));
+ assert_eq!(b(1u128).checked_shl(b(127)), Some(1 << 127));
+ assert_eq!(o.checked_shl(b(128)), None);
+
+ // https://github.com/rust-lang/rust/issues/41228
+ assert_eq!(b(-87559967289969187895646876466835277875_i128) /
+ b(84285771033834995895337664386045050880_i128),
+ -1i128);
+
+ // iter-arithmetic traits
+ assert_eq!(10i128, [1i128, 2, 3, 4].iter().sum());
+ assert_eq!(24i128, [1i128, 2, 3, 4].iter().product());
+}
diff --git a/tests/ui/numbers-arithmetic/i32-sub.rs b/tests/ui/numbers-arithmetic/i32-sub.rs
new file mode 100644
index 000000000..56df772b4
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/i32-sub.rs
@@ -0,0 +1,6 @@
+// run-pass
+
+
+
+
+pub fn main() { let mut x: i32 = -400; x = 0 - x; assert_eq!(x, 400); }
diff --git a/tests/ui/numbers-arithmetic/i8-incr.rs b/tests/ui/numbers-arithmetic/i8-incr.rs
new file mode 100644
index 000000000..718d259f7
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/i8-incr.rs
@@ -0,0 +1,12 @@
+// run-pass
+
+
+
+
+pub fn main() {
+ let mut x: i8 = -12;
+ let y: i8 = -12;
+ x = x + 1;
+ x = x - 1;
+ assert_eq!(x, y);
+}
diff --git a/tests/ui/numbers-arithmetic/int-abs-overflow.rs b/tests/ui/numbers-arithmetic/int-abs-overflow.rs
new file mode 100644
index 000000000..d63ba8cb0
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/int-abs-overflow.rs
@@ -0,0 +1,14 @@
+// run-pass
+// compile-flags: -C overflow-checks=on
+// ignore-emscripten no threads support
+// needs-unwind
+
+use std::thread;
+
+fn main() {
+ assert!(thread::spawn(|| i8::MIN.abs()).join().is_err());
+ assert!(thread::spawn(|| i16::MIN.abs()).join().is_err());
+ assert!(thread::spawn(|| i32::MIN.abs()).join().is_err());
+ assert!(thread::spawn(|| i64::MIN.abs()).join().is_err());
+ assert!(thread::spawn(|| isize::MIN.abs()).join().is_err());
+}
diff --git a/tests/ui/numbers-arithmetic/int.rs b/tests/ui/numbers-arithmetic/int.rs
new file mode 100644
index 000000000..b496a70a6
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/int.rs
@@ -0,0 +1,7 @@
+// run-pass
+
+
+
+// pretty-expanded FIXME #23616
+
+pub fn main() { let _x: isize = 10; }
diff --git a/tests/ui/numbers-arithmetic/integer-literal-radix.rs b/tests/ui/numbers-arithmetic/integer-literal-radix.rs
new file mode 100644
index 000000000..8f61ea17a
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/integer-literal-radix.rs
@@ -0,0 +1,19 @@
+// run-pass
+
+pub fn main() {
+ let a = 0xBEEF_isize;
+ let b = 0o755_isize;
+ let c = 0b10101_isize;
+ let d = -0xBEEF_isize;
+ let e = -0o755_isize;
+ let f = -0b10101_isize;
+
+ assert_eq!(a, 48879);
+ assert_eq!(b, 493);
+ assert_eq!(c, 21);
+ assert_eq!(d, -48879);
+ assert_eq!(e, -493);
+ assert_eq!(f, -21);
+
+
+}
diff --git a/tests/ui/numbers-arithmetic/integer-literal-suffix-inference-2.rs b/tests/ui/numbers-arithmetic/integer-literal-suffix-inference-2.rs
new file mode 100644
index 000000000..80248dc22
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/integer-literal-suffix-inference-2.rs
@@ -0,0 +1,9 @@
+// run-pass
+// pretty-expanded FIXME #23616
+
+fn foo(_: *const ()) {}
+
+fn main() {
+ let a = 3;
+ foo(&a as *const _ as *const ());
+}
diff --git a/tests/ui/numbers-arithmetic/integer-literal-suffix-inference-3.rs b/tests/ui/numbers-arithmetic/integer-literal-suffix-inference-3.rs
new file mode 100644
index 000000000..bec718a3c
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/integer-literal-suffix-inference-3.rs
@@ -0,0 +1,4 @@
+// run-pass
+fn main() {
+ println!("{}", std::mem::size_of_val(&1));
+}
diff --git a/tests/ui/numbers-arithmetic/integer-literal-suffix-inference.rs b/tests/ui/numbers-arithmetic/integer-literal-suffix-inference.rs
new file mode 100644
index 000000000..d177ced1a
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/integer-literal-suffix-inference.rs
@@ -0,0 +1,60 @@
+// run-pass
+// pretty-expanded FIXME #23616
+
+pub fn main() {
+ fn id_i8(n: i8) -> i8 { n }
+ fn id_i16(n: i16) -> i16 { n }
+ fn id_i32(n: i32) -> i32 { n }
+ fn id_i64(n: i64) -> i64 { n }
+
+ fn id_uint(n: usize) -> usize { n }
+ fn id_u8(n: u8) -> u8 { n }
+ fn id_u16(n: u16) -> u16 { n }
+ fn id_u32(n: u32) -> u32 { n }
+ fn id_u64(n: u64) -> u64 { n }
+
+ let _i: i8 = -128;
+ let j = -128;
+ id_i8(j);
+ id_i8(-128);
+
+ let _i: i16 = -32_768;
+ let j = -32_768;
+ id_i16(j);
+ id_i16(-32_768);
+
+ let _i: i32 = -2_147_483_648;
+ let j = -2_147_483_648;
+ id_i32(j);
+ id_i32(-2_147_483_648);
+
+ let _i: i64 = -9_223_372_036_854_775_808;
+ let j = -9_223_372_036_854_775_808;
+ id_i64(j);
+ id_i64(-9_223_372_036_854_775_808);
+
+ let _i: usize = 1;
+ let j = 1;
+ id_uint(j);
+ id_uint(1);
+
+ let _i: u8 = 255;
+ let j = 255;
+ id_u8(j);
+ id_u8(255);
+
+ let _i: u16 = 65_535;
+ let j = 65_535;
+ id_u16(j);
+ id_u16(65_535);
+
+ let _i: u32 = 4_294_967_295;
+ let j = 4_294_967_295;
+ id_u32(j);
+ id_u32(4_294_967_295);
+
+ let _i: u64 = 18_446_744_073_709_551_615;
+ let j = 18_446_744_073_709_551_615;
+ id_u64(j);
+ id_u64(18_446_744_073_709_551_615);
+}
diff --git a/tests/ui/numbers-arithmetic/issue-8460-const.noopt.stderr b/tests/ui/numbers-arithmetic/issue-8460-const.noopt.stderr
new file mode 100644
index 000000000..c4abcb784
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/issue-8460-const.noopt.stderr
@@ -0,0 +1,148 @@
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:11:36
+ |
+LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
+ | ^^^^^^^^^^^^^^^ attempt to compute `isize::MIN / -1_isize`, which would overflow
+ |
+ = note: `#[deny(unconditional_panic)]` on by default
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:13:36
+ |
+LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
+ | ^^^^^^^^^^^^ attempt to compute `i8::MIN / -1_i8`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:15:36
+ |
+LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
+ | ^^^^^^^^^^^^^ attempt to compute `i16::MIN / -1_i16`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:17:36
+ |
+LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
+ | ^^^^^^^^^^^^^ attempt to compute `i32::MIN / -1_i32`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:19:36
+ |
+LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
+ | ^^^^^^^^^^^^^ attempt to compute `i64::MIN / -1_i64`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:21:36
+ |
+LL | assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err());
+ | ^^^^^^^^^^^^^^ attempt to compute `i128::MIN / -1_i128`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:23:36
+ |
+LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
+ | ^^^^^^^^^^ attempt to divide `1_isize` by zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:25:36
+ |
+LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
+ | ^^^^^^^ attempt to divide `1_i8` by zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:27:36
+ |
+LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
+ | ^^^^^^^^ attempt to divide `1_i16` by zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:29:36
+ |
+LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
+ | ^^^^^^^^ attempt to divide `1_i32` by zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:31:36
+ |
+LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
+ | ^^^^^^^^ attempt to divide `1_i64` by zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:33:36
+ |
+LL | assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err());
+ | ^^^^^^^^^ attempt to divide `1_i128` by zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:35:36
+ |
+LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
+ | ^^^^^^^^^^^^^^^ attempt to compute the remainder of `isize::MIN % -1_isize`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:37:36
+ |
+LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
+ | ^^^^^^^^^^^^ attempt to compute the remainder of `i8::MIN % -1_i8`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:39:36
+ |
+LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
+ | ^^^^^^^^^^^^^ attempt to compute the remainder of `i16::MIN % -1_i16`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:41:36
+ |
+LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
+ | ^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:43:36
+ |
+LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
+ | ^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:45:36
+ |
+LL | assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err());
+ | ^^^^^^^^^^^^^^ attempt to compute the remainder of `i128::MIN % -1_i128`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:47:36
+ |
+LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
+ | ^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:49:36
+ |
+LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
+ | ^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:51:36
+ |
+LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
+ | ^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:53:36
+ |
+LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
+ | ^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:55:36
+ |
+LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
+ | ^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:57:36
+ |
+LL | assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err());
+ | ^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero
+
+error: aborting due to 24 previous errors
+
diff --git a/tests/ui/numbers-arithmetic/issue-8460-const.opt.stderr b/tests/ui/numbers-arithmetic/issue-8460-const.opt.stderr
new file mode 100644
index 000000000..c4abcb784
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/issue-8460-const.opt.stderr
@@ -0,0 +1,148 @@
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:11:36
+ |
+LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
+ | ^^^^^^^^^^^^^^^ attempt to compute `isize::MIN / -1_isize`, which would overflow
+ |
+ = note: `#[deny(unconditional_panic)]` on by default
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:13:36
+ |
+LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
+ | ^^^^^^^^^^^^ attempt to compute `i8::MIN / -1_i8`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:15:36
+ |
+LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
+ | ^^^^^^^^^^^^^ attempt to compute `i16::MIN / -1_i16`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:17:36
+ |
+LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
+ | ^^^^^^^^^^^^^ attempt to compute `i32::MIN / -1_i32`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:19:36
+ |
+LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
+ | ^^^^^^^^^^^^^ attempt to compute `i64::MIN / -1_i64`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:21:36
+ |
+LL | assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err());
+ | ^^^^^^^^^^^^^^ attempt to compute `i128::MIN / -1_i128`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:23:36
+ |
+LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
+ | ^^^^^^^^^^ attempt to divide `1_isize` by zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:25:36
+ |
+LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
+ | ^^^^^^^ attempt to divide `1_i8` by zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:27:36
+ |
+LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
+ | ^^^^^^^^ attempt to divide `1_i16` by zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:29:36
+ |
+LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
+ | ^^^^^^^^ attempt to divide `1_i32` by zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:31:36
+ |
+LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
+ | ^^^^^^^^ attempt to divide `1_i64` by zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:33:36
+ |
+LL | assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err());
+ | ^^^^^^^^^ attempt to divide `1_i128` by zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:35:36
+ |
+LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
+ | ^^^^^^^^^^^^^^^ attempt to compute the remainder of `isize::MIN % -1_isize`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:37:36
+ |
+LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
+ | ^^^^^^^^^^^^ attempt to compute the remainder of `i8::MIN % -1_i8`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:39:36
+ |
+LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
+ | ^^^^^^^^^^^^^ attempt to compute the remainder of `i16::MIN % -1_i16`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:41:36
+ |
+LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
+ | ^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:43:36
+ |
+LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
+ | ^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:45:36
+ |
+LL | assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err());
+ | ^^^^^^^^^^^^^^ attempt to compute the remainder of `i128::MIN % -1_i128`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:47:36
+ |
+LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
+ | ^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:49:36
+ |
+LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
+ | ^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:51:36
+ |
+LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
+ | ^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:53:36
+ |
+LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
+ | ^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:55:36
+ |
+LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
+ | ^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:57:36
+ |
+LL | assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err());
+ | ^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero
+
+error: aborting due to 24 previous errors
+
diff --git a/tests/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr b/tests/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr
new file mode 100644
index 000000000..c4abcb784
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr
@@ -0,0 +1,148 @@
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:11:36
+ |
+LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
+ | ^^^^^^^^^^^^^^^ attempt to compute `isize::MIN / -1_isize`, which would overflow
+ |
+ = note: `#[deny(unconditional_panic)]` on by default
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:13:36
+ |
+LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
+ | ^^^^^^^^^^^^ attempt to compute `i8::MIN / -1_i8`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:15:36
+ |
+LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
+ | ^^^^^^^^^^^^^ attempt to compute `i16::MIN / -1_i16`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:17:36
+ |
+LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
+ | ^^^^^^^^^^^^^ attempt to compute `i32::MIN / -1_i32`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:19:36
+ |
+LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
+ | ^^^^^^^^^^^^^ attempt to compute `i64::MIN / -1_i64`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:21:36
+ |
+LL | assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err());
+ | ^^^^^^^^^^^^^^ attempt to compute `i128::MIN / -1_i128`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:23:36
+ |
+LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
+ | ^^^^^^^^^^ attempt to divide `1_isize` by zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:25:36
+ |
+LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
+ | ^^^^^^^ attempt to divide `1_i8` by zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:27:36
+ |
+LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
+ | ^^^^^^^^ attempt to divide `1_i16` by zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:29:36
+ |
+LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
+ | ^^^^^^^^ attempt to divide `1_i32` by zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:31:36
+ |
+LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
+ | ^^^^^^^^ attempt to divide `1_i64` by zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:33:36
+ |
+LL | assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err());
+ | ^^^^^^^^^ attempt to divide `1_i128` by zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:35:36
+ |
+LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
+ | ^^^^^^^^^^^^^^^ attempt to compute the remainder of `isize::MIN % -1_isize`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:37:36
+ |
+LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
+ | ^^^^^^^^^^^^ attempt to compute the remainder of `i8::MIN % -1_i8`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:39:36
+ |
+LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
+ | ^^^^^^^^^^^^^ attempt to compute the remainder of `i16::MIN % -1_i16`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:41:36
+ |
+LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
+ | ^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:43:36
+ |
+LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
+ | ^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:45:36
+ |
+LL | assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err());
+ | ^^^^^^^^^^^^^^ attempt to compute the remainder of `i128::MIN % -1_i128`, which would overflow
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:47:36
+ |
+LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
+ | ^^^^^^^^^^ attempt to calculate the remainder of `1_isize` with a divisor of zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:49:36
+ |
+LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
+ | ^^^^^^^ attempt to calculate the remainder of `1_i8` with a divisor of zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:51:36
+ |
+LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
+ | ^^^^^^^^ attempt to calculate the remainder of `1_i16` with a divisor of zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:53:36
+ |
+LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
+ | ^^^^^^^^ attempt to calculate the remainder of `1_i32` with a divisor of zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:55:36
+ |
+LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
+ | ^^^^^^^^ attempt to calculate the remainder of `1_i64` with a divisor of zero
+
+error: this operation will panic at runtime
+ --> $DIR/issue-8460-const.rs:57:36
+ |
+LL | assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err());
+ | ^^^^^^^^^ attempt to calculate the remainder of `1_i128` with a divisor of zero
+
+error: aborting due to 24 previous errors
+
diff --git a/tests/ui/numbers-arithmetic/issue-8460-const.rs b/tests/ui/numbers-arithmetic/issue-8460-const.rs
new file mode 100644
index 000000000..02e7567da
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/issue-8460-const.rs
@@ -0,0 +1,59 @@
+// revisions: noopt opt opt_with_overflow_checks
+//[noopt]compile-flags: -C opt-level=0
+//[opt]compile-flags: -O
+//[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O
+
+// build-fail
+
+use std::thread;
+
+fn main() {
+ assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
+ //~^ ERROR operation will panic
+ assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
+ //~^ ERROR operation will panic
+ assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
+ //~^ ERROR operation will panic
+ assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
+ //~^ ERROR operation will panic
+ assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
+ //~^ ERROR operation will panic
+ assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err());
+ //~^ ERROR operation will panic
+ assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
+ //~^ ERROR operation will panic
+ assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
+ //~^ ERROR operation will panic
+ assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
+ //~^ ERROR operation will panic
+ assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
+ //~^ ERROR operation will panic
+ assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
+ //~^ ERROR operation will panic
+ assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err());
+ //~^ ERROR operation will panic
+ assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
+ //~^ ERROR operation will panic
+ assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
+ //~^ ERROR operation will panic
+ assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
+ //~^ ERROR operation will panic
+ assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
+ //~^ ERROR operation will panic
+ assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
+ //~^ ERROR operation will panic
+ assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err());
+ //~^ ERROR operation will panic
+ assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
+ //~^ ERROR operation will panic
+ assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
+ //~^ ERROR operation will panic
+ assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
+ //~^ ERROR operation will panic
+ assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
+ //~^ ERROR operation will panic
+ assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
+ //~^ ERROR operation will panic
+ assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err());
+ //~^ ERROR operation will panic
+}
diff --git a/tests/ui/numbers-arithmetic/issue-8460.rs b/tests/ui/numbers-arithmetic/issue-8460.rs
new file mode 100644
index 000000000..77368b87e
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/issue-8460.rs
@@ -0,0 +1,52 @@
+// run-pass
+#![allow(unused_must_use)]
+// ignore-emscripten no threads support
+// needs-unwind
+#![feature(rustc_attrs)]
+
+use std::thread;
+
+trait Int {
+ fn zero() -> Self;
+ fn one() -> Self;
+}
+macro_rules! doit {
+ ($($t:ident)*) => ($(impl Int for $t {
+ fn zero() -> Self { 0 }
+ fn one() -> Self { 1 }
+ })*)
+}
+doit! { i8 i16 i32 i64 isize }
+
+macro_rules! check {
+ ($($e:expr),*) => {
+ $(assert!(thread::spawn({
+ move|| { $e; }
+ }).join().is_err());)*
+ }
+}
+
+fn main() {
+ check![
+ isize::MIN / -isize::one(),
+ i8::MIN / -i8::one(),
+ i16::MIN / -i16::one(),
+ i32::MIN / -i32::one(),
+ i64::MIN / -i64::one(),
+ 1isize / isize::zero(),
+ 1i8 / i8::zero(),
+ 1i16 / i16::zero(),
+ 1i32 / i32::zero(),
+ 1i64 / i64::zero(),
+ isize::MIN % -isize::one(),
+ i8::MIN % -i8::one(),
+ i16::MIN % -i16::one(),
+ i32::MIN % -i32::one(),
+ i64::MIN % -i64::one(),
+ 1isize % isize::zero(),
+ 1i8 % i8::zero(),
+ 1i16 % i16::zero(),
+ 1i32 % i32::zero(),
+ 1i64 % i64::zero()
+ ];
+}
diff --git a/tests/ui/numbers-arithmetic/mod-zero.rs b/tests/ui/numbers-arithmetic/mod-zero.rs
new file mode 100644
index 000000000..083716394
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/mod-zero.rs
@@ -0,0 +1,9 @@
+// run-fail
+// error-pattern:attempt to calculate the remainder with a divisor of zero
+// ignore-emscripten no processes
+
+#[allow(unconditional_panic)]
+fn main() {
+ let y = 0;
+ let _z = 1 % y;
+}
diff --git a/tests/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs b/tests/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs
new file mode 100644
index 000000000..79d78da33
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs
@@ -0,0 +1,27 @@
+// run-pass
+// compile-flags: -C debug_assertions=yes
+// needs-unwind
+// ignore-emscripten dies with an LLVM error
+
+use std::panic;
+
+fn main() {
+ macro_rules! overflow_test {
+ ($t:ident) => (
+ let r = panic::catch_unwind(|| {
+ ($t::MAX).next_power_of_two()
+ });
+ assert!(r.is_err());
+
+ let r = panic::catch_unwind(|| {
+ (($t::MAX >> 1) + 2).next_power_of_two()
+ });
+ assert!(r.is_err());
+ )
+ }
+ overflow_test!(u8);
+ overflow_test!(u16);
+ overflow_test!(u32);
+ overflow_test!(u64);
+ overflow_test!(u128);
+}
diff --git a/tests/ui/numbers-arithmetic/next-power-of-two-overflow-ndebug.rs b/tests/ui/numbers-arithmetic/next-power-of-two-overflow-ndebug.rs
new file mode 100644
index 000000000..982cd97c5
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/next-power-of-two-overflow-ndebug.rs
@@ -0,0 +1,14 @@
+// run-pass
+// compile-flags: -C debug_assertions=no
+// ignore-emscripten dies with an LLVM error
+
+fn main() {
+ for i in 129..256 {
+ assert_eq!((i as u8).next_power_of_two(), 0);
+ }
+
+ assert_eq!(((1u16 << 15) + 1).next_power_of_two(), 0);
+ assert_eq!(((1u32 << 31) + 1).next_power_of_two(), 0);
+ assert_eq!(((1u64 << 63) + 1).next_power_of_two(), 0);
+ assert_eq!(((1u128 << 127) + 1).next_power_of_two(), 0);
+}
diff --git a/tests/ui/numbers-arithmetic/not-suggest-float-literal.rs b/tests/ui/numbers-arithmetic/not-suggest-float-literal.rs
new file mode 100644
index 000000000..513d02db9
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/not-suggest-float-literal.rs
@@ -0,0 +1,53 @@
+fn add_float_to_integer(x: u8) -> f32 {
+ x + 100.0 //~ ERROR cannot add `{float}` to `u8`
+}
+
+fn add_str_to_float(x: f64) -> f64 {
+ x + "foo" //~ ERROR cannot add `&str` to `f64`
+}
+
+fn add_lvar_to_float(x: f64) -> f64 {
+ let y = 3;
+ x + y //~ ERROR cannot add `{integer}` to `f64`
+}
+
+fn subtract_float_from_integer(x: u8) -> f32 {
+ x - 100.0 //~ ERROR cannot subtract `{float}` from `u8`
+}
+
+fn subtract_str_from_f64(x: f64) -> f64 {
+ x - "foo" //~ ERROR cannot subtract `&str` from `f64`
+}
+
+fn subtract_lvar_from_f64(x: f64) -> f64 {
+ let y = 3;
+ x - y //~ ERROR cannot subtract `{integer}` from `f64`
+}
+
+fn multiply_integer_by_float(x: u8) -> f32 {
+ x * 100.0 //~ ERROR cannot multiply `u8` by `{float}`
+}
+
+fn multiply_f64_by_str(x: f64) -> f64 {
+ x * "foo" //~ ERROR cannot multiply `f64` by `&str`
+}
+
+fn multiply_f64_by_lvar(x: f64) -> f64 {
+ let y = 3;
+ x * y //~ ERROR cannot multiply `f64` by `{integer}`
+}
+
+fn divide_integer_by_float(x: u8) -> u8 {
+ x / 100.0 //~ ERROR cannot divide `u8` by `{float}`
+}
+
+fn divide_f64_by_str(x: f64) -> f64 {
+ x / "foo" //~ ERROR cannot divide `f64` by `&str`
+}
+
+fn divide_f64_by_lvar(x: f64) -> f64 {
+ let y = 3;
+ x / y //~ ERROR cannot divide `f64` by `{integer}`
+}
+
+fn main() {}
diff --git a/tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr b/tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr
new file mode 100644
index 000000000..8f0eef237
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/not-suggest-float-literal.stderr
@@ -0,0 +1,160 @@
+error[E0277]: cannot add `{float}` to `u8`
+ --> $DIR/not-suggest-float-literal.rs:2:7
+ |
+LL | x + 100.0
+ | ^ no implementation for `u8 + {float}`
+ |
+ = help: the trait `Add<{float}>` is not implemented for `u8`
+ = help: the following other types implement trait `Add<Rhs>`:
+ <&'a u8 as Add<u8>>
+ <&u8 as Add<&u8>>
+ <u8 as Add<&u8>>
+ <u8 as Add>
+
+error[E0277]: cannot add `&str` to `f64`
+ --> $DIR/not-suggest-float-literal.rs:6:7
+ |
+LL | x + "foo"
+ | ^ no implementation for `f64 + &str`
+ |
+ = help: the trait `Add<&str>` is not implemented for `f64`
+ = help: the following other types implement trait `Add<Rhs>`:
+ <&'a f64 as Add<f64>>
+ <&f64 as Add<&f64>>
+ <f64 as Add<&f64>>
+ <f64 as Add>
+
+error[E0277]: cannot add `{integer}` to `f64`
+ --> $DIR/not-suggest-float-literal.rs:11:7
+ |
+LL | x + y
+ | ^ no implementation for `f64 + {integer}`
+ |
+ = help: the trait `Add<{integer}>` is not implemented for `f64`
+ = help: the following other types implement trait `Add<Rhs>`:
+ <&'a f64 as Add<f64>>
+ <&f64 as Add<&f64>>
+ <f64 as Add<&f64>>
+ <f64 as Add>
+
+error[E0277]: cannot subtract `{float}` from `u8`
+ --> $DIR/not-suggest-float-literal.rs:15:7
+ |
+LL | x - 100.0
+ | ^ no implementation for `u8 - {float}`
+ |
+ = help: the trait `Sub<{float}>` is not implemented for `u8`
+ = help: the following other types implement trait `Sub<Rhs>`:
+ <&'a u8 as Sub<u8>>
+ <&u8 as Sub<&u8>>
+ <u8 as Sub<&u8>>
+ <u8 as Sub>
+
+error[E0277]: cannot subtract `&str` from `f64`
+ --> $DIR/not-suggest-float-literal.rs:19:7
+ |
+LL | x - "foo"
+ | ^ no implementation for `f64 - &str`
+ |
+ = help: the trait `Sub<&str>` is not implemented for `f64`
+ = help: the following other types implement trait `Sub<Rhs>`:
+ <&'a f64 as Sub<f64>>
+ <&f64 as Sub<&f64>>
+ <f64 as Sub<&f64>>
+ <f64 as Sub>
+
+error[E0277]: cannot subtract `{integer}` from `f64`
+ --> $DIR/not-suggest-float-literal.rs:24:7
+ |
+LL | x - y
+ | ^ no implementation for `f64 - {integer}`
+ |
+ = help: the trait `Sub<{integer}>` is not implemented for `f64`
+ = help: the following other types implement trait `Sub<Rhs>`:
+ <&'a f64 as Sub<f64>>
+ <&f64 as Sub<&f64>>
+ <f64 as Sub<&f64>>
+ <f64 as Sub>
+
+error[E0277]: cannot multiply `u8` by `{float}`
+ --> $DIR/not-suggest-float-literal.rs:28:7
+ |
+LL | x * 100.0
+ | ^ no implementation for `u8 * {float}`
+ |
+ = help: the trait `Mul<{float}>` is not implemented for `u8`
+ = help: the following other types implement trait `Mul<Rhs>`:
+ <&'a u8 as Mul<u8>>
+ <&u8 as Mul<&u8>>
+ <u8 as Mul<&u8>>
+ <u8 as Mul>
+
+error[E0277]: cannot multiply `f64` by `&str`
+ --> $DIR/not-suggest-float-literal.rs:32:7
+ |
+LL | x * "foo"
+ | ^ no implementation for `f64 * &str`
+ |
+ = help: the trait `Mul<&str>` is not implemented for `f64`
+ = help: the following other types implement trait `Mul<Rhs>`:
+ <&'a f64 as Mul<f64>>
+ <&f64 as Mul<&f64>>
+ <f64 as Mul<&f64>>
+ <f64 as Mul>
+
+error[E0277]: cannot multiply `f64` by `{integer}`
+ --> $DIR/not-suggest-float-literal.rs:37:7
+ |
+LL | x * y
+ | ^ no implementation for `f64 * {integer}`
+ |
+ = help: the trait `Mul<{integer}>` is not implemented for `f64`
+ = help: the following other types implement trait `Mul<Rhs>`:
+ <&'a f64 as Mul<f64>>
+ <&f64 as Mul<&f64>>
+ <f64 as Mul<&f64>>
+ <f64 as Mul>
+
+error[E0277]: cannot divide `u8` by `{float}`
+ --> $DIR/not-suggest-float-literal.rs:41:7
+ |
+LL | x / 100.0
+ | ^ no implementation for `u8 / {float}`
+ |
+ = help: the trait `Div<{float}>` is not implemented for `u8`
+ = help: the following other types implement trait `Div<Rhs>`:
+ <&'a u8 as Div<u8>>
+ <&u8 as Div<&u8>>
+ <u8 as Div<&u8>>
+ <u8 as Div<NonZeroU8>>
+ <u8 as Div>
+
+error[E0277]: cannot divide `f64` by `&str`
+ --> $DIR/not-suggest-float-literal.rs:45:7
+ |
+LL | x / "foo"
+ | ^ no implementation for `f64 / &str`
+ |
+ = help: the trait `Div<&str>` is not implemented for `f64`
+ = help: the following other types implement trait `Div<Rhs>`:
+ <&'a f64 as Div<f64>>
+ <&f64 as Div<&f64>>
+ <f64 as Div<&f64>>
+ <f64 as Div>
+
+error[E0277]: cannot divide `f64` by `{integer}`
+ --> $DIR/not-suggest-float-literal.rs:50:7
+ |
+LL | x / y
+ | ^ no implementation for `f64 / {integer}`
+ |
+ = help: the trait `Div<{integer}>` is not implemented for `f64`
+ = help: the following other types implement trait `Div<Rhs>`:
+ <&'a f64 as Div<f64>>
+ <&f64 as Div<&f64>>
+ <f64 as Div<&f64>>
+ <f64 as Div>
+
+error: aborting due to 12 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/numbers-arithmetic/num-wrapping.rs b/tests/ui/numbers-arithmetic/num-wrapping.rs
new file mode 100644
index 000000000..43b1059f9
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/num-wrapping.rs
@@ -0,0 +1,448 @@
+// run-pass
+#![allow(unused_macros)]
+
+// compile-flags: -C debug-assertions
+//
+// Test std::num::Wrapping<T> for {uN, iN, usize, isize}
+
+#![feature(test)]
+
+extern crate test;
+
+use std::num::Wrapping;
+use std::ops::{
+ Add, Sub, Mul, Div, Rem, BitXor, BitOr, BitAnd,
+ AddAssign, SubAssign, MulAssign, DivAssign, RemAssign, BitXorAssign, BitOrAssign, BitAndAssign,
+ Shl, Shr, ShlAssign, ShrAssign
+};
+use test::black_box;
+
+macro_rules! int_modules {
+ ($(($name:ident, $size:expr),)*) => ($(
+ mod $name {
+ pub const BITS: usize = $size;
+ pub const MAX: $name = $name::MAX;
+ pub const MIN: $name = $name::MIN;
+ }
+ )*)
+}
+
+int_modules! {
+ (i8, 8),
+ (i16, 16),
+ (i32, 32),
+ (i64, 64),
+ (u8, 8),
+ (u16, 16),
+ (u32, 32),
+ (u64, 64),
+}
+
+#[cfg(target_pointer_width = "32")]
+int_modules! {
+ (isize, 32),
+ (usize, 32),
+}
+
+#[cfg(target_pointer_width = "64")]
+int_modules! {
+ (isize, 64),
+ (usize, 64),
+}
+
+fn main() {
+ test_ops();
+ test_op_assigns();
+ test_sh_ops();
+ test_sh_op_assigns();
+}
+
+fn test_ops() {
+ macro_rules! op_test {
+ ($op:ident ($lhs:expr, $rhs:expr) == $ans:expr) => {
+ assert_eq!(black_box(Wrapping($lhs).$op(Wrapping($rhs))), Wrapping($ans));
+ // FIXME(30524): uncomment this test when it's implemented
+ // assert_eq!(black_box(Wrapping($lhs).$op($rhs)), Wrapping($ans));
+ }
+ }
+
+ op_test!(add(i8::MAX, 1) == i8::MIN);
+ op_test!(add(i16::MAX, 1) == i16::MIN);
+ op_test!(add(i32::MAX, 1) == i32::MIN);
+ op_test!(add(i64::MAX, 1) == i64::MIN);
+ op_test!(add(isize::MAX, 1) == isize::MIN);
+
+ op_test!(add(u8::MAX, 1) == 0);
+ op_test!(add(u16::MAX, 1) == 0);
+ op_test!(add(u32::MAX, 1) == 0);
+ op_test!(add(u64::MAX, 1) == 0);
+ op_test!(add(usize::MAX, 1) == 0);
+
+
+ op_test!(sub(i8::MIN, 1) == i8::MAX);
+ op_test!(sub(i16::MIN, 1) == i16::MAX);
+ op_test!(sub(i32::MIN, 1) == i32::MAX);
+ op_test!(sub(i64::MIN, 1) == i64::MAX);
+ op_test!(sub(isize::MIN, 1) == isize::MAX);
+
+ op_test!(sub(0u8, 1) == u8::MAX);
+ op_test!(sub(0u16, 1) == u16::MAX);
+ op_test!(sub(0u32, 1) == u32::MAX);
+ op_test!(sub(0u64, 1) == u64::MAX);
+ op_test!(sub(0usize, 1) == usize::MAX);
+
+
+ op_test!(mul(i8::MAX, 2) == -2);
+ op_test!(mul(i16::MAX, 2) == -2);
+ op_test!(mul(i32::MAX, 2) == -2);
+ op_test!(mul(i64::MAX, 2) == -2);
+ op_test!(mul(isize::MAX, 2) == -2);
+
+ op_test!(mul(u8::MAX, 2) == u8::MAX - 1);
+ op_test!(mul(u16::MAX, 2) == u16::MAX - 1);
+ op_test!(mul(u32::MAX, 2) == u32::MAX - 1);
+ op_test!(mul(u64::MAX, 2) == u64::MAX - 1);
+ op_test!(mul(usize::MAX, 2) == usize::MAX - 1);
+
+
+ op_test!(div(i8::MIN, -1) == i8::MIN);
+ op_test!(div(i16::MIN, -1) == i16::MIN);
+ op_test!(div(i32::MIN, -1) == i32::MIN);
+ op_test!(div(i64::MIN, -1) == i64::MIN);
+ op_test!(div(isize::MIN, -1) == isize::MIN);
+
+
+ op_test!(rem(i8::MIN, -1) == 0);
+ op_test!(rem(i16::MIN, -1) == 0);
+ op_test!(rem(i32::MIN, -1) == 0);
+ op_test!(rem(i64::MIN, -1) == 0);
+ op_test!(rem(isize::MIN, -1) == 0);
+
+ // these are not that interesting, just testing to make sure they are implemented correctly
+ op_test!(bitxor(0b101010i8, 0b100110) == 0b001100);
+ op_test!(bitxor(0b101010i16, 0b100110) == 0b001100);
+ op_test!(bitxor(0b101010i32, 0b100110) == 0b001100);
+ op_test!(bitxor(0b101010i64, 0b100110) == 0b001100);
+ op_test!(bitxor(0b101010isize, 0b100110) == 0b001100);
+
+ op_test!(bitxor(0b101010u8, 0b100110) == 0b001100);
+ op_test!(bitxor(0b101010u16, 0b100110) == 0b001100);
+ op_test!(bitxor(0b101010u32, 0b100110) == 0b001100);
+ op_test!(bitxor(0b101010u64, 0b100110) == 0b001100);
+ op_test!(bitxor(0b101010usize, 0b100110) == 0b001100);
+
+
+ op_test!(bitor(0b101010i8, 0b100110) == 0b101110);
+ op_test!(bitor(0b101010i16, 0b100110) == 0b101110);
+ op_test!(bitor(0b101010i32, 0b100110) == 0b101110);
+ op_test!(bitor(0b101010i64, 0b100110) == 0b101110);
+ op_test!(bitor(0b101010isize, 0b100110) == 0b101110);
+
+ op_test!(bitor(0b101010u8, 0b100110) == 0b101110);
+ op_test!(bitor(0b101010u16, 0b100110) == 0b101110);
+ op_test!(bitor(0b101010u32, 0b100110) == 0b101110);
+ op_test!(bitor(0b101010u64, 0b100110) == 0b101110);
+ op_test!(bitor(0b101010usize, 0b100110) == 0b101110);
+
+
+ op_test!(bitand(0b101010i8, 0b100110) == 0b100010);
+ op_test!(bitand(0b101010i16, 0b100110) == 0b100010);
+ op_test!(bitand(0b101010i32, 0b100110) == 0b100010);
+ op_test!(bitand(0b101010i64, 0b100110) == 0b100010);
+ op_test!(bitand(0b101010isize, 0b100110) == 0b100010);
+
+ op_test!(bitand(0b101010u8, 0b100110) == 0b100010);
+ op_test!(bitand(0b101010u16, 0b100110) == 0b100010);
+ op_test!(bitand(0b101010u32, 0b100110) == 0b100010);
+ op_test!(bitand(0b101010u64, 0b100110) == 0b100010);
+ op_test!(bitand(0b101010usize, 0b100110) == 0b100010);
+}
+
+fn test_op_assigns() {
+ macro_rules! op_assign_test {
+ ($op:ident ($initial:expr, $rhs:expr) == $ans:expr) => {
+ {
+ let mut tmp = Wrapping($initial);
+ tmp = black_box(tmp);
+ tmp.$op(Wrapping($rhs));
+ assert_eq!(black_box(tmp), Wrapping($ans));
+ }
+
+ // also test that a &Wrapping<T> right-hand side is possible
+ {
+ let mut tmp = Wrapping($initial);
+ tmp = black_box(tmp);
+ tmp.$op(&Wrapping($rhs));
+ assert_eq!(black_box(tmp), Wrapping($ans));
+ }
+
+ // FIXME(30524): uncomment this test
+ /*
+ {
+ let mut tmp = Wrapping($initial);
+ tmp = black_box(tmp);
+ tmp.$op($rhs);
+ assert_eq!(black_box(tmp), Wrapping($ans));
+ }
+ */
+ }
+ }
+ op_assign_test!(add_assign(i8::MAX, 1) == i8::MIN);
+ op_assign_test!(add_assign(i16::MAX, 1) == i16::MIN);
+ op_assign_test!(add_assign(i32::MAX, 1) == i32::MIN);
+ op_assign_test!(add_assign(i64::MAX, 1) == i64::MIN);
+ op_assign_test!(add_assign(isize::MAX, 1) == isize::MIN);
+
+ op_assign_test!(add_assign(u8::MAX, 1) == u8::MIN);
+ op_assign_test!(add_assign(u16::MAX, 1) == u16::MIN);
+ op_assign_test!(add_assign(u32::MAX, 1) == u32::MIN);
+ op_assign_test!(add_assign(u64::MAX, 1) == u64::MIN);
+ op_assign_test!(add_assign(usize::MAX, 1) == usize::MIN);
+
+
+ op_assign_test!(sub_assign(i8::MIN, 1) == i8::MAX);
+ op_assign_test!(sub_assign(i16::MIN, 1) == i16::MAX);
+ op_assign_test!(sub_assign(i32::MIN, 1) == i32::MAX);
+ op_assign_test!(sub_assign(i64::MIN, 1) == i64::MAX);
+ op_assign_test!(sub_assign(isize::MIN, 1) == isize::MAX);
+
+ op_assign_test!(sub_assign(u8::MIN, 1) == u8::MAX);
+ op_assign_test!(sub_assign(u16::MIN, 1) == u16::MAX);
+ op_assign_test!(sub_assign(u32::MIN, 1) == u32::MAX);
+ op_assign_test!(sub_assign(u64::MIN, 1) == u64::MAX);
+ op_assign_test!(sub_assign(usize::MIN, 1) == usize::MAX);
+
+
+ op_assign_test!(mul_assign(i8::MAX, 2) == -2);
+ op_assign_test!(mul_assign(i16::MAX, 2) == -2);
+ op_assign_test!(mul_assign(i32::MAX, 2) == -2);
+ op_assign_test!(mul_assign(i64::MAX, 2) == -2);
+ op_assign_test!(mul_assign(isize::MAX, 2) == -2);
+
+ op_assign_test!(mul_assign(u8::MAX, 2) == u8::MAX - 1);
+ op_assign_test!(mul_assign(u16::MAX, 2) == u16::MAX - 1);
+ op_assign_test!(mul_assign(u32::MAX, 2) == u32::MAX - 1);
+ op_assign_test!(mul_assign(u64::MAX, 2) == u64::MAX - 1);
+ op_assign_test!(mul_assign(usize::MAX, 2) == usize::MAX - 1);
+
+
+ op_assign_test!(div_assign(i8::MIN, -1) == i8::MIN);
+ op_assign_test!(div_assign(i16::MIN, -1) == i16::MIN);
+ op_assign_test!(div_assign(i32::MIN, -1) == i32::MIN);
+ op_assign_test!(div_assign(i64::MIN, -1) == i64::MIN);
+ op_assign_test!(div_assign(isize::MIN, -1) == isize::MIN);
+
+
+ op_assign_test!(rem_assign(i8::MIN, -1) == 0);
+ op_assign_test!(rem_assign(i16::MIN, -1) == 0);
+ op_assign_test!(rem_assign(i32::MIN, -1) == 0);
+ op_assign_test!(rem_assign(i64::MIN, -1) == 0);
+ op_assign_test!(rem_assign(isize::MIN, -1) == 0);
+
+
+ // these are not that interesting, just testing to make sure they are implemented correctly
+ op_assign_test!(bitxor_assign(0b101010i8, 0b100110) == 0b001100);
+ op_assign_test!(bitxor_assign(0b101010i16, 0b100110) == 0b001100);
+ op_assign_test!(bitxor_assign(0b101010i32, 0b100110) == 0b001100);
+ op_assign_test!(bitxor_assign(0b101010i64, 0b100110) == 0b001100);
+ op_assign_test!(bitxor_assign(0b101010isize, 0b100110) == 0b001100);
+
+ op_assign_test!(bitxor_assign(0b101010u8, 0b100110) == 0b001100);
+ op_assign_test!(bitxor_assign(0b101010u16, 0b100110) == 0b001100);
+ op_assign_test!(bitxor_assign(0b101010u32, 0b100110) == 0b001100);
+ op_assign_test!(bitxor_assign(0b101010u64, 0b100110) == 0b001100);
+ op_assign_test!(bitxor_assign(0b101010usize, 0b100110) == 0b001100);
+
+
+ op_assign_test!(bitor_assign(0b101010i8, 0b100110) == 0b101110);
+ op_assign_test!(bitor_assign(0b101010i16, 0b100110) == 0b101110);
+ op_assign_test!(bitor_assign(0b101010i32, 0b100110) == 0b101110);
+ op_assign_test!(bitor_assign(0b101010i64, 0b100110) == 0b101110);
+ op_assign_test!(bitor_assign(0b101010isize, 0b100110) == 0b101110);
+
+ op_assign_test!(bitor_assign(0b101010u8, 0b100110) == 0b101110);
+ op_assign_test!(bitor_assign(0b101010u16, 0b100110) == 0b101110);
+ op_assign_test!(bitor_assign(0b101010u32, 0b100110) == 0b101110);
+ op_assign_test!(bitor_assign(0b101010u64, 0b100110) == 0b101110);
+ op_assign_test!(bitor_assign(0b101010usize, 0b100110) == 0b101110);
+
+
+ op_assign_test!(bitand_assign(0b101010i8, 0b100110) == 0b100010);
+ op_assign_test!(bitand_assign(0b101010i16, 0b100110) == 0b100010);
+ op_assign_test!(bitand_assign(0b101010i32, 0b100110) == 0b100010);
+ op_assign_test!(bitand_assign(0b101010i64, 0b100110) == 0b100010);
+ op_assign_test!(bitand_assign(0b101010isize, 0b100110) == 0b100010);
+
+ op_assign_test!(bitand_assign(0b101010u8, 0b100110) == 0b100010);
+ op_assign_test!(bitand_assign(0b101010u16, 0b100110) == 0b100010);
+ op_assign_test!(bitand_assign(0b101010u32, 0b100110) == 0b100010);
+ op_assign_test!(bitand_assign(0b101010u64, 0b100110) == 0b100010);
+ op_assign_test!(bitand_assign(0b101010usize, 0b100110) == 0b100010);
+}
+
+fn test_sh_ops() {
+ macro_rules! sh_test {
+ ($op:ident ($lhs:expr, $rhs:expr) == $ans:expr) => {
+ assert_eq!(black_box(Wrapping($lhs).$op($rhs)), Wrapping($ans));
+ }
+ }
+ // NOTE: This will break for i8 if we ever get i/u128
+ macro_rules! sh_test_all {
+ ($t:ty) => {
+ sh_test!(shl(i8::MAX, (i8::BITS + 1) as $t) == -2);
+ sh_test!(shl(i16::MAX, (i16::BITS + 1) as $t) == -2);
+ sh_test!(shl(i32::MAX, (i32::BITS + 1) as $t) == -2);
+ sh_test!(shl(i64::MAX, (i64::BITS + 1) as $t) == -2);
+ sh_test!(shl(isize::MAX, (isize::BITS + 1) as $t) == -2);
+
+ sh_test!(shl(u8::MAX, (u8::BITS + 1) as $t) == u8::MAX - 1);
+ sh_test!(shl(u16::MAX, (u16::BITS + 1) as $t) == u16::MAX - 1);
+ sh_test!(shl(u32::MAX, (u32::BITS + 1) as $t) == u32::MAX - 1);
+ sh_test!(shl(u64::MAX, (u64::BITS + 1) as $t) == u64::MAX - 1);
+ sh_test!(shl(usize::MAX, (usize::BITS + 1) as $t) == usize::MAX - 1);
+
+
+ sh_test!(shr(i8::MAX, (i8::BITS + 1) as $t) == i8::MAX / 2);
+ sh_test!(shr(i16::MAX, (i16::BITS + 1) as $t) == i16::MAX / 2);
+ sh_test!(shr(i32::MAX, (i32::BITS + 1) as $t) == i32::MAX / 2);
+ sh_test!(shr(i64::MAX, (i64::BITS + 1) as $t) == i64::MAX / 2);
+ sh_test!(shr(isize::MAX, (isize::BITS + 1) as $t) == isize::MAX / 2);
+
+ sh_test!(shr(u8::MAX, (u8::BITS + 1) as $t) == u8::MAX / 2);
+ sh_test!(shr(u16::MAX, (u16::BITS + 1) as $t) == u16::MAX / 2);
+ sh_test!(shr(u32::MAX, (u32::BITS + 1) as $t) == u32::MAX / 2);
+ sh_test!(shr(u64::MAX, (u64::BITS + 1) as $t) == u64::MAX / 2);
+ sh_test!(shr(usize::MAX, (usize::BITS + 1) as $t) == usize::MAX / 2);
+ }
+ }
+ macro_rules! sh_test_negative_all {
+ ($t:ty) => {
+ sh_test!(shr(i8::MAX, -((i8::BITS + 1) as $t)) == -2);
+ sh_test!(shr(i16::MAX, -((i16::BITS + 1) as $t)) == -2);
+ sh_test!(shr(i32::MAX, -((i32::BITS + 1) as $t)) == -2);
+ sh_test!(shr(i64::MAX, -((i64::BITS + 1) as $t)) == -2);
+ sh_test!(shr(isize::MAX, -((isize::BITS + 1) as $t)) == -2);
+
+ sh_test!(shr(u8::MAX, -((u8::BITS + 1) as $t)) == u8::MAX - 1);
+ sh_test!(shr(u16::MAX, -((u16::BITS + 1) as $t)) == u16::MAX - 1);
+ sh_test!(shr(u32::MAX, -((u32::BITS + 1) as $t)) == u32::MAX - 1);
+ sh_test!(shr(u64::MAX, -((u64::BITS + 1) as $t)) == u64::MAX - 1);
+ sh_test!(shr(usize::MAX, -((usize::BITS + 1) as $t)) == usize::MAX - 1);
+
+
+ sh_test!(shl(i8::MAX, -((i8::BITS + 1) as $t)) == i8::MAX / 2);
+ sh_test!(shl(i16::MAX, -((i16::BITS + 1) as $t)) == i16::MAX / 2);
+ sh_test!(shl(i32::MAX, -((i32::BITS + 1) as $t)) == i32::MAX / 2);
+ sh_test!(shl(i64::MAX, -((i64::BITS + 1) as $t)) == i64::MAX / 2);
+ sh_test!(shl(isize::MAX, -((isize::BITS + 1) as $t)) == isize::MAX / 2);
+
+ sh_test!(shl(u8::MAX, -((u8::BITS + 1) as $t)) == u8::MAX / 2);
+ sh_test!(shl(u16::MAX, -((u16::BITS + 1) as $t)) == u16::MAX / 2);
+ sh_test!(shl(u32::MAX, -((u32::BITS + 1) as $t)) == u32::MAX / 2);
+ sh_test!(shl(u64::MAX, -((u64::BITS + 1) as $t)) == u64::MAX / 2);
+ sh_test!(shl(usize::MAX, -((usize::BITS + 1) as $t)) == usize::MAX / 2);
+ }
+ }
+ // FIXME(#23545): Uncomment the remaining tests
+ //sh_test_all!(i8);
+ //sh_test_all!(u8);
+ //sh_test_all!(i16);
+ //sh_test_all!(u16);
+ //sh_test_all!(i32);
+ //sh_test_all!(u32);
+ //sh_test_all!(i64);
+ //sh_test_all!(u64);
+ //sh_test_all!(isize);
+ sh_test_all!(usize);
+
+ //sh_test_negative_all!(i8);
+ //sh_test_negative_all!(i16);
+ //sh_test_negative_all!(i32);
+ //sh_test_negative_all!(i64);
+ //sh_test_negative_all!(isize);
+}
+
+fn test_sh_op_assigns() {
+ macro_rules! sh_assign_test {
+ ($op:ident ($initial:expr, $rhs:expr) == $ans:expr) => {{
+ let mut tmp = Wrapping($initial);
+ tmp = black_box(tmp);
+ tmp.$op($rhs);
+ assert_eq!(black_box(tmp), Wrapping($ans));
+ }}
+ }
+ macro_rules! sh_assign_test_all {
+ ($t:ty) => {
+ sh_assign_test!(shl_assign(i8::MAX, (i8::BITS + 1) as $t) == -2);
+ sh_assign_test!(shl_assign(i16::MAX, (i16::BITS + 1) as $t) == -2);
+ sh_assign_test!(shl_assign(i32::MAX, (i32::BITS + 1) as $t) == -2);
+ sh_assign_test!(shl_assign(i64::MAX, (i64::BITS + 1) as $t) == -2);
+ sh_assign_test!(shl_assign(isize::MAX, (isize::BITS + 1) as $t) == -2);
+
+ sh_assign_test!(shl_assign(u8::MAX, (u8::BITS + 1) as $t) == u8::MAX - 1);
+ sh_assign_test!(shl_assign(u16::MAX, (u16::BITS + 1) as $t) == u16::MAX - 1);
+ sh_assign_test!(shl_assign(u32::MAX, (u32::BITS + 1) as $t) == u32::MAX - 1);
+ sh_assign_test!(shl_assign(u64::MAX, (u64::BITS + 1) as $t) == u64::MAX - 1);
+ sh_assign_test!(shl_assign(usize::MAX, (usize::BITS + 1) as $t) == usize::MAX - 1);
+
+
+ sh_assign_test!(shr_assign(i8::MAX, (i8::BITS + 1) as $t) == i8::MAX / 2);
+ sh_assign_test!(shr_assign(i16::MAX, (i16::BITS + 1) as $t) == i16::MAX / 2);
+ sh_assign_test!(shr_assign(i32::MAX, (i32::BITS + 1) as $t) == i32::MAX / 2);
+ sh_assign_test!(shr_assign(i64::MAX, (i64::BITS + 1) as $t) == i64::MAX / 2);
+ sh_assign_test!(shr_assign(isize::MAX, (isize::BITS + 1) as $t) == isize::MAX / 2);
+
+ sh_assign_test!(shr_assign(u8::MAX, (u8::BITS + 1) as $t) == u8::MAX / 2);
+ sh_assign_test!(shr_assign(u16::MAX, (u16::BITS + 1) as $t) == u16::MAX / 2);
+ sh_assign_test!(shr_assign(u32::MAX, (u32::BITS + 1) as $t) == u32::MAX / 2);
+ sh_assign_test!(shr_assign(u64::MAX, (u64::BITS + 1) as $t) == u64::MAX / 2);
+ sh_assign_test!(shr_assign(usize::MAX, (usize::BITS + 1) as $t) == usize::MAX / 2);
+ }
+ }
+ macro_rules! sh_assign_test_negative_all {
+ ($t:ty) => {
+ sh_assign_test!(shr_assign(i8::MAX, -((i8::BITS + 1) as $t)) == -2);
+ sh_assign_test!(shr_assign(i16::MAX, -((i16::BITS + 1) as $t)) == -2);
+ sh_assign_test!(shr_assign(i32::MAX, -((i32::BITS + 1) as $t)) == -2);
+ sh_assign_test!(shr_assign(i64::MAX, -((i64::BITS + 1) as $t)) == -2);
+ sh_assign_test!(shr_assign(isize::MAX, -((isize::BITS + 1) as $t)) == -2);
+
+ sh_assign_test!(shr_assign(u8::MAX, -((u8::BITS + 1) as $t)) == u8::MAX - 1);
+ sh_assign_test!(shr_assign(u16::MAX, -((u16::BITS + 1) as $t)) == u16::MAX - 1);
+ sh_assign_test!(shr_assign(u32::MAX, -((u32::BITS + 1) as $t)) == u32::MAX - 1);
+ sh_assign_test!(shr_assign(u64::MAX, -((u64::BITS + 1) as $t)) == u64::MAX - 1);
+ sh_assign_test!(shr_assign(usize::MAX, -((usize::BITS + 1) as $t)) == usize::MAX - 1);
+
+
+ sh_assign_test!(shl_assign(i8::MAX, -((i8::BITS + 1) as $t)) == i8::MAX / 2);
+ sh_assign_test!(shl_assign(i16::MAX, -((i16::BITS + 1) as $t)) == i16::MAX / 2);
+ sh_assign_test!(shl_assign(i32::MAX, -((i32::BITS + 1) as $t)) == i32::MAX / 2);
+ sh_assign_test!(shl_assign(i64::MAX, -((i64::BITS + 1) as $t)) == i64::MAX / 2);
+ sh_assign_test!(shl_assign(isize::MAX, -((isize::BITS + 1) as $t)) == isize::MAX / 2);
+
+ sh_assign_test!(shl_assign(u8::MAX, -((u8::BITS + 1) as $t)) == u8::MAX / 2);
+ sh_assign_test!(shl_assign(u16::MAX, -((u16::BITS + 1) as $t)) == u16::MAX / 2);
+ sh_assign_test!(shl_assign(u32::MAX, -((u32::BITS + 1) as $t)) == u32::MAX / 2);
+ sh_assign_test!(shl_assign(u64::MAX, -((u64::BITS + 1) as $t)) == u64::MAX / 2);
+ sh_assign_test!(shl_assign(usize::MAX, -((usize::BITS + 1) as $t)) == usize::MAX / 2);
+ }
+ }
+
+ // FIXME(#23545): Uncomment the remaining tests
+ //sh_assign_test_all!(i8);
+ //sh_assign_test_all!(u8);
+ //sh_assign_test_all!(i16);
+ //sh_assign_test_all!(u16);
+ //sh_assign_test_all!(i32);
+ //sh_assign_test_all!(u32);
+ //sh_assign_test_all!(i64);
+ //sh_assign_test_all!(u64);
+ //sh_assign_test_all!(isize);
+ sh_assign_test_all!(usize);
+
+ //sh_assign_test_negative_all!(i8);
+ //sh_assign_test_negative_all!(i16);
+ //sh_assign_test_negative_all!(i32);
+ //sh_assign_test_negative_all!(i64);
+ //sh_assign_test_negative_all!(isize);
+}
diff --git a/tests/ui/numbers-arithmetic/numeric-method-autoexport.rs b/tests/ui/numbers-arithmetic/numeric-method-autoexport.rs
new file mode 100644
index 000000000..5798c2591
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/numeric-method-autoexport.rs
@@ -0,0 +1,25 @@
+// run-pass
+// This file is intended to test only that methods are automatically
+// reachable for each numeric type, for each exported impl, with no imports
+// necessary. Testing the methods of the impls is done within the source
+// file for each numeric type.
+
+use std::ops::Add;
+
+pub fn main() {
+// ints
+ // num
+ assert_eq!(15_isize.add(6_isize), 21_isize);
+ assert_eq!(15_i8.add(6i8), 21_i8);
+ assert_eq!(15_i16.add(6i16), 21_i16);
+ assert_eq!(15_i32.add(6i32), 21_i32);
+ assert_eq!(15_i64.add(6i64), 21_i64);
+
+// uints
+ // num
+ assert_eq!(15_usize.add(6_usize), 21_usize);
+ assert_eq!(15_u8.add(6u8), 21_u8);
+ assert_eq!(15_u16.add(6u16), 21_u16);
+ assert_eq!(15_u32.add(6u32), 21_u32);
+ assert_eq!(15_u64.add(6u64), 21_u64);
+}
diff --git a/tests/ui/numbers-arithmetic/overflowing-add.rs b/tests/ui/numbers-arithmetic/overflowing-add.rs
new file mode 100644
index 000000000..b0f22a74b
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-add.rs
@@ -0,0 +1,10 @@
+// run-fail
+// error-pattern:thread 'main' panicked at 'attempt to add with overflow'
+// compile-flags: -C debug-assertions
+// ignore-emscripten no processes
+
+#![allow(arithmetic_overflow)]
+
+fn main() {
+ let _x = 200u8 + 200u8 + 200u8;
+}
diff --git a/tests/ui/numbers-arithmetic/overflowing-lsh-1.rs b/tests/ui/numbers-arithmetic/overflowing-lsh-1.rs
new file mode 100644
index 000000000..7f8b0c877
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-lsh-1.rs
@@ -0,0 +1,9 @@
+// build-fail
+// compile-flags: -C debug-assertions
+
+#![deny(arithmetic_overflow)]
+
+fn main() {
+ let _x = 1_i32 << 32;
+ //~^ ERROR: this arithmetic operation will overflow
+}
diff --git a/tests/ui/numbers-arithmetic/overflowing-lsh-1.stderr b/tests/ui/numbers-arithmetic/overflowing-lsh-1.stderr
new file mode 100644
index 000000000..434c9d5b4
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-lsh-1.stderr
@@ -0,0 +1,14 @@
+error: this arithmetic operation will overflow
+ --> $DIR/overflowing-lsh-1.rs:7:14
+ |
+LL | let _x = 1_i32 << 32;
+ | ^^^^^^^^^^^ attempt to shift left by `32_i32`, which would overflow
+ |
+note: the lint level is defined here
+ --> $DIR/overflowing-lsh-1.rs:4:9
+ |
+LL | #![deny(arithmetic_overflow)]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/numbers-arithmetic/overflowing-lsh-2.rs b/tests/ui/numbers-arithmetic/overflowing-lsh-2.rs
new file mode 100644
index 000000000..76718ecd1
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-lsh-2.rs
@@ -0,0 +1,9 @@
+// build-fail
+// compile-flags: -C debug-assertions
+
+#![deny(arithmetic_overflow)]
+
+fn main() {
+ let _x = 1 << -1;
+ //~^ ERROR: this arithmetic operation will overflow
+}
diff --git a/tests/ui/numbers-arithmetic/overflowing-lsh-2.stderr b/tests/ui/numbers-arithmetic/overflowing-lsh-2.stderr
new file mode 100644
index 000000000..c3b44e5a0
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-lsh-2.stderr
@@ -0,0 +1,14 @@
+error: this arithmetic operation will overflow
+ --> $DIR/overflowing-lsh-2.rs:7:14
+ |
+LL | let _x = 1 << -1;
+ | ^^^^^^^ attempt to shift left by `-1_i32`, which would overflow
+ |
+note: the lint level is defined here
+ --> $DIR/overflowing-lsh-2.rs:4:9
+ |
+LL | #![deny(arithmetic_overflow)]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/numbers-arithmetic/overflowing-lsh-3.rs b/tests/ui/numbers-arithmetic/overflowing-lsh-3.rs
new file mode 100644
index 000000000..b2bdd09bf
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-lsh-3.rs
@@ -0,0 +1,9 @@
+// build-fail
+// compile-flags: -C debug-assertions
+
+#![deny(arithmetic_overflow)]
+
+fn main() {
+ let _x = 1_u64 << 64;
+ //~^ ERROR: this arithmetic operation will overflow
+}
diff --git a/tests/ui/numbers-arithmetic/overflowing-lsh-3.stderr b/tests/ui/numbers-arithmetic/overflowing-lsh-3.stderr
new file mode 100644
index 000000000..9d6479bd7
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-lsh-3.stderr
@@ -0,0 +1,14 @@
+error: this arithmetic operation will overflow
+ --> $DIR/overflowing-lsh-3.rs:7:14
+ |
+LL | let _x = 1_u64 << 64;
+ | ^^^^^^^^^^^ attempt to shift left by `64_i32`, which would overflow
+ |
+note: the lint level is defined here
+ --> $DIR/overflowing-lsh-3.rs:4:9
+ |
+LL | #![deny(arithmetic_overflow)]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/numbers-arithmetic/overflowing-lsh-4.rs b/tests/ui/numbers-arithmetic/overflowing-lsh-4.rs
new file mode 100644
index 000000000..1042bfcb3
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-lsh-4.rs
@@ -0,0 +1,24 @@
+// build-fail
+// compile-flags: -C debug-assertions
+
+// This function is checking that our automatic truncation does not
+// sidestep the overflow checking.
+
+#![deny(arithmetic_overflow)]
+
+fn main() {
+ // this signals overflow when checking is on
+ let x = 1_i8 << 17;
+ //~^ ERROR: this arithmetic operation will overflow
+
+ // ... but when checking is off, the fallback will truncate the
+ // input to its lower three bits (= 1). Note that this is *not*
+ // the behavior of the x86 processor for 8- and 16-bit types,
+ // but it is necessary to avoid undefined behavior from LLVM.
+ //
+ // We check that here, by ensuring the result has only been
+ // shifted by one place; if overflow checking is turned off, then
+ // this assertion will pass (and the compiletest driver will
+ // report that the test did not produce the error expected above).
+ assert_eq!(x, 2_i8);
+}
diff --git a/tests/ui/numbers-arithmetic/overflowing-lsh-4.stderr b/tests/ui/numbers-arithmetic/overflowing-lsh-4.stderr
new file mode 100644
index 000000000..2bb5b6a6d
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-lsh-4.stderr
@@ -0,0 +1,14 @@
+error: this arithmetic operation will overflow
+ --> $DIR/overflowing-lsh-4.rs:11:13
+ |
+LL | let x = 1_i8 << 17;
+ | ^^^^^^^^^^ attempt to shift left by `17_i32`, which would overflow
+ |
+note: the lint level is defined here
+ --> $DIR/overflowing-lsh-4.rs:7:9
+ |
+LL | #![deny(arithmetic_overflow)]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/numbers-arithmetic/overflowing-mul.rs b/tests/ui/numbers-arithmetic/overflowing-mul.rs
new file mode 100644
index 000000000..34ab5d8fa
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-mul.rs
@@ -0,0 +1,10 @@
+// run-fail
+// error-pattern:thread 'main' panicked at 'attempt to multiply with overflow'
+// ignore-emscripten no processes
+// compile-flags: -C debug-assertions
+
+#![allow(arithmetic_overflow)]
+
+fn main() {
+ let x = 200u8 * 4;
+}
diff --git a/tests/ui/numbers-arithmetic/overflowing-neg.rs b/tests/ui/numbers-arithmetic/overflowing-neg.rs
new file mode 100644
index 000000000..df1198053
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-neg.rs
@@ -0,0 +1,10 @@
+// run-fail
+// error-pattern:thread 'main' panicked at 'attempt to negate with overflow'
+// ignore-emscripten no processes
+// compile-flags: -C debug-assertions
+
+#![allow(arithmetic_overflow)]
+
+fn main() {
+ let _x = -i8::MIN;
+}
diff --git a/tests/ui/numbers-arithmetic/overflowing-pow-signed.rs b/tests/ui/numbers-arithmetic/overflowing-pow-signed.rs
new file mode 100644
index 000000000..b59efe6f2
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-pow-signed.rs
@@ -0,0 +1,8 @@
+// run-fail
+// error-pattern:thread 'main' panicked at 'attempt to multiply with overflow'
+// ignore-emscripten no processes
+// compile-flags: -C debug-assertions
+
+fn main() {
+ let _x = 2i32.pow(1024);
+}
diff --git a/tests/ui/numbers-arithmetic/overflowing-pow-unsigned.rs b/tests/ui/numbers-arithmetic/overflowing-pow-unsigned.rs
new file mode 100644
index 000000000..f2643c164
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-pow-unsigned.rs
@@ -0,0 +1,8 @@
+// run-fail
+// error-pattern:thread 'main' panicked at 'attempt to multiply with overflow'
+// ignore-emscripten no processes
+// compile-flags: -C debug-assertions
+
+fn main() {
+ let _x = 2u32.pow(1024);
+}
diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-1.rs b/tests/ui/numbers-arithmetic/overflowing-rsh-1.rs
new file mode 100644
index 000000000..80593c865
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-rsh-1.rs
@@ -0,0 +1,9 @@
+// build-fail
+// compile-flags: -C debug-assertions
+
+#![deny(arithmetic_overflow)]
+
+fn main() {
+ let _x = -1_i32 >> 32;
+ //~^ ERROR: this arithmetic operation will overflow
+}
diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-1.stderr b/tests/ui/numbers-arithmetic/overflowing-rsh-1.stderr
new file mode 100644
index 000000000..b2b3114d1
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-rsh-1.stderr
@@ -0,0 +1,14 @@
+error: this arithmetic operation will overflow
+ --> $DIR/overflowing-rsh-1.rs:7:14
+ |
+LL | let _x = -1_i32 >> 32;
+ | ^^^^^^^^^^^^ attempt to shift right by `32_i32`, which would overflow
+ |
+note: the lint level is defined here
+ --> $DIR/overflowing-rsh-1.rs:4:9
+ |
+LL | #![deny(arithmetic_overflow)]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-2.rs b/tests/ui/numbers-arithmetic/overflowing-rsh-2.rs
new file mode 100644
index 000000000..917352bfc
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-rsh-2.rs
@@ -0,0 +1,9 @@
+// build-fail
+// compile-flags: -C debug-assertions
+
+#![deny(arithmetic_overflow)]
+
+fn main() {
+ let _x = -1_i32 >> -1;
+ //~^ ERROR: this arithmetic operation will overflow
+}
diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-2.stderr b/tests/ui/numbers-arithmetic/overflowing-rsh-2.stderr
new file mode 100644
index 000000000..ad18c3bb7
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-rsh-2.stderr
@@ -0,0 +1,14 @@
+error: this arithmetic operation will overflow
+ --> $DIR/overflowing-rsh-2.rs:7:14
+ |
+LL | let _x = -1_i32 >> -1;
+ | ^^^^^^^^^^^^ attempt to shift right by `-1_i32`, which would overflow
+ |
+note: the lint level is defined here
+ --> $DIR/overflowing-rsh-2.rs:4:9
+ |
+LL | #![deny(arithmetic_overflow)]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-3.rs b/tests/ui/numbers-arithmetic/overflowing-rsh-3.rs
new file mode 100644
index 000000000..1e052990a
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-rsh-3.rs
@@ -0,0 +1,9 @@
+// build-fail
+// compile-flags: -C debug-assertions
+
+#![deny(arithmetic_overflow)]
+
+fn main() {
+ let _x = -1_i64 >> 64;
+ //~^ ERROR: this arithmetic operation will overflow
+}
diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-3.stderr b/tests/ui/numbers-arithmetic/overflowing-rsh-3.stderr
new file mode 100644
index 000000000..37d02e09d
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-rsh-3.stderr
@@ -0,0 +1,14 @@
+error: this arithmetic operation will overflow
+ --> $DIR/overflowing-rsh-3.rs:7:14
+ |
+LL | let _x = -1_i64 >> 64;
+ | ^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+ |
+note: the lint level is defined here
+ --> $DIR/overflowing-rsh-3.rs:4:9
+ |
+LL | #![deny(arithmetic_overflow)]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-4.rs b/tests/ui/numbers-arithmetic/overflowing-rsh-4.rs
new file mode 100644
index 000000000..be918becd
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-rsh-4.rs
@@ -0,0 +1,24 @@
+// build-fail
+// compile-flags: -C debug-assertions
+
+// This function is checking that our (type-based) automatic
+// truncation does not sidestep the overflow checking.
+
+#![deny(arithmetic_overflow)]
+
+fn main() {
+ // this signals overflow when checking is on
+ let x = 2_i8 >> 17;
+ //~^ ERROR: this arithmetic operation will overflow
+
+ // ... but when checking is off, the fallback will truncate the
+ // input to its lower three bits (= 1). Note that this is *not*
+ // the behavior of the x86 processor for 8- and 16-bit types,
+ // but it is necessary to avoid undefined behavior from LLVM.
+ //
+ // We check that here, by ensuring the result is not zero; if
+ // overflow checking is turned off, then this assertion will pass
+ // (and the compiletest driver will report that the test did not
+ // produce the error expected above).
+ assert_eq!(x, 1_i8);
+}
diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-4.stderr b/tests/ui/numbers-arithmetic/overflowing-rsh-4.stderr
new file mode 100644
index 000000000..692602c07
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-rsh-4.stderr
@@ -0,0 +1,14 @@
+error: this arithmetic operation will overflow
+ --> $DIR/overflowing-rsh-4.rs:11:13
+ |
+LL | let x = 2_i8 >> 17;
+ | ^^^^^^^^^^ attempt to shift right by `17_i32`, which would overflow
+ |
+note: the lint level is defined here
+ --> $DIR/overflowing-rsh-4.rs:7:9
+ |
+LL | #![deny(arithmetic_overflow)]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-5.rs b/tests/ui/numbers-arithmetic/overflowing-rsh-5.rs
new file mode 100644
index 000000000..f75e779ed
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-rsh-5.rs
@@ -0,0 +1,9 @@
+// build-fail
+// compile-flags: -C debug-assertions
+
+#![deny(arithmetic_overflow)]
+
+fn main() {
+ let _n = 1i64 >> [64][0];
+ //~^ ERROR: this arithmetic operation will overflow
+}
diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-5.stderr b/tests/ui/numbers-arithmetic/overflowing-rsh-5.stderr
new file mode 100644
index 000000000..e3b5859df
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-rsh-5.stderr
@@ -0,0 +1,14 @@
+error: this arithmetic operation will overflow
+ --> $DIR/overflowing-rsh-5.rs:7:14
+ |
+LL | let _n = 1i64 >> [64][0];
+ | ^^^^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+ |
+note: the lint level is defined here
+ --> $DIR/overflowing-rsh-5.rs:4:9
+ |
+LL | #![deny(arithmetic_overflow)]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-6.rs b/tests/ui/numbers-arithmetic/overflowing-rsh-6.rs
new file mode 100644
index 000000000..f75e779ed
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-rsh-6.rs
@@ -0,0 +1,9 @@
+// build-fail
+// compile-flags: -C debug-assertions
+
+#![deny(arithmetic_overflow)]
+
+fn main() {
+ let _n = 1i64 >> [64][0];
+ //~^ ERROR: this arithmetic operation will overflow
+}
diff --git a/tests/ui/numbers-arithmetic/overflowing-rsh-6.stderr b/tests/ui/numbers-arithmetic/overflowing-rsh-6.stderr
new file mode 100644
index 000000000..a3475c04c
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-rsh-6.stderr
@@ -0,0 +1,14 @@
+error: this arithmetic operation will overflow
+ --> $DIR/overflowing-rsh-6.rs:7:14
+ |
+LL | let _n = 1i64 >> [64][0];
+ | ^^^^^^^^^^^^^^^ attempt to shift right by `64_i32`, which would overflow
+ |
+note: the lint level is defined here
+ --> $DIR/overflowing-rsh-6.rs:4:9
+ |
+LL | #![deny(arithmetic_overflow)]
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/numbers-arithmetic/overflowing-sub.rs b/tests/ui/numbers-arithmetic/overflowing-sub.rs
new file mode 100644
index 000000000..66685ac96
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/overflowing-sub.rs
@@ -0,0 +1,10 @@
+// run-fail
+// error-pattern:thread 'main' panicked at 'attempt to subtract with overflow'
+// ignore-emscripten no processes
+// compile-flags: -C debug-assertions
+
+#![allow(arithmetic_overflow)]
+
+fn main() {
+ let _x = 42u8 - (42u8 + 1);
+}
diff --git a/tests/ui/numbers-arithmetic/promoted_overflow.rs b/tests/ui/numbers-arithmetic/promoted_overflow.rs
new file mode 100644
index 000000000..ba168f773
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/promoted_overflow.rs
@@ -0,0 +1,13 @@
+#![allow(arithmetic_overflow)]
+
+// run-fail
+// error-pattern: overflow
+// compile-flags: -C overflow-checks=yes
+// for some reason, fails to match error string on
+// wasm32-unknown-unknown with stripped debuginfo and symbols,
+// so don't strip it
+// compile-flags:-Cstrip=none
+
+fn main() {
+ let x: &'static u32 = &(0u32 - 1);
+}
diff --git a/tests/ui/numbers-arithmetic/promoted_overflow_opt.rs b/tests/ui/numbers-arithmetic/promoted_overflow_opt.rs
new file mode 100644
index 000000000..76279e913
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/promoted_overflow_opt.rs
@@ -0,0 +1,8 @@
+// run-pass
+
+// compile-flags: -O
+
+fn main() {
+ let x = &(0u32 - 1);
+ assert_eq!(*x, u32::MAX)
+}
diff --git a/tests/ui/numbers-arithmetic/saturating-float-casts-impl.rs b/tests/ui/numbers-arithmetic/saturating-float-casts-impl.rs
new file mode 100644
index 000000000..4c6929d66
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/saturating-float-casts-impl.rs
@@ -0,0 +1,503 @@
+// ignore-test
+
+// Tests saturating float->int casts. See u128-as-f32.rs for the opposite direction.
+//
+// Some of these tests come from a similar file in miri,
+// tests/run-pass/float.rs. Individual test cases are potentially duplicated
+// with the previously existing tests, but since this runs so quickly anyway,
+// we're not spending the time to figure out exactly which ones should be
+// merged.
+
+extern crate test;
+
+use self::test::black_box;
+
+macro_rules! test {
+ ($val:expr, $src_ty:ident -> $dest_ty:ident, $expected:expr) => (
+ // black_box disables constant evaluation to test run-time conversions:
+ assert_eq!(black_box::<$src_ty>($val) as $dest_ty, $expected,
+ "run-time {} -> {}", stringify!($src_ty), stringify!($dest_ty));
+
+ {
+ const X: $src_ty = $val;
+ const Y: $dest_ty = X as $dest_ty;
+ assert_eq!(Y, $expected,
+ "const eval {} -> {}", stringify!($src_ty), stringify!($dest_ty));
+ }
+ );
+
+ ($fval:expr, f* -> $ity:ident, $ival:expr) => (
+ test!($fval, f32 -> $ity, $ival);
+ test!($fval, f64 -> $ity, $ival);
+ )
+}
+
+macro_rules! common_fptoi_tests {
+ ($fty:ident -> $($ity:ident)+) => ({ $(
+ test!($fty::NAN, $fty -> $ity, 0);
+ test!($fty::INFINITY, $fty -> $ity, $ity::MAX);
+ test!($fty::NEG_INFINITY, $fty -> $ity, $ity::MIN);
+ // These two tests are not solely float->int tests, in particular the latter relies on
+ // `u128::MAX as f32` not being UB. But that's okay, since this file tests int->float
+ // as well, the test is just slightly misplaced.
+ test!($ity::MIN as $fty, $fty -> $ity, $ity::MIN);
+ test!($ity::MAX as $fty, $fty -> $ity, $ity::MAX);
+ test!(0., $fty -> $ity, 0);
+ test!($fty::MIN_POSITIVE, $fty -> $ity, 0);
+ test!(-0.9, $fty -> $ity, 0);
+ test!(1., $fty -> $ity, 1);
+ test!(42., $fty -> $ity, 42);
+ )+ });
+
+ (f* -> $($ity:ident)+) => ({
+ common_fptoi_tests!(f32 -> $($ity)+);
+ common_fptoi_tests!(f64 -> $($ity)+);
+ })
+}
+
+macro_rules! fptoui_tests {
+ ($fty: ident -> $($ity: ident)+) => ({ $(
+ test!(-0., $fty -> $ity, 0);
+ test!(-$fty::MIN_POSITIVE, $fty -> $ity, 0);
+ test!(-0.99999994, $fty -> $ity, 0);
+ test!(-1., $fty -> $ity, 0);
+ test!(-100., $fty -> $ity, 0);
+ test!(#[allow(overflowing_literals)] -1e50, $fty -> $ity, 0);
+ test!(#[allow(overflowing_literals)] -1e130, $fty -> $ity, 0);
+ )+ });
+
+ (f* -> $($ity:ident)+) => ({
+ fptoui_tests!(f32 -> $($ity)+);
+ fptoui_tests!(f64 -> $($ity)+);
+ })
+}
+
+use std::fmt::Debug;
+
+// Helper function to avoid promotion so that this tests "run-time" casts, not CTFE.
+#[track_caller]
+#[inline(never)]
+fn assert_eq<T: PartialEq + Debug>(x: T, y: T) {
+ assert_eq!(x, y);
+}
+
+trait FloatToInt<Int>: Copy {
+ fn cast(self) -> Int;
+ unsafe fn cast_unchecked(self) -> Int;
+}
+
+impl FloatToInt<i8> for f32 {
+ fn cast(self) -> i8 {
+ self as _
+ }
+ unsafe fn cast_unchecked(self) -> i8 {
+ self.to_int_unchecked()
+ }
+}
+impl FloatToInt<i32> for f32 {
+ fn cast(self) -> i32 {
+ self as _
+ }
+ unsafe fn cast_unchecked(self) -> i32 {
+ self.to_int_unchecked()
+ }
+}
+impl FloatToInt<u32> for f32 {
+ fn cast(self) -> u32 {
+ self as _
+ }
+ unsafe fn cast_unchecked(self) -> u32 {
+ self.to_int_unchecked()
+ }
+}
+impl FloatToInt<i64> for f32 {
+ fn cast(self) -> i64 {
+ self as _
+ }
+ unsafe fn cast_unchecked(self) -> i64 {
+ self.to_int_unchecked()
+ }
+}
+impl FloatToInt<u64> for f32 {
+ fn cast(self) -> u64 {
+ self as _
+ }
+ unsafe fn cast_unchecked(self) -> u64 {
+ self.to_int_unchecked()
+ }
+}
+
+impl FloatToInt<i8> for f64 {
+ fn cast(self) -> i8 {
+ self as _
+ }
+ unsafe fn cast_unchecked(self) -> i8 {
+ self.to_int_unchecked()
+ }
+}
+impl FloatToInt<i32> for f64 {
+ fn cast(self) -> i32 {
+ self as _
+ }
+ unsafe fn cast_unchecked(self) -> i32 {
+ self.to_int_unchecked()
+ }
+}
+impl FloatToInt<u32> for f64 {
+ fn cast(self) -> u32 {
+ self as _
+ }
+ unsafe fn cast_unchecked(self) -> u32 {
+ self.to_int_unchecked()
+ }
+}
+impl FloatToInt<i64> for f64 {
+ fn cast(self) -> i64 {
+ self as _
+ }
+ unsafe fn cast_unchecked(self) -> i64 {
+ self.to_int_unchecked()
+ }
+}
+impl FloatToInt<u64> for f64 {
+ fn cast(self) -> u64 {
+ self as _
+ }
+ unsafe fn cast_unchecked(self) -> u64 {
+ self.to_int_unchecked()
+ }
+}
+// FIXME emscripten does not support i128
+#[cfg(not(target_os = "emscripten"))]
+impl FloatToInt<i128> for f64 {
+ fn cast(self) -> i128 {
+ self as _
+ }
+ unsafe fn cast_unchecked(self) -> i128 {
+ self.to_int_unchecked()
+ }
+}
+// FIXME emscripten does not support i128
+#[cfg(not(target_os = "emscripten"))]
+impl FloatToInt<u128> for f64 {
+ fn cast(self) -> u128 {
+ self as _
+ }
+ unsafe fn cast_unchecked(self) -> u128 {
+ self.to_int_unchecked()
+ }
+}
+
+/// Test this cast both via `as` and via `to_int_unchecked` (i.e., it must not saturate).
+#[track_caller]
+#[inline(never)]
+fn test_both_cast<F, I>(x: F, y: I)
+where
+ F: FloatToInt<I>,
+ I: PartialEq + Debug,
+{
+ assert_eq!(x.cast(), y);
+ assert_eq!(unsafe { x.cast_unchecked() }, y);
+}
+
+fn casts() {
+ // f32 -> i8
+ test_both_cast::<f32, i8>(127.99, 127);
+ test_both_cast::<f32, i8>(-128.99, -128);
+
+ // f32 -> i32
+ test_both_cast::<f32, i32>(0.0, 0);
+ test_both_cast::<f32, i32>(-0.0, 0);
+ test_both_cast::<f32, i32>(/*0x1p-149*/ f32::from_bits(0x00000001), 0);
+ test_both_cast::<f32, i32>(/*-0x1p-149*/ f32::from_bits(0x80000001), 0);
+ test_both_cast::<f32, i32>(/*0x1.19999ap+0*/ f32::from_bits(0x3f8ccccd), 1);
+ test_both_cast::<f32, i32>(/*-0x1.19999ap+0*/ f32::from_bits(0xbf8ccccd), -1);
+ test_both_cast::<f32, i32>(1.9, 1);
+ test_both_cast::<f32, i32>(-1.9, -1);
+ test_both_cast::<f32, i32>(5.0, 5);
+ test_both_cast::<f32, i32>(-5.0, -5);
+ test_both_cast::<f32, i32>(2147483520.0, 2147483520);
+ test_both_cast::<f32, i32>(-2147483648.0, -2147483648);
+ // unrepresentable casts
+ assert_eq::<i32>(2147483648.0f32 as i32, i32::MAX);
+ assert_eq::<i32>(-2147483904.0f32 as i32, i32::MIN);
+ assert_eq::<i32>(f32::MAX as i32, i32::MAX);
+ assert_eq::<i32>(f32::MIN as i32, i32::MIN);
+ assert_eq::<i32>(f32::INFINITY as i32, i32::MAX);
+ assert_eq::<i32>(f32::NEG_INFINITY as i32, i32::MIN);
+ assert_eq::<i32>(f32::NAN as i32, 0);
+ assert_eq::<i32>((-f32::NAN) as i32, 0);
+
+ // f32 -> u32
+ test_both_cast::<f32, u32>(0.0, 0);
+ test_both_cast::<f32, u32>(-0.0, 0);
+ test_both_cast::<f32, u32>(-0.9999999, 0);
+ test_both_cast::<f32, u32>(/*0x1p-149*/ f32::from_bits(0x1), 0);
+ test_both_cast::<f32, u32>(/*-0x1p-149*/ f32::from_bits(0x80000001), 0);
+ test_both_cast::<f32, u32>(/*0x1.19999ap+0*/ f32::from_bits(0x3f8ccccd), 1);
+ test_both_cast::<f32, u32>(1.9, 1);
+ test_both_cast::<f32, u32>(5.0, 5);
+ test_both_cast::<f32, u32>(2147483648.0, 0x8000_0000);
+ test_both_cast::<f32, u32>(4294967040.0, 0u32.wrapping_sub(256));
+ test_both_cast::<f32, u32>(/*-0x1.ccccccp-1*/ f32::from_bits(0xbf666666), 0);
+ test_both_cast::<f32, u32>(/*-0x1.fffffep-1*/ f32::from_bits(0xbf7fffff), 0);
+ test_both_cast::<f32, u32>((u32::MAX - 128) as f32, u32::MAX - 255); // rounding loss
+
+ // unrepresentable casts:
+
+ // rounds up and then becomes unrepresentable
+ assert_eq::<u32>((u32::MAX - 127) as f32 as u32, u32::MAX);
+
+ assert_eq::<u32>(4294967296.0f32 as u32, u32::MAX);
+ assert_eq::<u32>(-5.0f32 as u32, 0);
+ assert_eq::<u32>(f32::MAX as u32, u32::MAX);
+ assert_eq::<u32>(f32::MIN as u32, 0);
+ assert_eq::<u32>(f32::INFINITY as u32, u32::MAX);
+ assert_eq::<u32>(f32::NEG_INFINITY as u32, 0);
+ assert_eq::<u32>(f32::NAN as u32, 0);
+ assert_eq::<u32>((-f32::NAN) as u32, 0);
+
+ // f32 -> i64
+ test_both_cast::<f32, i64>(4294967296.0, 4294967296);
+ test_both_cast::<f32, i64>(-4294967296.0, -4294967296);
+ test_both_cast::<f32, i64>(9223371487098961920.0, 9223371487098961920);
+ test_both_cast::<f32, i64>(-9223372036854775808.0, -9223372036854775808);
+
+ // f64 -> i8
+ test_both_cast::<f64, i8>(127.99, 127);
+ test_both_cast::<f64, i8>(-128.99, -128);
+
+ // f64 -> i32
+ test_both_cast::<f64, i32>(0.0, 0);
+ test_both_cast::<f64, i32>(-0.0, 0);
+ test_both_cast::<f64, i32>(/*0x1.199999999999ap+0*/ f64::from_bits(0x3ff199999999999a), 1);
+ test_both_cast::<f64, i32>(
+ /*-0x1.199999999999ap+0*/ f64::from_bits(0xbff199999999999a),
+ -1,
+ );
+ test_both_cast::<f64, i32>(1.9, 1);
+ test_both_cast::<f64, i32>(-1.9, -1);
+ test_both_cast::<f64, i32>(1e8, 100_000_000);
+ test_both_cast::<f64, i32>(2147483647.0, 2147483647);
+ test_both_cast::<f64, i32>(-2147483648.0, -2147483648);
+ // unrepresentable casts
+ assert_eq::<i32>(2147483648.0f64 as i32, i32::MAX);
+ assert_eq::<i32>(-2147483649.0f64 as i32, i32::MIN);
+
+ // f64 -> i64
+ test_both_cast::<f64, i64>(0.0, 0);
+ test_both_cast::<f64, i64>(-0.0, 0);
+ test_both_cast::<f64, i64>(/*0x0.0000000000001p-1022*/ f64::from_bits(0x1), 0);
+ test_both_cast::<f64, i64>(
+ /*-0x0.0000000000001p-1022*/ f64::from_bits(0x8000000000000001),
+ 0,
+ );
+ test_both_cast::<f64, i64>(/*0x1.199999999999ap+0*/ f64::from_bits(0x3ff199999999999a), 1);
+ test_both_cast::<f64, i64>(
+ /*-0x1.199999999999ap+0*/ f64::from_bits(0xbff199999999999a),
+ -1,
+ );
+ test_both_cast::<f64, i64>(5.0, 5);
+ test_both_cast::<f64, i64>(5.9, 5);
+ test_both_cast::<f64, i64>(-5.0, -5);
+ test_both_cast::<f64, i64>(-5.9, -5);
+ test_both_cast::<f64, i64>(4294967296.0, 4294967296);
+ test_both_cast::<f64, i64>(-4294967296.0, -4294967296);
+ test_both_cast::<f64, i64>(9223372036854774784.0, 9223372036854774784);
+ test_both_cast::<f64, i64>(-9223372036854775808.0, -9223372036854775808);
+ // unrepresentable casts
+ assert_eq::<i64>(9223372036854775808.0f64 as i64, i64::MAX);
+ assert_eq::<i64>(-9223372036854777856.0f64 as i64, i64::MIN);
+ assert_eq::<i64>(f64::MAX as i64, i64::MAX);
+ assert_eq::<i64>(f64::MIN as i64, i64::MIN);
+ assert_eq::<i64>(f64::INFINITY as i64, i64::MAX);
+ assert_eq::<i64>(f64::NEG_INFINITY as i64, i64::MIN);
+ assert_eq::<i64>(f64::NAN as i64, 0);
+ assert_eq::<i64>((-f64::NAN) as i64, 0);
+
+ // f64 -> u64
+ test_both_cast::<f64, u64>(0.0, 0);
+ test_both_cast::<f64, u64>(-0.0, 0);
+ test_both_cast::<f64, u64>(-0.99999999999, 0);
+ test_both_cast::<f64, u64>(5.0, 5);
+ test_both_cast::<f64, u64>(1e16, 10000000000000000);
+ test_both_cast::<f64, u64>((u64::MAX - 1024) as f64, u64::MAX - 2047); // rounding loss
+ test_both_cast::<f64, u64>(9223372036854775808.0, 9223372036854775808);
+ // unrepresentable casts
+ assert_eq::<u64>(-5.0f64 as u64, 0);
+ // rounds up and then becomes unrepresentable
+ assert_eq::<u64>((u64::MAX - 1023) as f64 as u64, u64::MAX);
+ assert_eq::<u64>(18446744073709551616.0f64 as u64, u64::MAX);
+ assert_eq::<u64>(f64::MAX as u64, u64::MAX);
+ assert_eq::<u64>(f64::MIN as u64, 0);
+ assert_eq::<u64>(f64::INFINITY as u64, u64::MAX);
+ assert_eq::<u64>(f64::NEG_INFINITY as u64, 0);
+ assert_eq::<u64>(f64::NAN as u64, 0);
+ assert_eq::<u64>((-f64::NAN) as u64, 0);
+
+ // FIXME emscripten does not support i128
+ #[cfg(not(target_os = "emscripten"))]
+ {
+ // f64 -> i128
+ assert_eq::<i128>(f64::MAX as i128, i128::MAX);
+ assert_eq::<i128>(f64::MIN as i128, i128::MIN);
+
+ // f64 -> u128
+ assert_eq::<u128>(f64::MAX as u128, u128::MAX);
+ assert_eq::<u128>(f64::MIN as u128, 0);
+ }
+
+ // int -> f32
+ assert_eq::<f32>(127i8 as f32, 127.0);
+ assert_eq::<f32>(2147483647i32 as f32, 2147483648.0);
+ assert_eq::<f32>((-2147483648i32) as f32, -2147483648.0);
+ assert_eq::<f32>(1234567890i32 as f32, /*0x1.26580cp+30*/ f32::from_bits(0x4e932c06));
+ assert_eq::<f32>(16777217i32 as f32, 16777216.0);
+ assert_eq::<f32>((-16777217i32) as f32, -16777216.0);
+ assert_eq::<f32>(16777219i32 as f32, 16777220.0);
+ assert_eq::<f32>((-16777219i32) as f32, -16777220.0);
+ assert_eq::<f32>(
+ 0x7fffff4000000001i64 as f32,
+ /*0x1.fffffep+62*/ f32::from_bits(0x5effffff),
+ );
+ assert_eq::<f32>(
+ 0x8000004000000001u64 as i64 as f32,
+ /*-0x1.fffffep+62*/ f32::from_bits(0xdeffffff),
+ );
+ assert_eq::<f32>(
+ 0x0020000020000001i64 as f32,
+ /*0x1.000002p+53*/ f32::from_bits(0x5a000001),
+ );
+ assert_eq::<f32>(
+ 0xffdfffffdfffffffu64 as i64 as f32,
+ /*-0x1.000002p+53*/ f32::from_bits(0xda000001),
+ );
+ // FIXME emscripten does not support i128
+ #[cfg(not(target_os = "emscripten"))]
+ {
+ assert_eq::<f32>(i128::MIN as f32, -170141183460469231731687303715884105728.0f32);
+ assert_eq::<f32>(u128::MAX as f32, f32::INFINITY); // saturation
+ }
+
+ // int -> f64
+ assert_eq::<f64>(127i8 as f64, 127.0);
+ assert_eq::<f64>(i16::MIN as f64, -32768.0f64);
+ assert_eq::<f64>(2147483647i32 as f64, 2147483647.0);
+ assert_eq::<f64>(-2147483648i32 as f64, -2147483648.0);
+ assert_eq::<f64>(987654321i32 as f64, 987654321.0);
+ assert_eq::<f64>(9223372036854775807i64 as f64, 9223372036854775807.0);
+ assert_eq::<f64>(-9223372036854775808i64 as f64, -9223372036854775808.0);
+ assert_eq::<f64>(4669201609102990i64 as f64, 4669201609102990.0); // Feigenbaum (?)
+ assert_eq::<f64>(9007199254740993i64 as f64, 9007199254740992.0);
+ assert_eq::<f64>(-9007199254740993i64 as f64, -9007199254740992.0);
+ assert_eq::<f64>(9007199254740995i64 as f64, 9007199254740996.0);
+ assert_eq::<f64>(-9007199254740995i64 as f64, -9007199254740996.0);
+ // FIXME emscripten does not support i128
+ #[cfg(not(target_os = "emscripten"))]
+ {
+ // even that fits...
+ assert_eq::<f64>(u128::MAX as f64, 340282366920938463463374607431768211455.0f64);
+ }
+
+ // f32 -> f64
+ assert_eq::<u64>((0.0f32 as f64).to_bits(), 0.0f64.to_bits());
+ assert_eq::<u64>(((-0.0f32) as f64).to_bits(), (-0.0f64).to_bits());
+ assert_eq::<f64>(5.0f32 as f64, 5.0f64);
+ assert_eq::<f64>(
+ /*0x1p-149*/ f32::from_bits(0x1) as f64,
+ /*0x1p-149*/ f64::from_bits(0x36a0000000000000),
+ );
+ assert_eq::<f64>(
+ /*-0x1p-149*/ f32::from_bits(0x80000001) as f64,
+ /*-0x1p-149*/ f64::from_bits(0xb6a0000000000000),
+ );
+ assert_eq::<f64>(
+ /*0x1.fffffep+127*/ f32::from_bits(0x7f7fffff) as f64,
+ /*0x1.fffffep+127*/ f64::from_bits(0x47efffffe0000000),
+ );
+ assert_eq::<f64>(
+ /*-0x1.fffffep+127*/ (-f32::from_bits(0x7f7fffff)) as f64,
+ /*-0x1.fffffep+127*/ -f64::from_bits(0x47efffffe0000000),
+ );
+ assert_eq::<f64>(
+ /*0x1p-119*/ f32::from_bits(0x4000000) as f64,
+ /*0x1p-119*/ f64::from_bits(0x3880000000000000),
+ );
+ assert_eq::<f64>(
+ /*0x1.8f867ep+125*/ f32::from_bits(0x7e47c33f) as f64,
+ 6.6382536710104395e+37,
+ );
+ assert_eq::<f64>(f32::INFINITY as f64, f64::INFINITY);
+ assert_eq::<f64>(f32::NEG_INFINITY as f64, f64::NEG_INFINITY);
+
+ // f64 -> f32
+ assert_eq::<u32>((0.0f64 as f32).to_bits(), 0.0f32.to_bits());
+ assert_eq::<u32>(((-0.0f64) as f32).to_bits(), (-0.0f32).to_bits());
+ assert_eq::<f32>(5.0f64 as f32, 5.0f32);
+ assert_eq::<f32>(/*0x0.0000000000001p-1022*/ f64::from_bits(0x1) as f32, 0.0);
+ assert_eq::<f32>(/*-0x0.0000000000001p-1022*/ (-f64::from_bits(0x1)) as f32, -0.0);
+ assert_eq::<f32>(
+ /*0x1.fffffe0000000p-127*/ f64::from_bits(0x380fffffe0000000) as f32,
+ /*0x1p-149*/ f32::from_bits(0x800000),
+ );
+ assert_eq::<f32>(
+ /*0x1.4eae4f7024c7p+108*/ f64::from_bits(0x46b4eae4f7024c70) as f32,
+ /*0x1.4eae5p+108*/ f32::from_bits(0x75a75728),
+ );
+ assert_eq::<f32>(f64::MAX as f32, f32::INFINITY);
+ assert_eq::<f32>(f64::MIN as f32, f32::NEG_INFINITY);
+ assert_eq::<f32>(f64::INFINITY as f32, f32::INFINITY);
+ assert_eq::<f32>(f64::NEG_INFINITY as f32, f32::NEG_INFINITY);
+}
+
+pub fn run() {
+ casts(); // from miri's tests
+
+ common_fptoi_tests!(f* -> i8 i16 i32 i64 u8 u16 u32 u64);
+ fptoui_tests!(f* -> u8 u16 u32 u64);
+ // FIXME emscripten does not support i128
+ #[cfg(not(target_os = "emscripten"))]
+ {
+ common_fptoi_tests!(f* -> i128 u128);
+ fptoui_tests!(f* -> u128);
+ }
+
+ // The following tests cover edge cases for some integer types.
+
+ // # u8
+ test!(254., f* -> u8, 254);
+ test!(256., f* -> u8, 255);
+
+ // # i8
+ test!(-127., f* -> i8, -127);
+ test!(-129., f* -> i8, -128);
+ test!(126., f* -> i8, 126);
+ test!(128., f* -> i8, 127);
+
+ // # i32
+ // -2147483648. is i32::MIN (exactly)
+ test!(-2147483648., f* -> i32, i32::MIN);
+ // 2147483648. is i32::MAX rounded up
+ test!(2147483648., f32 -> i32, 2147483647);
+ // With 24 significand bits, floats with magnitude in [2^30 + 1, 2^31] are rounded to
+ // multiples of 2^7. Therefore, nextDown(round(i32::MAX)) is 2^31 - 128:
+ test!(2147483520., f32 -> i32, 2147483520);
+ // Similarly, nextUp(i32::MIN) is i32::MIN + 2^8 and nextDown(i32::MIN) is i32::MIN - 2^7
+ test!(-2147483904., f* -> i32, i32::MIN);
+ test!(-2147483520., f* -> i32, -2147483520);
+
+ // # u32
+ // round(MAX) and nextUp(round(MAX))
+ test!(4294967040., f* -> u32, 4294967040);
+ test!(4294967296., f* -> u32, 4294967295);
+
+ // # u128
+ #[cfg(not(target_os = "emscripten"))]
+ {
+ // float->int:
+ test!(f32::MAX, f32 -> u128, 0xffffff00000000000000000000000000);
+ // nextDown(f32::MAX) = 2^128 - 2 * 2^104
+ const SECOND_LARGEST_F32: f32 = 340282326356119256160033759537265639424.;
+ test!(SECOND_LARGEST_F32, f32 -> u128, 0xfffffe00000000000000000000000000);
+ }
+}
diff --git a/tests/ui/numbers-arithmetic/saturating-float-casts-wasm.rs b/tests/ui/numbers-arithmetic/saturating-float-casts-wasm.rs
new file mode 100644
index 000000000..cad059173
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/saturating-float-casts-wasm.rs
@@ -0,0 +1,13 @@
+// run-pass
+// only-wasm32
+// compile-flags: -Zmir-opt-level=0 -C target-feature=+nontrapping-fptoint
+
+#![feature(test, stmt_expr_attributes)]
+#![deny(overflowing_literals)]
+
+#[path = "saturating-float-casts-impl.rs"]
+mod implementation;
+
+pub fn main() {
+ implementation::run();
+}
diff --git a/tests/ui/numbers-arithmetic/saturating-float-casts.rs b/tests/ui/numbers-arithmetic/saturating-float-casts.rs
new file mode 100644
index 000000000..cc248a9be
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/saturating-float-casts.rs
@@ -0,0 +1,12 @@
+// run-pass
+// compile-flags:-Zmir-opt-level=0
+
+#![feature(test, stmt_expr_attributes)]
+#![deny(overflowing_literals)]
+
+#[path = "saturating-float-casts-impl.rs"]
+mod implementation;
+
+pub fn main() {
+ implementation::run();
+}
diff --git a/tests/ui/numbers-arithmetic/shift-near-oflo.rs b/tests/ui/numbers-arithmetic/shift-near-oflo.rs
new file mode 100644
index 000000000..55006a113
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/shift-near-oflo.rs
@@ -0,0 +1,100 @@
+// run-pass
+// compile-flags: -C debug-assertions
+
+// Check that we do *not* overflow on a number of edge cases.
+// (compare with test/run-fail/overflowing-{lsh,rsh}*.rs)
+
+fn main() {
+ test_left_shift();
+ test_right_shift();
+}
+
+pub static mut HACK: i32 = 0;
+
+// Work around constant-evaluation
+// The point of this test is to exercise the code generated for execution at runtime,
+// `id` can never be flagged as a const fn by future aggressive analyses...
+// due to the modification of the static
+#[inline(never)]
+fn id<T>(x: T) -> T {
+ unsafe { HACK += 1; }
+ x
+}
+
+fn test_left_shift() {
+ // negative rhs can panic, but values in [0,N-1] are okay for iN
+
+ macro_rules! tests {
+ ($iN:ty, $uN:ty, $max_rhs:expr, $expect_i:expr, $expect_u:expr) => { {
+ let x = (1 as $iN) << id(0);
+ assert_eq!(x, 1);
+ let x = (1 as $uN) << id(0);
+ assert_eq!(x, 1);
+ let x = (1 as $iN) << id($max_rhs);
+ assert_eq!(x, $expect_i);
+ let x = (1 as $uN) << id($max_rhs);
+ assert_eq!(x, $expect_u);
+ // high-order bits on LHS are silently discarded without panic.
+ let x = (3 as $iN) << id($max_rhs);
+ assert_eq!(x, $expect_i);
+ let x = (3 as $uN) << id($max_rhs);
+ assert_eq!(x, $expect_u);
+ } }
+ }
+
+ let x = 1_i8 << id(0);
+ assert_eq!(x, 1);
+ let x = 1_u8 << id(0);
+ assert_eq!(x, 1);
+ let x = 1_i8 << id(7);
+ assert_eq!(x, i8::MIN);
+ let x = 1_u8 << id(7);
+ assert_eq!(x, 0x80);
+ // high-order bits on LHS are silently discarded without panic.
+ let x = 3_i8 << id(7);
+ assert_eq!(x, i8::MIN);
+ let x = 3_u8 << id(7);
+ assert_eq!(x, 0x80);
+
+ // above is (approximately) expanded from:
+ tests!(i8, u8, 7, i8::MIN, 0x80_u8);
+
+ tests!(i16, u16, 15, i16::MIN, 0x8000_u16);
+ tests!(i32, u32, 31, i32::MIN, 0x8000_0000_u32);
+ tests!(i64, u64, 63, i64::MIN, 0x8000_0000_0000_0000_u64);
+}
+
+fn test_right_shift() {
+ // negative rhs can panic, but values in [0,N-1] are okay for iN
+
+ macro_rules! tests {
+ ($iN:ty, $uN:ty, $max_rhs:expr,
+ $signbit_i:expr, $highbit_i:expr, $highbit_u:expr) =>
+ { {
+ let x = (1 as $iN) >> id(0);
+ assert_eq!(x, 1);
+ let x = (1 as $uN) >> id(0);
+ assert_eq!(x, 1);
+ let x = ($highbit_i) >> id($max_rhs-1);
+ assert_eq!(x, 1);
+ let x = ($highbit_u) >> id($max_rhs);
+ assert_eq!(x, 1);
+ // sign-bit is carried by arithmetic right shift
+ let x = ($signbit_i) >> id($max_rhs);
+ assert_eq!(x, -1);
+ // low-order bits on LHS are silently discarded without panic.
+ let x = ($highbit_i + 1) >> id($max_rhs-1);
+ assert_eq!(x, 1);
+ let x = ($highbit_u + 1) >> id($max_rhs);
+ assert_eq!(x, 1);
+ let x = ($signbit_i + 1) >> id($max_rhs);
+ assert_eq!(x, -1);
+ } }
+ }
+
+ tests!(i8, u8, 7, i8::MIN, 0x40_i8, 0x80_u8);
+ tests!(i16, u16, 15, i16::MIN, 0x4000_u16, 0x8000_u16);
+ tests!(i32, u32, 31, i32::MIN, 0x4000_0000_u32, 0x8000_0000_u32);
+ tests!(i64, u64, 63, i64::MIN,
+ 0x4000_0000_0000_0000_u64, 0x8000_0000_0000_0000_u64);
+}
diff --git a/tests/ui/numbers-arithmetic/shift-various-types.rs b/tests/ui/numbers-arithmetic/shift-various-types.rs
new file mode 100644
index 000000000..473bda3d7
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/shift-various-types.rs
@@ -0,0 +1,48 @@
+// run-pass
+// Test that we can do shifts by any integral type.
+
+
+struct Panolpy {
+ i8: i8,
+ i16: i16,
+ i32: i32,
+ i64: i64,
+ isize: isize,
+
+ u8: u8,
+ u16: u16,
+ u32: u32,
+ u64: u64,
+ usize: usize,
+}
+
+fn foo(p: &Panolpy) {
+ assert_eq!(22 >> p.i8, 11);
+ assert_eq!(22 >> p.i16, 11);
+ assert_eq!(22 >> p.i32, 11);
+ assert_eq!(22 >> p.i64, 11);
+ assert_eq!(22 >> p.isize, 11);
+
+ assert_eq!(22 >> p.u8, 11);
+ assert_eq!(22 >> p.u16, 11);
+ assert_eq!(22 >> p.u32, 11);
+ assert_eq!(22 >> p.u64, 11);
+ assert_eq!(22 >> p.usize, 11);
+}
+
+fn main() {
+ let p = Panolpy {
+ i8: 1,
+ i16: 1,
+ i32: 1,
+ i64: 1,
+ isize: 1,
+
+ u8: 1,
+ u16: 1,
+ u32: 1,
+ u64: 1,
+ usize: 1,
+ };
+ foo(&p)
+}
diff --git a/tests/ui/numbers-arithmetic/shift.rs b/tests/ui/numbers-arithmetic/shift.rs
new file mode 100644
index 000000000..2fc77928e
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/shift.rs
@@ -0,0 +1,76 @@
+// run-pass
+#![allow(non_upper_case_globals)]
+#![allow(overflowing_literals)]
+
+// Testing shifts for various combinations of integers
+// Issue #1570
+
+
+pub fn main() {
+ test_misc();
+ test_expr();
+ test_const();
+}
+
+fn test_misc() {
+ assert_eq!(1 << 1 << 1 << 1 << 1 << 1, 32);
+}
+
+fn test_expr() {
+ let v10 = 10 as usize;
+ let v4 = 4 as u8;
+ let v2 = 2 as u8;
+ assert_eq!(v10 >> v2 as usize, v2 as usize);
+ assert_eq!(v10 << v4 as usize, 160 as usize);
+
+ let v10 = 10 as u8;
+ let v4 = 4 as usize;
+ let v2 = 2 as usize;
+ assert_eq!(v10 >> v2 as usize, v2 as u8);
+ assert_eq!(v10 << v4 as usize, 160 as u8);
+
+ let v10 = 10 as isize;
+ let v4 = 4 as i8;
+ let v2 = 2 as i8;
+ assert_eq!(v10 >> v2 as usize, v2 as isize);
+ assert_eq!(v10 << v4 as usize, 160 as isize);
+
+ let v10 = 10 as i8;
+ let v4 = 4 as isize;
+ let v2 = 2 as isize;
+ assert_eq!(v10 >> v2 as usize, v2 as i8);
+ assert_eq!(v10 << v4 as usize, 160 as i8);
+
+ let v10 = 10 as usize;
+ let v4 = 4 as isize;
+ let v2 = 2 as isize;
+ assert_eq!(v10 >> v2 as usize, v2 as usize);
+ assert_eq!(v10 << v4 as usize, 160 as usize);
+}
+
+fn test_const() {
+ static r1_1: usize = 10_usize >> 2_usize;
+ static r2_1: usize = 10_usize << 4_usize;
+ assert_eq!(r1_1, 2 as usize);
+ assert_eq!(r2_1, 160 as usize);
+
+ static r1_2: u8 = 10u8 >> 2_usize;
+ static r2_2: u8 = 10u8 << 4_usize;
+ assert_eq!(r1_2, 2 as u8);
+ assert_eq!(r2_2, 160 as u8);
+
+ static r1_3: isize = 10 >> 2_usize;
+ static r2_3: isize = 10 << 4_usize;
+ assert_eq!(r1_3, 2 as isize);
+ assert_eq!(r2_3, 160 as isize);
+
+ static r1_4: i8 = 10i8 >> 2_usize;
+ static r2_4: i8 = 10i8 << 4_usize;
+ assert_eq!(r1_4, 2 as i8);
+ assert_eq!(r2_4, 160 as i8);
+
+ static r1_5: usize = 10_usize >> 2_usize;
+ static r2_5: usize = 10_usize << 4_usize;
+ assert_eq!(r1_5, 2 as usize);
+ assert_eq!(r2_5, 160 as usize);
+}
diff --git a/tests/ui/numbers-arithmetic/signed-shift-const-eval.rs b/tests/ui/numbers-arithmetic/signed-shift-const-eval.rs
new file mode 100644
index 000000000..6d0462b46
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/signed-shift-const-eval.rs
@@ -0,0 +1,8 @@
+// run-pass
+#![allow(non_camel_case_types)]
+
+
+enum test { thing = -5 >> 1_usize }
+pub fn main() {
+ assert_eq!(test::thing as isize, -3);
+}
diff --git a/tests/ui/numbers-arithmetic/suggest-float-literal.fixed b/tests/ui/numbers-arithmetic/suggest-float-literal.fixed
new file mode 100644
index 000000000..9278262a6
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/suggest-float-literal.fixed
@@ -0,0 +1,37 @@
+// run-rustfix
+
+#![allow(dead_code)]
+
+fn add_integer_to_f32(x: f32) -> f32 {
+ x + 100.0 //~ ERROR cannot add `{integer}` to `f32`
+}
+
+fn add_integer_to_f64(x: f64) -> f64 {
+ x + 100.0 //~ ERROR cannot add `{integer}` to `f64`
+}
+
+fn subtract_integer_from_f32(x: f32) -> f32 {
+ x - 100.0 //~ ERROR cannot subtract `{integer}` from `f32`
+}
+
+fn subtract_integer_from_f64(x: f64) -> f64 {
+ x - 100.0 //~ ERROR cannot subtract `{integer}` from `f64`
+}
+
+fn multiply_f32_by_integer(x: f32) -> f32 {
+ x * 100.0 //~ ERROR cannot multiply `f32` by `{integer}`
+}
+
+fn multiply_f64_by_integer(x: f64) -> f64 {
+ x * 100.0 //~ ERROR cannot multiply `f64` by `{integer}`
+}
+
+fn divide_f32_by_integer(x: f32) -> f32 {
+ x / 100.0 //~ ERROR cannot divide `f32` by `{integer}`
+}
+
+fn divide_f64_by_integer(x: f64) -> f64 {
+ x / 100.0 //~ ERROR cannot divide `f64` by `{integer}`
+}
+
+fn main() {}
diff --git a/tests/ui/numbers-arithmetic/suggest-float-literal.rs b/tests/ui/numbers-arithmetic/suggest-float-literal.rs
new file mode 100644
index 000000000..59e67f8d3
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/suggest-float-literal.rs
@@ -0,0 +1,37 @@
+// run-rustfix
+
+#![allow(dead_code)]
+
+fn add_integer_to_f32(x: f32) -> f32 {
+ x + 100 //~ ERROR cannot add `{integer}` to `f32`
+}
+
+fn add_integer_to_f64(x: f64) -> f64 {
+ x + 100 //~ ERROR cannot add `{integer}` to `f64`
+}
+
+fn subtract_integer_from_f32(x: f32) -> f32 {
+ x - 100 //~ ERROR cannot subtract `{integer}` from `f32`
+}
+
+fn subtract_integer_from_f64(x: f64) -> f64 {
+ x - 100 //~ ERROR cannot subtract `{integer}` from `f64`
+}
+
+fn multiply_f32_by_integer(x: f32) -> f32 {
+ x * 100 //~ ERROR cannot multiply `f32` by `{integer}`
+}
+
+fn multiply_f64_by_integer(x: f64) -> f64 {
+ x * 100 //~ ERROR cannot multiply `f64` by `{integer}`
+}
+
+fn divide_f32_by_integer(x: f32) -> f32 {
+ x / 100 //~ ERROR cannot divide `f32` by `{integer}`
+}
+
+fn divide_f64_by_integer(x: f64) -> f64 {
+ x / 100 //~ ERROR cannot divide `f64` by `{integer}`
+}
+
+fn main() {}
diff --git a/tests/ui/numbers-arithmetic/suggest-float-literal.stderr b/tests/ui/numbers-arithmetic/suggest-float-literal.stderr
new file mode 100644
index 000000000..03779d356
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/suggest-float-literal.stderr
@@ -0,0 +1,139 @@
+error[E0277]: cannot add `{integer}` to `f32`
+ --> $DIR/suggest-float-literal.rs:6:7
+ |
+LL | x + 100
+ | ^ no implementation for `f32 + {integer}`
+ |
+ = help: the trait `Add<{integer}>` is not implemented for `f32`
+ = help: the following other types implement trait `Add<Rhs>`:
+ <&'a f32 as Add<f32>>
+ <&f32 as Add<&f32>>
+ <f32 as Add<&f32>>
+ <f32 as Add>
+help: consider using a floating-point literal by writing it with `.0`
+ |
+LL | x + 100.0
+ | ++
+
+error[E0277]: cannot add `{integer}` to `f64`
+ --> $DIR/suggest-float-literal.rs:10:7
+ |
+LL | x + 100
+ | ^ no implementation for `f64 + {integer}`
+ |
+ = help: the trait `Add<{integer}>` is not implemented for `f64`
+ = help: the following other types implement trait `Add<Rhs>`:
+ <&'a f64 as Add<f64>>
+ <&f64 as Add<&f64>>
+ <f64 as Add<&f64>>
+ <f64 as Add>
+help: consider using a floating-point literal by writing it with `.0`
+ |
+LL | x + 100.0
+ | ++
+
+error[E0277]: cannot subtract `{integer}` from `f32`
+ --> $DIR/suggest-float-literal.rs:14:7
+ |
+LL | x - 100
+ | ^ no implementation for `f32 - {integer}`
+ |
+ = help: the trait `Sub<{integer}>` is not implemented for `f32`
+ = help: the following other types implement trait `Sub<Rhs>`:
+ <&'a f32 as Sub<f32>>
+ <&f32 as Sub<&f32>>
+ <f32 as Sub<&f32>>
+ <f32 as Sub>
+help: consider using a floating-point literal by writing it with `.0`
+ |
+LL | x - 100.0
+ | ++
+
+error[E0277]: cannot subtract `{integer}` from `f64`
+ --> $DIR/suggest-float-literal.rs:18:7
+ |
+LL | x - 100
+ | ^ no implementation for `f64 - {integer}`
+ |
+ = help: the trait `Sub<{integer}>` is not implemented for `f64`
+ = help: the following other types implement trait `Sub<Rhs>`:
+ <&'a f64 as Sub<f64>>
+ <&f64 as Sub<&f64>>
+ <f64 as Sub<&f64>>
+ <f64 as Sub>
+help: consider using a floating-point literal by writing it with `.0`
+ |
+LL | x - 100.0
+ | ++
+
+error[E0277]: cannot multiply `f32` by `{integer}`
+ --> $DIR/suggest-float-literal.rs:22:7
+ |
+LL | x * 100
+ | ^ no implementation for `f32 * {integer}`
+ |
+ = help: the trait `Mul<{integer}>` is not implemented for `f32`
+ = help: the following other types implement trait `Mul<Rhs>`:
+ <&'a f32 as Mul<f32>>
+ <&f32 as Mul<&f32>>
+ <f32 as Mul<&f32>>
+ <f32 as Mul>
+help: consider using a floating-point literal by writing it with `.0`
+ |
+LL | x * 100.0
+ | ++
+
+error[E0277]: cannot multiply `f64` by `{integer}`
+ --> $DIR/suggest-float-literal.rs:26:7
+ |
+LL | x * 100
+ | ^ no implementation for `f64 * {integer}`
+ |
+ = help: the trait `Mul<{integer}>` is not implemented for `f64`
+ = help: the following other types implement trait `Mul<Rhs>`:
+ <&'a f64 as Mul<f64>>
+ <&f64 as Mul<&f64>>
+ <f64 as Mul<&f64>>
+ <f64 as Mul>
+help: consider using a floating-point literal by writing it with `.0`
+ |
+LL | x * 100.0
+ | ++
+
+error[E0277]: cannot divide `f32` by `{integer}`
+ --> $DIR/suggest-float-literal.rs:30:7
+ |
+LL | x / 100
+ | ^ no implementation for `f32 / {integer}`
+ |
+ = help: the trait `Div<{integer}>` is not implemented for `f32`
+ = help: the following other types implement trait `Div<Rhs>`:
+ <&'a f32 as Div<f32>>
+ <&f32 as Div<&f32>>
+ <f32 as Div<&f32>>
+ <f32 as Div>
+help: consider using a floating-point literal by writing it with `.0`
+ |
+LL | x / 100.0
+ | ++
+
+error[E0277]: cannot divide `f64` by `{integer}`
+ --> $DIR/suggest-float-literal.rs:34:7
+ |
+LL | x / 100
+ | ^ no implementation for `f64 / {integer}`
+ |
+ = help: the trait `Div<{integer}>` is not implemented for `f64`
+ = help: the following other types implement trait `Div<Rhs>`:
+ <&'a f64 as Div<f64>>
+ <&f64 as Div<&f64>>
+ <f64 as Div<&f64>>
+ <f64 as Div>
+help: consider using a floating-point literal by writing it with `.0`
+ |
+LL | x / 100.0
+ | ++
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/numbers-arithmetic/u128-as-f32.rs b/tests/ui/numbers-arithmetic/u128-as-f32.rs
new file mode 100644
index 000000000..839ce932d
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/u128-as-f32.rs
@@ -0,0 +1,46 @@
+// run-pass
+
+#![feature(test)]
+#![deny(overflowing_literals)]
+extern crate test;
+
+use test::black_box;
+
+macro_rules! test {
+ ($val:expr, $src_ty:ident -> $dest_ty:ident, $expected:expr) => ({
+ {
+ const X: $src_ty = $val;
+ const Y: $dest_ty = X as $dest_ty;
+ assert_eq!(Y, $expected,
+ "const eval {} -> {}", stringify!($src_ty), stringify!($dest_ty));
+ }
+ // black_box disables constant evaluation to test run-time conversions:
+ assert_eq!(black_box::<$src_ty>($val) as $dest_ty, $expected,
+ "run-time {} -> {}", stringify!($src_ty), stringify!($dest_ty));
+ });
+}
+
+pub fn main() {
+ // nextDown(f32::MAX) = 2^128 - 2 * 2^104
+ const SECOND_LARGEST_F32: f32 = 340282326356119256160033759537265639424.;
+
+ // f32::MAX - 0.5 ULP and smaller should be rounded down
+ test!(0xfffffe00000000000000000000000000, u128 -> f32, SECOND_LARGEST_F32);
+ test!(0xfffffe7fffffffffffffffffffffffff, u128 -> f32, SECOND_LARGEST_F32);
+ test!(0xfffffe80000000000000000000000000, u128 -> f32, SECOND_LARGEST_F32);
+ // numbers within < 0.5 ULP of f32::MAX it should be rounded to f32::MAX
+ test!(0xfffffe80000000000000000000000001, u128 -> f32, f32::MAX);
+ test!(0xfffffeffffffffffffffffffffffffff, u128 -> f32, f32::MAX);
+ test!(0xffffff00000000000000000000000000, u128 -> f32, f32::MAX);
+ test!(0xffffff00000000000000000000000001, u128 -> f32, f32::MAX);
+ test!(0xffffff7fffffffffffffffffffffffff, u128 -> f32, f32::MAX);
+ // f32::MAX + 0.5 ULP and greater should be rounded to infinity
+ test!(0xffffff80000000000000000000000000, u128 -> f32, f32::INFINITY);
+ test!(0xffffff80000000f00000000000000000, u128 -> f32, f32::INFINITY);
+ test!(0xffffff87ffffffffffffffff00000001, u128 -> f32, f32::INFINITY);
+
+ // u128->f64 should not be affected by the u128->f32 checks
+ test!(0xffffff80000000000000000000000000, u128 -> f64,
+ 340282356779733661637539395458142568448.0);
+ test!(u128::MAX, u128 -> f64, 340282366920938463463374607431768211455.0);
+}
diff --git a/tests/ui/numbers-arithmetic/u128.rs b/tests/ui/numbers-arithmetic/u128.rs
new file mode 100644
index 000000000..d7e28055b
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/u128.rs
@@ -0,0 +1,119 @@
+// run-pass
+
+#![feature(test)]
+
+extern crate test;
+use test::black_box as b;
+
+fn main() {
+ let x: u128 = 0xFFFF_FFFF_FFFF_FFFF__FFFF_FFFF_FFFF_FFFF;
+ assert_eq!(0, !x);
+ assert_eq!(0, !x);
+ let y: u128 = 0xFFFF_FFFF_FFFF_FFFF__FFFF_FFFF_FFFF_FFFE;
+ assert_eq!(!1, y);
+ assert_eq!(x, y | 1);
+ assert_eq!(0xFAFF_0000_FF8F_0000__FFFF_0000_FFFF_FFFE,
+ y &
+ 0xFAFF_0000_FF8F_0000__FFFF_0000_FFFF_FFFF);
+ let z: u128 = 0xABCD_EF;
+ assert_eq!(z * z, 0x734C_C2F2_A521);
+ assert_eq!(z * z * z * z, 0x33EE_0E2A_54E2_59DA_A0E7_8E41);
+ assert_eq!(z + z + z + z, 0x2AF3_7BC);
+ let k: u128 = 0x1234_5678_9ABC_DEFF_EDCB_A987_6543_210;
+ assert_eq!(k + k, 0x2468_ACF1_3579_BDFF_DB97_530E_CA86_420);
+ assert_eq!(0, k - k);
+ assert_eq!(0x1234_5678_9ABC_DEFF_EDCB_A987_5A86_421, k - z);
+ assert_eq!(0x1000_0000_0000_0000_0000_0000_0000_000,
+ k - 0x234_5678_9ABC_DEFF_EDCB_A987_6543_210);
+ assert_eq!(0x6EF5_DE4C_D3BC_2AAA_3BB4_CC5D_D6EE_8, k / 42);
+ assert_eq!(0, k % 42);
+ assert_eq!(15, z % 42);
+ assert_eq!(0x169D_A8020_CEC18, k % 0x3ACB_FE49_FF24_AC);
+ assert_eq!(0x91A2_B3C4_D5E6_F7, k >> 65);
+ assert_eq!(0xFDB9_7530_ECA8_6420_0000_0000_0000_0000, k << 65);
+ assert!(k > z);
+ assert!(y > k);
+ assert!(y < x);
+ assert_eq!(x as u64, !0);
+ assert_eq!(z as u64, 0xABCD_EF);
+ assert_eq!(k as u64, 0xFEDC_BA98_7654_3210);
+ assert_eq!(k as i128, 0x1234_5678_9ABC_DEFF_EDCB_A987_6543_210);
+ assert_eq!((z as f64) as u128, z);
+ assert_eq!((z as f32) as u128, z);
+ assert_eq!((z as f64 * 16.0) as u128, z * 16);
+ assert_eq!((z as f32 * 16.0) as u128, z * 16);
+ let l :u128 = 432 << 100;
+ assert_eq!((l as f32) as u128, l);
+ assert_eq!((l as f64) as u128, l);
+ // formatting
+ let j: u128 = 1 << 67;
+ assert_eq!("147573952589676412928", format!("{}", j));
+ assert_eq!("80000000000000000", format!("{:x}", j));
+ assert_eq!("20000000000000000000000", format!("{:o}", j));
+ assert_eq!("10000000000000000000000000000000000000000000000000000000000000000000",
+ format!("{:b}", j));
+ assert_eq!("340282366920938463463374607431768211455",
+ format!("{}", u128::MAX));
+ assert_eq!("147573952589676412928", format!("{:?}", j));
+ // common traits
+ assert_eq!(x, b(x.clone()));
+ // overflow checks
+ assert_eq!((z).checked_mul(z), Some(0x734C_C2F2_A521));
+ assert_eq!((k).checked_mul(k), None);
+ let l: u128 = b(u128::MAX - 10);
+ let o: u128 = b(17);
+ assert_eq!(l.checked_add(b(11)), None);
+ assert_eq!(l.checked_sub(l), Some(0));
+ assert_eq!(o.checked_sub(b(18)), None);
+ assert_eq!(b(1u128).checked_shl(b(127)), Some(1 << 127));
+ assert_eq!(o.checked_shl(b(128)), None);
+
+ // Test cases for all udivmodti4 branches.
+ // case "0X/0X"
+ assert_eq!(b(0x69545bd57727c050_u128) /
+ b(0x3283527a3350d88c_u128),
+ 2u128);
+ // case "0X/KX"
+ assert_eq!(b(0x0_8003c9c50b473ae6_u128) /
+ b(0x1_283e8838c30fa8f4_u128),
+ 0u128);
+ // case "K0/K0"
+ assert_eq!(b(0xc43f42a207978720_u128 << 64) /
+ b(0x098e62b74c23cf1a_u128 << 64),
+ 20u128);
+ // case "KK/K0" for power-of-two D.
+ assert_eq!(b(0xa9008fb6c9d81e42_0e25730562a601c8_u128) /
+ b(1u128 << 120),
+ 169u128);
+ // case "KK/K0" with N >= D (https://github.com/rust-lang/rust/issues/41228).
+ assert_eq!(b(0xe4d26e59f0640328_06da5b06efe83a41_u128) /
+ b(0x330fcb030ea4447c_u128 << 64),
+ 4u128);
+ assert_eq!(b(3u128 << 64 | 1) /
+ b(3u128 << 64),
+ 1u128);
+ // case "KK/K0" with N < D.
+ assert_eq!(b(0x6655c9fb66ca2884_e2d1dfd470158c62_u128) /
+ b(0xb35b667cab7e355b_u128 << 64),
+ 0u128);
+ // case "KX/0K" for power-of-two D.
+ assert_eq!(b(0x3e49dd84feb2df59_7b2f97d93a253969_u128) /
+ b(1u128 << 4),
+ 0x03e49dd84feb2df5_97b2f97d93a25396_u128);
+ // case "KX/0K" in general.
+ assert_eq!(b(0x299692b3a1dae5bd_6162e6f489d2620e_u128) /
+ b(0x900b6f027571d6f7_u128),
+ 0x49e95f54b0442578_u128);
+ // case "KX/KK" with N >= D.
+ assert_eq!(b(0xc7b889180b67b07d_bc1a3c88783d35b5_u128) /
+ b(0x1d7e69f53160b9e2_60074771e852f244_u128),
+ 6u128);
+ // case "KX/KK" with N < D.
+ assert_eq!(b(0x679289ac23bb334f_36144401cf882172_u128) /
+ b(0x7b0b271b64865f05_f54a7b72746c062f_u128),
+ 0u128);
+
+ // iter-arithmetic traits
+ assert_eq!(10u128, [1u128, 2, 3, 4].iter().sum());
+ assert_eq!(24u128, [1u128, 2, 3, 4].iter().product());
+}
diff --git a/tests/ui/numbers-arithmetic/u32-decr.rs b/tests/ui/numbers-arithmetic/u32-decr.rs
new file mode 100644
index 000000000..d9e097818
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/u32-decr.rs
@@ -0,0 +1,10 @@
+// run-pass
+
+
+
+
+pub fn main() {
+ let mut word: u32 = 200000;
+ word = word - 1;
+ assert_eq!(word, 199999);
+}
diff --git a/tests/ui/numbers-arithmetic/u8-incr-decr.rs b/tests/ui/numbers-arithmetic/u8-incr-decr.rs
new file mode 100644
index 000000000..b16ec011d
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/u8-incr-decr.rs
@@ -0,0 +1,19 @@
+// run-pass
+
+
+
+
+// These constants were chosen because they aren't used anywhere
+// in the rest of the generated code so they're easily grep-able.
+
+pub fn main() {
+ let mut x: u8 = 19; // 0x13
+
+ let mut y: u8 = 35; // 0x23
+
+ x = x + 7; // 0x7
+
+ y = y - 9; // 0x9
+
+ assert_eq!(x, y);
+}
diff --git a/tests/ui/numbers-arithmetic/u8-incr.rs b/tests/ui/numbers-arithmetic/u8-incr.rs
new file mode 100644
index 000000000..5242acf5b
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/u8-incr.rs
@@ -0,0 +1,15 @@
+// run-pass
+
+
+
+
+pub fn main() {
+ let mut x: u8 = 12;
+ let y: u8 = 12;
+ x = x + 1;
+ x = x - 1;
+ assert_eq!(x, y);
+ // x = 14;
+ // x = x + 1;
+
+}
diff --git a/tests/ui/numbers-arithmetic/uint.rs b/tests/ui/numbers-arithmetic/uint.rs
new file mode 100644
index 000000000..d219eae8f
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/uint.rs
@@ -0,0 +1,7 @@
+// run-pass
+
+
+
+// pretty-expanded FIXME #23616
+
+pub fn main() { let _x: usize = 10 as usize; }
diff --git a/tests/ui/numbers-arithmetic/unary-minus-suffix-inference.rs b/tests/ui/numbers-arithmetic/unary-minus-suffix-inference.rs
new file mode 100644
index 000000000..a4d0a8494
--- /dev/null
+++ b/tests/ui/numbers-arithmetic/unary-minus-suffix-inference.rs
@@ -0,0 +1,23 @@
+// run-pass
+
+pub fn main() {
+ let a = 1;
+ let a_neg: i8 = -a;
+ println!("{}", a_neg);
+
+ let b = 1;
+ let b_neg: i16 = -b;
+ println!("{}", b_neg);
+
+ let c = 1;
+ let c_neg: i32 = -c;
+ println!("{}", c_neg);
+
+ let d = 1;
+ let d_neg: i64 = -d;
+ println!("{}", d_neg);
+
+ let e = 1;
+ let e_neg: isize = -e;
+ println!("{}", e_neg);
+}