diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index f261fdc268b5b..e4b186736e2a1 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -405,13 +405,16 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } let arg = self.eval_operand(arg, source_info)?; + let oflo_check = self.tcx.sess.overflow_checks(); let val = self.use_ecx(source_info, |this| { let prim = this.ecx.read_immediate(arg)?; match op { UnOp::Neg => { - // Need to do overflow check here: For actual CTFE, MIR - // generation emits code that does this before calling the op. - if prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) { + // We check overflow in debug mode already + // so should only check in release mode. + if !oflo_check + && prim.layout.ty.is_signed() + && prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) { throw_panic!(OverflowNeg) } } @@ -485,7 +488,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { Scalar::from_bool(overflow).into(), ) } else { - if overflow { + // We check overflow in debug mode already + // so should only check in release mode. + if !self.tcx.sess.overflow_checks() && overflow { let err = err_panic!(Overflow(op)).into(); let _: Option<()> = self.use_ecx(source_info, |_| Err(err)); return None; diff --git a/src/test/ui/consts/const-err2.rs b/src/test/ui/consts/const-err2.rs index a5f685a159b39..ecbcc2a4b496f 100644 --- a/src/test/ui/consts/const-err2.rs +++ b/src/test/ui/consts/const-err2.rs @@ -5,6 +5,7 @@ #![feature(rustc_attrs)] #![allow(exceeding_bitshifts)] + #![deny(const_err)] fn black_box(_: T) { @@ -21,7 +22,7 @@ fn main() { let d = 42u8 - (42u8 + 1); //~^ ERROR const_err let _e = [5u8][1]; - //~^ ERROR const_err + //~^ ERROR index out of bounds black_box(a); black_box(b); black_box(c); diff --git a/src/test/ui/consts/const-err2.stderr b/src/test/ui/consts/const-err2.stderr index 659c3afc618a9..1d84d44dc27b3 100644 --- a/src/test/ui/consts/const-err2.stderr +++ b/src/test/ui/consts/const-err2.stderr @@ -1,35 +1,35 @@ error: this expression will panic at runtime - --> $DIR/const-err2.rs:15:13 + --> $DIR/const-err2.rs:16:13 | LL | let a = -std::i8::MIN; | ^^^^^^^^^^^^^ attempt to negate with overflow | note: lint level defined here - --> $DIR/const-err2.rs:8:9 + --> $DIR/const-err2.rs:9:9 | LL | #![deny(const_err)] | ^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/const-err2.rs:17:13 + --> $DIR/const-err2.rs:18:13 | LL | let b = 200u8 + 200u8 + 200u8; | ^^^^^^^^^^^^^ attempt to add with overflow error: this expression will panic at runtime - --> $DIR/const-err2.rs:19:13 + --> $DIR/const-err2.rs:20:13 | LL | let c = 200u8 * 4; | ^^^^^^^^^ attempt to multiply with overflow error: this expression will panic at runtime - --> $DIR/const-err2.rs:21:13 + --> $DIR/const-err2.rs:22:13 | LL | let d = 42u8 - (42u8 + 1); | ^^^^^^^^^^^^^^^^^ attempt to subtract with overflow error: index out of bounds: the len is 1 but the index is 1 - --> $DIR/const-err2.rs:23:14 + --> $DIR/const-err2.rs:24:14 | LL | let _e = [5u8][1]; | ^^^^^^^^ diff --git a/src/test/ui/consts/const-err3.rs b/src/test/ui/consts/const-err3.rs new file mode 100644 index 0000000000000..a9cf04cda7a5a --- /dev/null +++ b/src/test/ui/consts/const-err3.rs @@ -0,0 +1,30 @@ +// needed because negating int::MIN will behave differently between +// optimized compilation and unoptimized compilation and thus would +// lead to different lints being emitted +// compile-flags: -C overflow-checks=on -O + +#![feature(rustc_attrs)] +#![allow(exceeding_bitshifts)] + +#![deny(const_err)] + +fn black_box(_: T) { + unimplemented!() +} + +fn main() { + let a = -std::i8::MIN; + //~^ ERROR const_err + let b = 200u8 + 200u8 + 200u8; + //~^ ERROR const_err + let c = 200u8 * 4; + //~^ ERROR const_err + let d = 42u8 - (42u8 + 1); + //~^ ERROR const_err + let _e = [5u8][1]; + //~^ ERROR const_err + black_box(a); + black_box(b); + black_box(c); + black_box(d); +} diff --git a/src/test/ui/consts/const-err3.stderr b/src/test/ui/consts/const-err3.stderr new file mode 100644 index 0000000000000..0602707be7040 --- /dev/null +++ b/src/test/ui/consts/const-err3.stderr @@ -0,0 +1,38 @@ +error: attempt to negate with overflow + --> $DIR/const-err3.rs:16:13 + | +LL | let a = -std::i8::MIN; + | ^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/const-err3.rs:9:9 + | +LL | #![deny(const_err)] + | ^^^^^^^^^ + +error: attempt to add with overflow + --> $DIR/const-err3.rs:18:13 + | +LL | let b = 200u8 + 200u8 + 200u8; + | ^^^^^^^^^^^^^ + +error: attempt to multiply with overflow + --> $DIR/const-err3.rs:20:13 + | +LL | let c = 200u8 * 4; + | ^^^^^^^^^ + +error: attempt to subtract with overflow + --> $DIR/const-err3.rs:22:13 + | +LL | let d = 42u8 - (42u8 + 1); + | ^^^^^^^^^^^^^^^^^ + +error: index out of bounds: the len is 1 but the index is 1 + --> $DIR/const-err3.rs:24:14 + | +LL | let _e = [5u8][1]; + | ^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs index cd989731452b3..45941398f4b66 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.rs +++ b/src/test/ui/consts/const-eval/promoted_errors.rs @@ -5,7 +5,7 @@ fn main() { println!("{}", 0u32 - 1); let _x = 0u32 - 1; - //~^ ERROR this expression will panic at runtime [const_err] + //~^ ERROR const_err println!("{}", 1/(1-1)); //~^ ERROR attempt to divide by zero [const_err] //~| ERROR reaching this expression at runtime will panic or abort [const_err] diff --git a/src/test/ui/consts/const-eval/promoted_errors2.rs b/src/test/ui/consts/const-eval/promoted_errors2.rs new file mode 100644 index 0000000000000..7adb394144bdd --- /dev/null +++ b/src/test/ui/consts/const-eval/promoted_errors2.rs @@ -0,0 +1,22 @@ +// compile-flags: -C overflow-checks=on -O + +#![deny(const_err)] + +fn main() { + println!("{}", 0u32 - 1); + //~^ ERROR attempt to subtract with overflow + let _x = 0u32 - 1; + //~^ ERROR attempt to subtract with overflow + println!("{}", 1/(1-1)); + //~^ ERROR attempt to divide by zero [const_err] + //~| ERROR reaching this expression at runtime will panic or abort [const_err] + let _x = 1/(1-1); + //~^ ERROR const_err + //~| ERROR const_err + println!("{}", 1/(false as u32)); + //~^ ERROR attempt to divide by zero [const_err] + //~| ERROR reaching this expression at runtime will panic or abort [const_err] + let _x = 1/(false as u32); + //~^ ERROR const_err + //~| ERROR const_err +} diff --git a/src/test/ui/consts/const-eval/promoted_errors2.stderr b/src/test/ui/consts/const-eval/promoted_errors2.stderr new file mode 100644 index 0000000000000..2819e6e8fdbe0 --- /dev/null +++ b/src/test/ui/consts/const-eval/promoted_errors2.stderr @@ -0,0 +1,68 @@ +error: attempt to subtract with overflow + --> $DIR/promoted_errors2.rs:6:20 + | +LL | println!("{}", 0u32 - 1); + | ^^^^^^^^ + | +note: lint level defined here + --> $DIR/promoted_errors2.rs:3:9 + | +LL | #![deny(const_err)] + | ^^^^^^^^^ + +error: attempt to subtract with overflow + --> $DIR/promoted_errors2.rs:8:14 + | +LL | let _x = 0u32 - 1; + | ^^^^^^^^ + +error: attempt to divide by zero + --> $DIR/promoted_errors2.rs:10:20 + | +LL | println!("{}", 1/(1-1)); + | ^^^^^^^ + +error: reaching this expression at runtime will panic or abort + --> $DIR/promoted_errors2.rs:10:20 + | +LL | println!("{}", 1/(1-1)); + | ^^^^^^^ attempt to divide by zero + +error: attempt to divide by zero + --> $DIR/promoted_errors2.rs:13:14 + | +LL | let _x = 1/(1-1); + | ^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/promoted_errors2.rs:13:14 + | +LL | let _x = 1/(1-1); + | ^^^^^^^ attempt to divide by zero + +error: attempt to divide by zero + --> $DIR/promoted_errors2.rs:16:20 + | +LL | println!("{}", 1/(false as u32)); + | ^^^^^^^^^^^^^^^^ + +error: reaching this expression at runtime will panic or abort + --> $DIR/promoted_errors2.rs:16:20 + | +LL | println!("{}", 1/(false as u32)); + | ^^^^^^^^^^^^^^^^ attempt to divide by zero + +error: attempt to divide by zero + --> $DIR/promoted_errors2.rs:19:14 + | +LL | let _x = 1/(false as u32); + | ^^^^^^^^^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/promoted_errors2.rs:19:14 + | +LL | let _x = 1/(false as u32); + | ^^^^^^^^^^^^^^^^ attempt to divide by zero + +error: aborting due to 10 previous errors + diff --git a/src/test/ui/consts/issue-64059-2.rs b/src/test/ui/consts/issue-64059-2.rs new file mode 100644 index 0000000000000..38911c3dcf692 --- /dev/null +++ b/src/test/ui/consts/issue-64059-2.rs @@ -0,0 +1,6 @@ +// compile-flags: -C overflow-checks=on -O +// run-pass + +fn main() { + let _ = -(-0.0); +} diff --git a/src/test/ui/consts/issue-64059.rs b/src/test/ui/consts/issue-64059.rs new file mode 100644 index 0000000000000..c4c895fef66cf --- /dev/null +++ b/src/test/ui/consts/issue-64059.rs @@ -0,0 +1,5 @@ +// run-pass + +fn main() { + let _ = -(-0.0); +} diff --git a/src/test/ui/issues/issue-8460-const2.rs b/src/test/ui/issues/issue-8460-const2.rs new file mode 100644 index 0000000000000..c3f53e3298b2b --- /dev/null +++ b/src/test/ui/issues/issue-8460-const2.rs @@ -0,0 +1,59 @@ +// compile-flags: -C overflow-checks=on -O + +#![deny(const_err)] + +use std::{isize, i8, i16, i32, i64}; +use std::thread; + +fn main() { + assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); + //~^ ERROR attempt to divide with overflow + assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); + //~^ ERROR attempt to divide with overflow + assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); + //~^ ERROR attempt to divide with overflow + assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); + //~^ ERROR attempt to divide with overflow + assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); + //~^ ERROR attempt to divide with overflow + assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); + //~^ ERROR attempt to divide by zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); + //~^ ERROR attempt to divide by zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); + //~^ ERROR attempt to divide by zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); + //~^ ERROR attempt to divide by zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); + //~^ ERROR attempt to divide by zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with overflow + assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with overflow + assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with overflow + assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with overflow + assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with overflow + assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with a divisor of zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with a divisor of zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with a divisor of zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with a divisor of zero + //~| ERROR this expression will panic at runtime + assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); + //~^ ERROR attempt to calculate the remainder with a divisor of zero + //~| ERROR this expression will panic at runtime +} diff --git a/src/test/ui/issues/issue-8460-const2.stderr b/src/test/ui/issues/issue-8460-const2.stderr new file mode 100644 index 0000000000000..b688ec1367794 --- /dev/null +++ b/src/test/ui/issues/issue-8460-const2.stderr @@ -0,0 +1,188 @@ +error: attempt to divide with overflow + --> $DIR/issue-8460-const2.rs:9:36 + | +LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/issue-8460-const2.rs:3:9 + | +LL | #![deny(const_err)] + | ^^^^^^^^^ + +error: attempt to divide with overflow + --> $DIR/issue-8460-const2.rs:11:36 + | +LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^ + +error: attempt to divide with overflow + --> $DIR/issue-8460-const2.rs:13:36 + | +LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ + +error: attempt to divide with overflow + --> $DIR/issue-8460-const2.rs:15:36 + | +LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ + +error: attempt to divide with overflow + --> $DIR/issue-8460-const2.rs:17:36 + | +LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ + +error: attempt to divide by zero + --> $DIR/issue-8460-const2.rs:19:36 + | +LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); + | ^^^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:19:36 + | +LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); + | ^^^^^^^^^^ attempt to divide by zero + +error: attempt to divide by zero + --> $DIR/issue-8460-const2.rs:22:36 + | +LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); + | ^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:22:36 + | +LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); + | ^^^^^^^ attempt to divide by zero + +error: attempt to divide by zero + --> $DIR/issue-8460-const2.rs:25:36 + | +LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); + | ^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:25:36 + | +LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide by zero + +error: attempt to divide by zero + --> $DIR/issue-8460-const2.rs:28:36 + | +LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); + | ^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:28:36 + | +LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide by zero + +error: attempt to divide by zero + --> $DIR/issue-8460-const2.rs:31:36 + | +LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); + | ^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:31:36 + | +LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide by zero + +error: attempt to calculate the remainder with overflow + --> $DIR/issue-8460-const2.rs:34:36 + | +LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^^^ + +error: attempt to calculate the remainder with overflow + --> $DIR/issue-8460-const2.rs:36:36 + | +LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^ + +error: attempt to calculate the remainder with overflow + --> $DIR/issue-8460-const2.rs:38:36 + | +LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ + +error: attempt to calculate the remainder with overflow + --> $DIR/issue-8460-const2.rs:40:36 + | +LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ + +error: attempt to calculate the remainder with overflow + --> $DIR/issue-8460-const2.rs:42:36 + | +LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ + +error: attempt to calculate the remainder with a divisor of zero + --> $DIR/issue-8460-const2.rs:44:36 + | +LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); + | ^^^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:44:36 + | +LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); + | ^^^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: attempt to calculate the remainder with a divisor of zero + --> $DIR/issue-8460-const2.rs:47:36 + | +LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); + | ^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:47:36 + | +LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); + | ^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: attempt to calculate the remainder with a divisor of zero + --> $DIR/issue-8460-const2.rs:50:36 + | +LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); + | ^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:50:36 + | +LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: attempt to calculate the remainder with a divisor of zero + --> $DIR/issue-8460-const2.rs:53:36 + | +LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); + | ^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:53:36 + | +LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: attempt to calculate the remainder with a divisor of zero + --> $DIR/issue-8460-const2.rs:56:36 + | +LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); + | ^^^^^^^^ + +error: this expression will panic at runtime + --> $DIR/issue-8460-const2.rs:56:36 + | +LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: aborting due to 30 previous errors +