Skip to content

Commit 4f643d7

Browse files
committed
rollup merge of rust-lang#23863: pnkfelix/arith-oflo-const-eval
const_eval : add overflow-checking for {`+`, `-`, `*`, `/`, `<<`, `>>`}. One tricky detail here: There is some duplication of labor between `rustc::middle::const_eval` and `rustc_trans::trans::consts`. It might be good to explore ways to try to factor out the common structure to the two passes (by abstracting over the particular value-representation used in the compile-time interpreter). ---- Update: Rebased atop rust-lang#23841 Fix rust-lang#22531 Fix rust-lang#23030 Fix rust-lang#23221 Fix rust-lang#23235
2 parents 72f5973 + 2a9de1d commit 4f643d7

30 files changed

+1727
-261
lines changed

src/libcore/num/wrapping.rs

+130
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ use intrinsics::{i16_mul_with_overflow, u16_mul_with_overflow};
3030
use intrinsics::{i32_mul_with_overflow, u32_mul_with_overflow};
3131
use intrinsics::{i64_mul_with_overflow, u64_mul_with_overflow};
3232

33+
use ::{i8,i16,i32,i64,u8,u16,u32,u64};
34+
3335
#[unstable(feature = "core", reason = "may be removed, renamed, or relocated")]
3436
#[deprecated(since = "1.0.0", reason = "moved to inherent methods")]
3537
pub trait WrappingOps {
@@ -43,6 +45,12 @@ pub trait OverflowingOps {
4345
fn overflowing_add(self, rhs: Self) -> (Self, bool);
4446
fn overflowing_sub(self, rhs: Self) -> (Self, bool);
4547
fn overflowing_mul(self, rhs: Self) -> (Self, bool);
48+
49+
fn overflowing_div(self, rhs: Self) -> (Self, bool);
50+
fn overflowing_rem(self, rhs: Self) -> (Self, bool);
51+
52+
fn overflowing_shl(self, rhs: u32) -> (Self, bool);
53+
fn overflowing_shr(self, rhs: u32) -> (Self, bool);
4654
}
4755

4856
macro_rules! sh_impl {
@@ -184,6 +192,20 @@ macro_rules! wrapping_impl {
184192

185193
wrapping_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
186194

195+
mod shift_max {
196+
#![allow(non_upper_case_globals)]
197+
198+
pub const i8: u32 = (1 << 3) - 1;
199+
pub const i16: u32 = (1 << 4) - 1;
200+
pub const i32: u32 = (1 << 5) - 1;
201+
pub const i64: u32 = (1 << 6) - 1;
202+
203+
pub const u8: u32 = i8;
204+
pub const u16: u32 = i16;
205+
pub const u32: u32 = i32;
206+
pub const u64: u32 = i64;
207+
}
208+
187209
macro_rules! overflowing_impl {
188210
($($t:ident)*) => ($(
189211
impl OverflowingOps for $t {
@@ -205,6 +227,34 @@ macro_rules! overflowing_impl {
205227
concat_idents!($t, _mul_with_overflow)(self, rhs)
206228
}
207229
}
230+
231+
#[inline(always)]
232+
fn overflowing_div(self, rhs: $t) -> ($t, bool) {
233+
if self == $t::MIN && rhs == -1 {
234+
(1, true)
235+
} else {
236+
(self/rhs, false)
237+
}
238+
}
239+
#[inline(always)]
240+
fn overflowing_rem(self, rhs: $t) -> ($t, bool) {
241+
if self == $t::MIN && rhs == -1 {
242+
(0, true)
243+
} else {
244+
(self % rhs, false)
245+
}
246+
}
247+
248+
#[inline(always)]
249+
fn overflowing_shl(self, rhs: u32) -> ($t, bool) {
250+
(self << (rhs & self::shift_max::$t),
251+
(rhs > self::shift_max::$t))
252+
}
253+
#[inline(always)]
254+
fn overflowing_shr(self, rhs: u32) -> ($t, bool) {
255+
(self >> (rhs & self::shift_max::$t),
256+
(rhs > self::shift_max::$t))
257+
}
208258
}
209259
)*)
210260
}
@@ -234,6 +284,26 @@ impl OverflowingOps for usize {
234284
(res.0 as usize, res.1)
235285
}
236286
}
287+
#[inline(always)]
288+
fn overflowing_div(self, rhs: usize) -> (usize, bool) {
289+
let (r, f) = (self as u64).overflowing_div(rhs as u64);
290+
(r as usize, f)
291+
}
292+
#[inline(always)]
293+
fn overflowing_rem(self, rhs: usize) -> (usize, bool) {
294+
let (r, f) = (self as u64).overflowing_rem(rhs as u64);
295+
(r as usize, f)
296+
}
297+
#[inline(always)]
298+
fn overflowing_shl(self, rhs: u32) -> (usize, bool) {
299+
let (r, f) = (self as u64).overflowing_shl(rhs);
300+
(r as usize, f)
301+
}
302+
#[inline(always)]
303+
fn overflowing_shr(self, rhs: u32) -> (usize, bool) {
304+
let (r, f) = (self as u64).overflowing_shr(rhs);
305+
(r as usize, f)
306+
}
237307
}
238308

239309
#[cfg(target_pointer_width = "32")]
@@ -259,6 +329,26 @@ impl OverflowingOps for usize {
259329
(res.0 as usize, res.1)
260330
}
261331
}
332+
#[inline(always)]
333+
fn overflowing_div(self, rhs: usize) -> (usize, bool) {
334+
let (r, f) = (self as u32).overflowing_div(rhs as u32);
335+
(r as usize, f)
336+
}
337+
#[inline(always)]
338+
fn overflowing_rem(self, rhs: usize) -> (usize, bool) {
339+
let (r, f) = (self as u32).overflowing_rem(rhs as u32);
340+
(r as usize, f)
341+
}
342+
#[inline(always)]
343+
fn overflowing_shl(self, rhs: u32) -> (usize, bool) {
344+
let (r, f) = (self as u32).overflowing_shl(rhs);
345+
(r as usize, f)
346+
}
347+
#[inline(always)]
348+
fn overflowing_shr(self, rhs: u32) -> (usize, bool) {
349+
let (r, f) = (self as u32).overflowing_shr(rhs);
350+
(r as usize, f)
351+
}
262352
}
263353

264354
#[cfg(target_pointer_width = "64")]
@@ -284,6 +374,26 @@ impl OverflowingOps for isize {
284374
(res.0 as isize, res.1)
285375
}
286376
}
377+
#[inline(always)]
378+
fn overflowing_div(self, rhs: isize) -> (isize, bool) {
379+
let (r, f) = (self as i64).overflowing_div(rhs as i64);
380+
(r as isize, f)
381+
}
382+
#[inline(always)]
383+
fn overflowing_rem(self, rhs: isize) -> (isize, bool) {
384+
let (r, f) = (self as i64).overflowing_rem(rhs as i64);
385+
(r as isize, f)
386+
}
387+
#[inline(always)]
388+
fn overflowing_shl(self, rhs: u32) -> (isize, bool) {
389+
let (r, f) = (self as i64).overflowing_shl(rhs);
390+
(r as isize, f)
391+
}
392+
#[inline(always)]
393+
fn overflowing_shr(self, rhs: u32) -> (isize, bool) {
394+
let (r, f) = (self as i64).overflowing_shr(rhs);
395+
(r as isize, f)
396+
}
287397
}
288398

289399
#[cfg(target_pointer_width = "32")]
@@ -309,4 +419,24 @@ impl OverflowingOps for isize {
309419
(res.0 as isize, res.1)
310420
}
311421
}
422+
#[inline(always)]
423+
fn overflowing_div(self, rhs: isize) -> (isize, bool) {
424+
let (r, f) = (self as i32).overflowing_div(rhs as i32);
425+
(r as isize, f)
426+
}
427+
#[inline(always)]
428+
fn overflowing_rem(self, rhs: isize) -> (isize, bool) {
429+
let (r, f) = (self as i32).overflowing_rem(rhs as i32);
430+
(r as isize, f)
431+
}
432+
#[inline(always)]
433+
fn overflowing_shl(self, rhs: u32) -> (isize, bool) {
434+
let (r, f) = (self as i32).overflowing_shl(rhs);
435+
(r as isize, f)
436+
}
437+
#[inline(always)]
438+
fn overflowing_shr(self, rhs: u32) -> (isize, bool) {
439+
let (r, f) = (self as i32).overflowing_shr(rhs);
440+
(r as isize, f)
441+
}
312442
}

src/libcoretest/num/uint_macros.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ mod tests {
2020
fn test_overflows() {
2121
assert!(MAX > 0);
2222
assert!(MIN <= 0);
23-
assert!(MIN + MAX + 1 == 0);
23+
assert!((MIN + MAX).wrapping_add(1) == 0);
2424
}
2525

2626
#[test]

src/librustc/diagnostics.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ register_diagnostics! {
6868
E0019,
6969
E0020,
7070
E0022,
71+
E0079, // enum variant: expected signed integer constant
72+
E0080, // enum variant: constant evaluation error
7173
E0109,
7274
E0110,
7375
E0133,
@@ -128,7 +130,8 @@ register_diagnostics! {
128130
E0313, // lifetime of borrowed pointer outlives lifetime of captured variable
129131
E0314, // closure outlives stack frame
130132
E0315, // cannot invoke closure outside of its lifetime
131-
E0316 // nested quantification of lifetimes
133+
E0316, // nested quantification of lifetimes
134+
E0370 // discriminant overflow
132135
}
133136

134137
__build_diagnostic_array! { DIAGNOSTICS }

src/librustc/middle/astencode.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1197,7 +1197,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
11971197
})
11981198
}
11991199

1200-
if let Some(ty) = tcx.node_types.borrow().get(&id) {
1200+
if let Some(ty) = tcx.node_types().get(&id) {
12011201
rbml_w.tag(c::tag_table_node_type, |rbml_w| {
12021202
rbml_w.id(id);
12031203
rbml_w.emit_ty(ecx, *ty);
@@ -1884,7 +1884,7 @@ fn decode_side_tables(dcx: &DecodeContext,
18841884
let ty = val_dsr.read_ty(dcx);
18851885
debug!("inserting ty for node {}: {}",
18861886
id, ty_to_string(dcx.tcx, ty));
1887-
dcx.tcx.node_types.borrow_mut().insert(id, ty);
1887+
dcx.tcx.node_type_insert(id, ty);
18881888
}
18891889
c::tag_table_item_subst => {
18901890
let item_substs = ty::ItemSubsts {

0 commit comments

Comments
 (0)