Skip to content

Commit 545a3a9

Browse files
authored
Auto merge of #35300 - eddyb:mir-neg-overflow, r=arielb1
rustc_trans: don't Assert(Overflow(Neg)) when overflow checks are off. Generic functions using `Neg` on primitive types would panic even in release mode, with MIR trans. The solution is a bit hacky, as I'm checking the message, since there's no dedicated `CheckedUnOp`. Blocks Servo rustup ([failure #1](http://build.servo.org/builders/linux-rel/builds/2477/steps/test_3/logs/stdio), [failure #2](http://build.servo.org/builders/mac-rel-css/builds/2364/steps/test/logs/stdio)) - this should be the last hurdle, it affects only one test.
2 parents e804a3c + fbabe61 commit 545a3a9

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

src/librustc_trans/mir/block.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,23 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
261261

262262
mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, cleanup } => {
263263
let cond = self.trans_operand(&bcx, cond).immediate();
264-
let const_cond = common::const_to_opt_uint(cond).map(|c| c == 1);
264+
let mut const_cond = common::const_to_opt_uint(cond).map(|c| c == 1);
265+
266+
// This case can currently arise only from functions marked
267+
// with #[rustc_inherit_overflow_checks] and inlined from
268+
// another crate (mostly core::num generic/#[inline] fns),
269+
// while the current crate doesn't use overflow checks.
270+
// NOTE: Unlike binops, negation doesn't have its own
271+
// checked operation, just a comparison with the minimum
272+
// value, so we have to check for the assert message.
273+
if !bcx.ccx().check_overflow() {
274+
use rustc_const_math::ConstMathErr::Overflow;
275+
use rustc_const_math::Op::Neg;
276+
277+
if let mir::AssertMessage::Math(Overflow(Neg)) = *msg {
278+
const_cond = Some(expected);
279+
}
280+
}
265281

266282
// Don't translate the panic block if success if known.
267283
if const_cond == Some(expected) {

src/test/run-pass/mir_overflow_off.rs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: -Z force-overflow-checks=off -Z orbit
12+
13+
// Test that with MIR trans, overflow checks can be
14+
// turned off, even when they're from core::ops::*.
15+
16+
use std::ops::*;
17+
18+
fn main() {
19+
assert_eq!(i8::neg(-0x80), -0x80);
20+
21+
assert_eq!(u8::add(0xff, 1), 0_u8);
22+
assert_eq!(u8::sub(0, 1), 0xff_u8);
23+
assert_eq!(u8::mul(0xff, 2), 0xfe_u8);
24+
assert_eq!(u8::shl(1, 9), 2_u8);
25+
assert_eq!(u8::shr(2, 9), 1_u8);
26+
}

0 commit comments

Comments
 (0)