diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:02:58 +0000 |
commit | 698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch) | |
tree | 173a775858bd501c378080a10dca74132f05bc50 /src/test/ui/numbers-arithmetic | |
parent | Initial commit. (diff) | |
download | rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip |
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
77 files changed, 3457 insertions, 0 deletions
diff --git a/src/test/ui/numbers-arithmetic/arith-unsigned.rs b/src/test/ui/numbers-arithmetic/arith-unsigned.rs new file mode 100644 index 000000000..ad57d9f86 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/div-mod.rs b/src/test/ui/numbers-arithmetic/div-mod.rs new file mode 100644 index 000000000..acb92a7df --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/divide-by-zero.rs b/src/test/ui/numbers-arithmetic/divide-by-zero.rs new file mode 100644 index 000000000..30e0e6c1b --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/float-int-invalid-const-cast.rs b/src/test/ui/numbers-arithmetic/float-int-invalid-const-cast.rs new file mode 100644 index 000000000..769114960 --- /dev/null +++ b/src/test/ui/numbers-arithmetic/float-int-invalid-const-cast.rs @@ -0,0 +1,50 @@ +// run-pass + +#![deny(const_err)] + +// 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/src/test/ui/numbers-arithmetic/float-literal-inference.rs b/src/test/ui/numbers-arithmetic/float-literal-inference.rs new file mode 100644 index 000000000..c4645e4f8 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/float-nan.rs b/src/test/ui/numbers-arithmetic/float-nan.rs new file mode 100644 index 000000000..0cc6473e5 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/float-signature.rs b/src/test/ui/numbers-arithmetic/float-signature.rs new file mode 100644 index 000000000..d47280ea2 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/float.rs b/src/test/ui/numbers-arithmetic/float.rs new file mode 100644 index 000000000..d55c05857 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/float2.rs b/src/test/ui/numbers-arithmetic/float2.rs new file mode 100644 index 000000000..b1bcf8da5 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/float_math.rs b/src/test/ui/numbers-arithmetic/float_math.rs new file mode 100644 index 000000000..a2902ee56 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/floatlits.rs b/src/test/ui/numbers-arithmetic/floatlits.rs new file mode 100644 index 000000000..07049af31 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/i128.rs b/src/test/ui/numbers-arithmetic/i128.rs new file mode 100644 index 000000000..d61a1ab03 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/i32-sub.rs b/src/test/ui/numbers-arithmetic/i32-sub.rs new file mode 100644 index 000000000..56df772b4 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/i8-incr.rs b/src/test/ui/numbers-arithmetic/i8-incr.rs new file mode 100644 index 000000000..718d259f7 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/int-abs-overflow.rs b/src/test/ui/numbers-arithmetic/int-abs-overflow.rs new file mode 100644 index 000000000..d63ba8cb0 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/int.rs b/src/test/ui/numbers-arithmetic/int.rs new file mode 100644 index 000000000..b496a70a6 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/integer-literal-radix.rs b/src/test/ui/numbers-arithmetic/integer-literal-radix.rs new file mode 100644 index 000000000..8f61ea17a --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/integer-literal-suffix-inference-2.rs b/src/test/ui/numbers-arithmetic/integer-literal-suffix-inference-2.rs new file mode 100644 index 000000000..80248dc22 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/integer-literal-suffix-inference-3.rs b/src/test/ui/numbers-arithmetic/integer-literal-suffix-inference-3.rs new file mode 100644 index 000000000..bec718a3c --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/integer-literal-suffix-inference.rs b/src/test/ui/numbers-arithmetic/integer-literal-suffix-inference.rs new file mode 100644 index 000000000..d177ced1a --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/issue-8460-const.noopt.stderr b/src/test/ui/numbers-arithmetic/issue-8460-const.noopt.stderr new file mode 100644 index 000000000..e2eee1ccd --- /dev/null +++ b/src/test/ui/numbers-arithmetic/issue-8460-const.noopt.stderr @@ -0,0 +1,148 @@ +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:13: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:15: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:17: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:19: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:21: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:23: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:25: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:27: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:29: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:31: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:33: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:35: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:37: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:39: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:41: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:43: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:45: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:47: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:49: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:51: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:53: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:55: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:57: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:59: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/src/test/ui/numbers-arithmetic/issue-8460-const.opt.stderr b/src/test/ui/numbers-arithmetic/issue-8460-const.opt.stderr new file mode 100644 index 000000000..e2eee1ccd --- /dev/null +++ b/src/test/ui/numbers-arithmetic/issue-8460-const.opt.stderr @@ -0,0 +1,148 @@ +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:13: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:15: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:17: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:19: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:21: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:23: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:25: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:27: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:29: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:31: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:33: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:35: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:37: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:39: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:41: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:43: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:45: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:47: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:49: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:51: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:53: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:55: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:57: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:59: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/src/test/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr b/src/test/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr new file mode 100644 index 000000000..e2eee1ccd --- /dev/null +++ b/src/test/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:13: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:15: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:17: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:19: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:21: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:23: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:25: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:27: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:29: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:31: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:33: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:35: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:37: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:39: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:41: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:43: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:45: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:47: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:49: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:51: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:53: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:55: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:57: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:59: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/src/test/ui/numbers-arithmetic/issue-8460-const.rs b/src/test/ui/numbers-arithmetic/issue-8460-const.rs new file mode 100644 index 000000000..8cad6deb3 --- /dev/null +++ b/src/test/ui/numbers-arithmetic/issue-8460-const.rs @@ -0,0 +1,61 @@ +// 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 + +#![deny(const_err)] + +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/src/test/ui/numbers-arithmetic/issue-8460.rs b/src/test/ui/numbers-arithmetic/issue-8460.rs new file mode 100644 index 000000000..77368b87e --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/mod-zero.rs b/src/test/ui/numbers-arithmetic/mod-zero.rs new file mode 100644 index 000000000..083716394 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs b/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs new file mode 100644 index 000000000..f857d4f4c --- /dev/null +++ b/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs @@ -0,0 +1,28 @@ +// run-pass +// compile-flags: -C debug_assertions=yes +// needs-unwind +// ignore-wasm32-bare compiled with panic=abort by default +// 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/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-ndebug.rs b/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-ndebug.rs new file mode 100644 index 000000000..982cd97c5 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/not-suggest-float-literal.rs b/src/test/ui/numbers-arithmetic/not-suggest-float-literal.rs new file mode 100644 index 000000000..513d02db9 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr b/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr new file mode 100644 index 000000000..6aa1ad8dd --- /dev/null +++ b/src/test/ui/numbers-arithmetic/not-suggest-float-literal.stderr @@ -0,0 +1,219 @@ +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 f32 as Add<f32>> + <&'a f64 as Add<f64>> + <&'a i128 as Add<i128>> + <&'a i16 as Add<i16>> + <&'a i32 as Add<i32>> + <&'a i64 as Add<i64>> + <&'a i8 as Add<i8>> + <&'a isize as Add<isize>> + and 48 others + +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 f32 as Add<f32>> + <&'a f64 as Add<f64>> + <&'a i128 as Add<i128>> + <&'a i16 as Add<i16>> + <&'a i32 as Add<i32>> + <&'a i64 as Add<i64>> + <&'a i8 as Add<i8>> + <&'a isize as Add<isize>> + and 48 others + +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 f32 as Add<f32>> + <&'a f64 as Add<f64>> + <&'a i128 as Add<i128>> + <&'a i16 as Add<i16>> + <&'a i32 as Add<i32>> + <&'a i64 as Add<i64>> + <&'a i8 as Add<i8>> + <&'a isize as Add<isize>> + and 48 others + +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 f32 as Sub<f32>> + <&'a f64 as Sub<f64>> + <&'a i128 as Sub<i128>> + <&'a i16 as Sub<i16>> + <&'a i32 as Sub<i32>> + <&'a i64 as Sub<i64>> + <&'a i8 as Sub<i8>> + <&'a isize as Sub<isize>> + and 48 others + +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 f32 as Sub<f32>> + <&'a f64 as Sub<f64>> + <&'a i128 as Sub<i128>> + <&'a i16 as Sub<i16>> + <&'a i32 as Sub<i32>> + <&'a i64 as Sub<i64>> + <&'a i8 as Sub<i8>> + <&'a isize as Sub<isize>> + and 48 others + +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 f32 as Sub<f32>> + <&'a f64 as Sub<f64>> + <&'a i128 as Sub<i128>> + <&'a i16 as Sub<i16>> + <&'a i32 as Sub<i32>> + <&'a i64 as Sub<i64>> + <&'a i8 as Sub<i8>> + <&'a isize as Sub<isize>> + and 48 others + +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 f32 as Mul<f32>> + <&'a f64 as Mul<f64>> + <&'a i128 as Mul<i128>> + <&'a i16 as Mul<i16>> + <&'a i32 as Mul<i32>> + <&'a i64 as Mul<i64>> + <&'a i8 as Mul<i8>> + <&'a isize as Mul<isize>> + and 49 others + +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 f32 as Mul<f32>> + <&'a f64 as Mul<f64>> + <&'a i128 as Mul<i128>> + <&'a i16 as Mul<i16>> + <&'a i32 as Mul<i32>> + <&'a i64 as Mul<i64>> + <&'a i8 as Mul<i8>> + <&'a isize as Mul<isize>> + and 49 others + +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 f32 as Mul<f32>> + <&'a f64 as Mul<f64>> + <&'a i128 as Mul<i128>> + <&'a i16 as Mul<i16>> + <&'a i32 as Mul<i32>> + <&'a i64 as Mul<i64>> + <&'a i8 as Mul<i8>> + <&'a isize as Mul<isize>> + and 49 others + +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 f32 as Div<f32>> + <&'a f64 as Div<f64>> + <&'a i128 as Div<i128>> + <&'a i16 as Div<i16>> + <&'a i32 as Div<i32>> + <&'a i64 as Div<i64>> + <&'a i8 as Div<i8>> + <&'a isize as Div<isize>> + and 54 others + +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 f32 as Div<f32>> + <&'a f64 as Div<f64>> + <&'a i128 as Div<i128>> + <&'a i16 as Div<i16>> + <&'a i32 as Div<i32>> + <&'a i64 as Div<i64>> + <&'a i8 as Div<i8>> + <&'a isize as Div<isize>> + and 54 others + +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 f32 as Div<f32>> + <&'a f64 as Div<f64>> + <&'a i128 as Div<i128>> + <&'a i16 as Div<i16>> + <&'a i32 as Div<i32>> + <&'a i64 as Div<i64>> + <&'a i8 as Div<i8>> + <&'a isize as Div<isize>> + and 54 others + +error: aborting due to 12 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/numbers-arithmetic/num-wrapping.rs b/src/test/ui/numbers-arithmetic/num-wrapping.rs new file mode 100644 index 000000000..43b1059f9 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/numeric-method-autoexport.rs b/src/test/ui/numbers-arithmetic/numeric-method-autoexport.rs new file mode 100644 index 000000000..5798c2591 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/overflowing-add.rs b/src/test/ui/numbers-arithmetic/overflowing-add.rs new file mode 100644 index 000000000..b0f22a74b --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/overflowing-lsh-1.rs b/src/test/ui/numbers-arithmetic/overflowing-lsh-1.rs new file mode 100644 index 000000000..e5ce80336 --- /dev/null +++ b/src/test/ui/numbers-arithmetic/overflowing-lsh-1.rs @@ -0,0 +1,9 @@ +// build-fail +// compile-flags: -C debug-assertions + +#![deny(arithmetic_overflow, const_err)] + +fn main() { + let _x = 1_i32 << 32; + //~^ ERROR: this arithmetic operation will overflow +} diff --git a/src/test/ui/numbers-arithmetic/overflowing-lsh-1.stderr b/src/test/ui/numbers-arithmetic/overflowing-lsh-1.stderr new file mode 100644 index 000000000..1d029939c --- /dev/null +++ b/src/test/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, const_err)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/numbers-arithmetic/overflowing-lsh-2.rs b/src/test/ui/numbers-arithmetic/overflowing-lsh-2.rs new file mode 100644 index 000000000..7fd3407a0 --- /dev/null +++ b/src/test/ui/numbers-arithmetic/overflowing-lsh-2.rs @@ -0,0 +1,9 @@ +// build-fail +// compile-flags: -C debug-assertions + +#![deny(arithmetic_overflow, const_err)] + +fn main() { + let _x = 1 << -1; + //~^ ERROR: this arithmetic operation will overflow +} diff --git a/src/test/ui/numbers-arithmetic/overflowing-lsh-2.stderr b/src/test/ui/numbers-arithmetic/overflowing-lsh-2.stderr new file mode 100644 index 000000000..8598792e0 --- /dev/null +++ b/src/test/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, const_err)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/numbers-arithmetic/overflowing-lsh-3.rs b/src/test/ui/numbers-arithmetic/overflowing-lsh-3.rs new file mode 100644 index 000000000..e007eb4a2 --- /dev/null +++ b/src/test/ui/numbers-arithmetic/overflowing-lsh-3.rs @@ -0,0 +1,9 @@ +// build-fail +// compile-flags: -C debug-assertions + +#![deny(arithmetic_overflow, const_err)] + +fn main() { + let _x = 1_u64 << 64; + //~^ ERROR: this arithmetic operation will overflow +} diff --git a/src/test/ui/numbers-arithmetic/overflowing-lsh-3.stderr b/src/test/ui/numbers-arithmetic/overflowing-lsh-3.stderr new file mode 100644 index 000000000..9c6f806f1 --- /dev/null +++ b/src/test/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, const_err)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/numbers-arithmetic/overflowing-lsh-4.rs b/src/test/ui/numbers-arithmetic/overflowing-lsh-4.rs new file mode 100644 index 000000000..738d01339 --- /dev/null +++ b/src/test/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, const_err)] + +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/src/test/ui/numbers-arithmetic/overflowing-lsh-4.stderr b/src/test/ui/numbers-arithmetic/overflowing-lsh-4.stderr new file mode 100644 index 000000000..08081a0b7 --- /dev/null +++ b/src/test/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, const_err)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/numbers-arithmetic/overflowing-mul.rs b/src/test/ui/numbers-arithmetic/overflowing-mul.rs new file mode 100644 index 000000000..34ab5d8fa --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/overflowing-neg.rs b/src/test/ui/numbers-arithmetic/overflowing-neg.rs new file mode 100644 index 000000000..df1198053 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/overflowing-pow-signed.rs b/src/test/ui/numbers-arithmetic/overflowing-pow-signed.rs new file mode 100644 index 000000000..b59efe6f2 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/overflowing-pow-unsigned.rs b/src/test/ui/numbers-arithmetic/overflowing-pow-unsigned.rs new file mode 100644 index 000000000..f2643c164 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/overflowing-rsh-1.rs b/src/test/ui/numbers-arithmetic/overflowing-rsh-1.rs new file mode 100644 index 000000000..f1488cf85 --- /dev/null +++ b/src/test/ui/numbers-arithmetic/overflowing-rsh-1.rs @@ -0,0 +1,9 @@ +// build-fail +// compile-flags: -C debug-assertions + +#![deny(arithmetic_overflow, const_err)] + +fn main() { + let _x = -1_i32 >> 32; + //~^ ERROR: this arithmetic operation will overflow +} diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-1.stderr b/src/test/ui/numbers-arithmetic/overflowing-rsh-1.stderr new file mode 100644 index 000000000..4d726fa7f --- /dev/null +++ b/src/test/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, const_err)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-2.rs b/src/test/ui/numbers-arithmetic/overflowing-rsh-2.rs new file mode 100644 index 000000000..39127b970 --- /dev/null +++ b/src/test/ui/numbers-arithmetic/overflowing-rsh-2.rs @@ -0,0 +1,9 @@ +// build-fail +// compile-flags: -C debug-assertions + +#![deny(arithmetic_overflow, const_err)] + +fn main() { + let _x = -1_i32 >> -1; + //~^ ERROR: this arithmetic operation will overflow +} diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-2.stderr b/src/test/ui/numbers-arithmetic/overflowing-rsh-2.stderr new file mode 100644 index 000000000..9a8349d5d --- /dev/null +++ b/src/test/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, const_err)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-3.rs b/src/test/ui/numbers-arithmetic/overflowing-rsh-3.rs new file mode 100644 index 000000000..8ee6dde93 --- /dev/null +++ b/src/test/ui/numbers-arithmetic/overflowing-rsh-3.rs @@ -0,0 +1,9 @@ +// build-fail +// compile-flags: -C debug-assertions + +#![deny(arithmetic_overflow, const_err)] + +fn main() { + let _x = -1_i64 >> 64; + //~^ ERROR: this arithmetic operation will overflow +} diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-3.stderr b/src/test/ui/numbers-arithmetic/overflowing-rsh-3.stderr new file mode 100644 index 000000000..f48b7ff6d --- /dev/null +++ b/src/test/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, const_err)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-4.rs b/src/test/ui/numbers-arithmetic/overflowing-rsh-4.rs new file mode 100644 index 000000000..ce7f818e3 --- /dev/null +++ b/src/test/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, const_err)] + +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/src/test/ui/numbers-arithmetic/overflowing-rsh-4.stderr b/src/test/ui/numbers-arithmetic/overflowing-rsh-4.stderr new file mode 100644 index 000000000..4816a3899 --- /dev/null +++ b/src/test/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, const_err)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-5.rs b/src/test/ui/numbers-arithmetic/overflowing-rsh-5.rs new file mode 100644 index 000000000..88928c995 --- /dev/null +++ b/src/test/ui/numbers-arithmetic/overflowing-rsh-5.rs @@ -0,0 +1,9 @@ +// build-fail +// compile-flags: -C debug-assertions + +#![deny(arithmetic_overflow, const_err)] + +fn main() { + let _n = 1i64 >> [64][0]; + //~^ ERROR: this arithmetic operation will overflow +} diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-5.stderr b/src/test/ui/numbers-arithmetic/overflowing-rsh-5.stderr new file mode 100644 index 000000000..cd36f543d --- /dev/null +++ b/src/test/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, const_err)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-6.rs b/src/test/ui/numbers-arithmetic/overflowing-rsh-6.rs new file mode 100644 index 000000000..88928c995 --- /dev/null +++ b/src/test/ui/numbers-arithmetic/overflowing-rsh-6.rs @@ -0,0 +1,9 @@ +// build-fail +// compile-flags: -C debug-assertions + +#![deny(arithmetic_overflow, const_err)] + +fn main() { + let _n = 1i64 >> [64][0]; + //~^ ERROR: this arithmetic operation will overflow +} diff --git a/src/test/ui/numbers-arithmetic/overflowing-rsh-6.stderr b/src/test/ui/numbers-arithmetic/overflowing-rsh-6.stderr new file mode 100644 index 000000000..bec8b17df --- /dev/null +++ b/src/test/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, const_err)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/numbers-arithmetic/overflowing-sub.rs b/src/test/ui/numbers-arithmetic/overflowing-sub.rs new file mode 100644 index 000000000..66685ac96 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/promoted_overflow.rs b/src/test/ui/numbers-arithmetic/promoted_overflow.rs new file mode 100644 index 000000000..ba168f773 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/promoted_overflow_opt.rs b/src/test/ui/numbers-arithmetic/promoted_overflow_opt.rs new file mode 100644 index 000000000..4785abbc5 --- /dev/null +++ b/src/test/ui/numbers-arithmetic/promoted_overflow_opt.rs @@ -0,0 +1,9 @@ +// run-pass +#![allow(const_err)] + +// compile-flags: -O + +fn main() { + let x = &(0u32 - 1); + assert_eq!(*x, u32::MAX) +} diff --git a/src/test/ui/numbers-arithmetic/saturating-float-casts-impl.rs b/src/test/ui/numbers-arithmetic/saturating-float-casts-impl.rs new file mode 100644 index 000000000..4c6929d66 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/saturating-float-casts-wasm.rs b/src/test/ui/numbers-arithmetic/saturating-float-casts-wasm.rs new file mode 100644 index 000000000..cad059173 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/saturating-float-casts.rs b/src/test/ui/numbers-arithmetic/saturating-float-casts.rs new file mode 100644 index 000000000..cc248a9be --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/shift-near-oflo.rs b/src/test/ui/numbers-arithmetic/shift-near-oflo.rs new file mode 100644 index 000000000..55006a113 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/shift-various-types.rs b/src/test/ui/numbers-arithmetic/shift-various-types.rs new file mode 100644 index 000000000..473bda3d7 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/shift.rs b/src/test/ui/numbers-arithmetic/shift.rs new file mode 100644 index 000000000..2fc77928e --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/signed-shift-const-eval.rs b/src/test/ui/numbers-arithmetic/signed-shift-const-eval.rs new file mode 100644 index 000000000..6d0462b46 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/suggest-float-literal.fixed b/src/test/ui/numbers-arithmetic/suggest-float-literal.fixed new file mode 100644 index 000000000..9278262a6 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/suggest-float-literal.rs b/src/test/ui/numbers-arithmetic/suggest-float-literal.rs new file mode 100644 index 000000000..59e67f8d3 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr b/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr new file mode 100644 index 000000000..988379e58 --- /dev/null +++ b/src/test/ui/numbers-arithmetic/suggest-float-literal.stderr @@ -0,0 +1,179 @@ +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>> + <&'a f64 as Add<f64>> + <&'a i128 as Add<i128>> + <&'a i16 as Add<i16>> + <&'a i32 as Add<i32>> + <&'a i64 as Add<i64>> + <&'a i8 as Add<i8>> + <&'a isize as Add<isize>> + and 48 others +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 f32 as Add<f32>> + <&'a f64 as Add<f64>> + <&'a i128 as Add<i128>> + <&'a i16 as Add<i16>> + <&'a i32 as Add<i32>> + <&'a i64 as Add<i64>> + <&'a i8 as Add<i8>> + <&'a isize as Add<isize>> + and 48 others +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>> + <&'a f64 as Sub<f64>> + <&'a i128 as Sub<i128>> + <&'a i16 as Sub<i16>> + <&'a i32 as Sub<i32>> + <&'a i64 as Sub<i64>> + <&'a i8 as Sub<i8>> + <&'a isize as Sub<isize>> + and 48 others +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 f32 as Sub<f32>> + <&'a f64 as Sub<f64>> + <&'a i128 as Sub<i128>> + <&'a i16 as Sub<i16>> + <&'a i32 as Sub<i32>> + <&'a i64 as Sub<i64>> + <&'a i8 as Sub<i8>> + <&'a isize as Sub<isize>> + and 48 others +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>> + <&'a f64 as Mul<f64>> + <&'a i128 as Mul<i128>> + <&'a i16 as Mul<i16>> + <&'a i32 as Mul<i32>> + <&'a i64 as Mul<i64>> + <&'a i8 as Mul<i8>> + <&'a isize as Mul<isize>> + and 49 others +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 f32 as Mul<f32>> + <&'a f64 as Mul<f64>> + <&'a i128 as Mul<i128>> + <&'a i16 as Mul<i16>> + <&'a i32 as Mul<i32>> + <&'a i64 as Mul<i64>> + <&'a i8 as Mul<i8>> + <&'a isize as Mul<isize>> + and 49 others +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>> + <&'a f64 as Div<f64>> + <&'a i128 as Div<i128>> + <&'a i16 as Div<i16>> + <&'a i32 as Div<i32>> + <&'a i64 as Div<i64>> + <&'a i8 as Div<i8>> + <&'a isize as Div<isize>> + and 54 others +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 f32 as Div<f32>> + <&'a f64 as Div<f64>> + <&'a i128 as Div<i128>> + <&'a i16 as Div<i16>> + <&'a i32 as Div<i32>> + <&'a i64 as Div<i64>> + <&'a i8 as Div<i8>> + <&'a isize as Div<isize>> + and 54 others +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/src/test/ui/numbers-arithmetic/u128-as-f32.rs b/src/test/ui/numbers-arithmetic/u128-as-f32.rs new file mode 100644 index 000000000..839ce932d --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/u128.rs b/src/test/ui/numbers-arithmetic/u128.rs new file mode 100644 index 000000000..d7e28055b --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/u32-decr.rs b/src/test/ui/numbers-arithmetic/u32-decr.rs new file mode 100644 index 000000000..d9e097818 --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/u8-incr-decr.rs b/src/test/ui/numbers-arithmetic/u8-incr-decr.rs new file mode 100644 index 000000000..b16ec011d --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/u8-incr.rs b/src/test/ui/numbers-arithmetic/u8-incr.rs new file mode 100644 index 000000000..5242acf5b --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/uint.rs b/src/test/ui/numbers-arithmetic/uint.rs new file mode 100644 index 000000000..d219eae8f --- /dev/null +++ b/src/test/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/src/test/ui/numbers-arithmetic/unary-minus-suffix-inference.rs b/src/test/ui/numbers-arithmetic/unary-minus-suffix-inference.rs new file mode 100644 index 000000000..a4d0a8494 --- /dev/null +++ b/src/test/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); +} |