diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index d645f6cf183..d09165f904a 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -518,18 +518,19 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } } - fn check_unary_op(&mut self, arg: &Operand<'tcx>, source_info: SourceInfo) -> Option<()> { + fn check_unary_op( + &mut self, + op: UnOp, + arg: &Operand<'tcx>, + source_info: SourceInfo, + ) -> Option<()> { self.use_ecx(source_info, |this| { - let ty = arg.ty(&this.local_decls, this.tcx); + let val = this.ecx.read_immediate(this.ecx.eval_operand(arg, None)?)?; + let (_res, overflow, _ty) = this.ecx.overflowing_unary_op(op, val)?; - if ty.is_integral() { - let arg = this.ecx.eval_operand(arg, None)?; - let prim = this.ecx.read_immediate(arg)?; - // 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)) { - throw_panic!(OverflowNeg) - } + if overflow { + assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow"); + throw_panic!(OverflowNeg); } Ok(()) @@ -574,11 +575,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { if !overflow_check { self.use_ecx(source_info, |this| { let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?; - let (_, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?; + let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?; if overflow { - let err = err_panic!(Overflow(op)).into(); - return Err(err); + throw_panic!(Overflow(op)); } Ok(()) @@ -618,9 +618,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // Additional checking: if overflow checks are disabled (which is usually the case in // release mode), then we need to do additional checking here to give lints to the user // if an overflow would occur. - Rvalue::UnaryOp(UnOp::Neg, arg) if !overflow_check => { - trace!("checking UnaryOp(op = Neg, arg = {:?})", arg); - self.check_unary_op(arg, source_info)?; + Rvalue::UnaryOp(op, arg) if !overflow_check => { + trace!("checking UnaryOp(op = {:?}, arg = {:?})", op, arg); + self.check_unary_op(*op, arg, source_info)?; } // Additional checking: check for overflows on integer binary operations and report