diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index b7cdb05a5d7..785b734b799 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -390,7 +390,7 @@ pub enum ErrKind { IndexedNonVec, IndexNegative, IndexNotInt, - IndexOutOfBounds, + IndexOutOfBounds { len: u64, index: u64 }, RepeatCountNotNatural, RepeatCountNotInt, @@ -441,7 +441,10 @@ pub fn description(&self) -> Cow { IndexedNonVec => "indexing is only supported for arrays".into_cow(), IndexNegative => "indices must be non-negative integers".into_cow(), IndexNotInt => "indices must be integers".into_cow(), - IndexOutOfBounds => "array index out of bounds".into_cow(), + IndexOutOfBounds { len, index } => { + format!("index out of bounds: the len is {} but the index is {}", + len, index).into_cow() + } RepeatCountNotNatural => "repeat count must be a natural number".into_cow(), RepeatCountNotInt => "repeat count must be integers".into_cow(), @@ -835,7 +838,9 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; assert_eq!(idx as usize as u64, idx); match arr { - Array(_, n) if idx >= n => signal!(e, IndexOutOfBounds), + Array(_, n) if idx >= n => { + signal!(e, IndexOutOfBounds { len: n, index: idx }) + } Array(v, n) => if let hir::ExprVec(ref v) = tcx.map.expect_expr(v).node { assert_eq!(n as usize as u64, n); eval_const_expr_partial(tcx, &v[idx as usize], ty_hint, fn_args)? @@ -843,7 +848,9 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, bug!() }, - Repeat(_, n) if idx >= n => signal!(e, IndexOutOfBounds), + Repeat(_, n) if idx >= n => { + signal!(e, IndexOutOfBounds { len: n, index: idx }) + } Repeat(elem, _) => eval_const_expr_partial( tcx, &tcx.map.expect_expr(elem), @@ -851,7 +858,9 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn_args, )?, - ByteStr(ref data) if idx >= data.len() as u64 => signal!(e, IndexOutOfBounds), + ByteStr(ref data) if idx >= data.len() as u64 => { + signal!(e, IndexOutOfBounds { len: data.len() as u64, index: idx }) + } ByteStr(data) => { Integral(U8(data[idx as usize])) }, diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index bd36c18a47e..6788d5de6d8 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -716,7 +716,10 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, if iv >= len { // FIXME #3170: report this earlier on in the const-eval // pass. Reporting here is a bit late. - const_err(cx, e.span, Err(ErrKind::IndexOutOfBounds), trueconst)?; + const_err(cx, e.span, Err(ErrKind::IndexOutOfBounds { + len: len, + index: iv + }), trueconst)?; C_undef(val_ty(arr).element_type()) } else { const_get_elt(arr, &[iv as c_uint]) diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index e73d02a1e29..e32e542ed89 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -298,8 +298,13 @@ fn trans(&mut self) -> Result, ConstEvalFailure> { let cond_bool = common::const_to_uint(cond.llval) != 0; if cond_bool != expected { let err = match *msg { - mir::AssertMessage::BoundsCheck {..} => { - ErrKind::IndexOutOfBounds + mir::AssertMessage::BoundsCheck { ref len, ref index } => { + let len = self.const_operand(len, span)?; + let index = self.const_operand(index, span)?; + ErrKind::IndexOutOfBounds { + len: common::const_to_uint(len.llval), + index: common::const_to_uint(index.llval) + } } mir::AssertMessage::Math(ref err) => { ErrKind::Math(err.clone()) diff --git a/src/test/compile-fail/array_const_index-0.rs b/src/test/compile-fail/array_const_index-0.rs index 1134dbfd1c4..e65230389f9 100644 --- a/src/test/compile-fail/array_const_index-0.rs +++ b/src/test/compile-fail/array_const_index-0.rs @@ -10,7 +10,7 @@ const A: &'static [i32] = &[]; const B: i32 = (&A)[1]; -//~^ ERROR: array index out of bounds +//~^ ERROR index out of bounds: the len is 0 but the index is 1 fn main() { let _ = B; diff --git a/src/test/compile-fail/array_const_index-1.rs b/src/test/compile-fail/array_const_index-1.rs index e59895cda44..69d84e24c49 100644 --- a/src/test/compile-fail/array_const_index-1.rs +++ b/src/test/compile-fail/array_const_index-1.rs @@ -9,7 +9,8 @@ // except according to those terms. const A: [i32; 0] = []; -const B: i32 = A[1]; //~ ERROR: array index out of bounds +const B: i32 = A[1]; +//~^ ERROR index out of bounds: the len is 0 but the index is 1 fn main() { let _ = B; diff --git a/src/test/compile-fail/const-array-oob.rs b/src/test/compile-fail/const-array-oob.rs index 15426febbcd..faabed4fd5e 100644 --- a/src/test/compile-fail/const-array-oob.rs +++ b/src/test/compile-fail/const-array-oob.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-tidy-linelength + #![feature(const_indexing)] const FOO: [u32; 3] = [1, 2, 3]; const BAR: u32 = FOO[5]; // no error, because the error below occurs before regular const eval const BLUB: [u32; FOO[4]] = [5, 6]; -//~^ ERROR array length constant evaluation error: array index out of bounds [E0250] +//~^ ERROR array length constant evaluation error: index out of bounds: the len is 3 but the index is 4 [E0250] fn main() { let _ = BAR; diff --git a/src/test/compile-fail/const-err-early.rs b/src/test/compile-fail/const-err-early.rs index 7567791c240..f666140970b 100644 --- a/src/test/compile-fail/const-err-early.rs +++ b/src/test/compile-fail/const-err-early.rs @@ -15,8 +15,10 @@ pub const B: u8 = 200u8 + 200u8; //~ ERROR attempted to add with overflow pub const C: u8 = 200u8 * 4; //~ ERROR attempted to multiply with overflow pub const D: u8 = 42u8 - (42u8 + 1); //~ ERROR attempted to subtract with overflow -pub const E: u8 = [5u8][1]; //~ ERROR index out of bounds +pub const E: u8 = [5u8][1]; +//~^ ERROR index out of bounds: the len is 1 but the index is 1 fn main() { - let _e = [6u8][1]; //~ ERROR: array index out of bounds + let _e = [6u8][1]; + //~^ ERROR index out of bounds: the len is 1 but the index is 1 } diff --git a/src/test/compile-fail/const-err.rs b/src/test/compile-fail/const-err.rs index 85d67f52bfe..ac2ef6662a4 100644 --- a/src/test/compile-fail/const-err.rs +++ b/src/test/compile-fail/const-err.rs @@ -20,8 +20,8 @@ fn black_box(_: T) { // Make sure that the two uses get two errors. const FOO: u8 = [5u8][1]; -//~^ ERROR array index out of bounds -//~^^ ERROR array index out of bounds +//~^ ERROR index out of bounds: the len is 1 but the index is 1 +//~^^ ERROR index out of bounds: the len is 1 but the index is 1 fn main() { let a = -std::i8::MIN; @@ -34,7 +34,7 @@ fn main() { let d = 42u8 - (42u8 + 1); //~^ WARN attempted to subtract with overflow let _e = [5u8][1]; - //~^ WARN array index out of bounds + //~^ WARN index out of bounds: the len is 1 but the index is 1 black_box(a); black_box(b); black_box(c); diff --git a/src/test/compile-fail/const-slice-oob.rs b/src/test/compile-fail/const-slice-oob.rs index b50468c33fd..d63b0097e5a 100644 --- a/src/test/compile-fail/const-slice-oob.rs +++ b/src/test/compile-fail/const-slice-oob.rs @@ -9,7 +9,8 @@ // except according to those terms. const FOO: &'static[u32] = &[1, 2, 3]; -const BAR: u32 = FOO[5]; //~ ERROR array index out of bounds +const BAR: u32 = FOO[5]; +//~^ ERROR index out of bounds: the len is 3 but the index is 5 fn main() { let _ = BAR;