Skip to content

Commit 1447fbf

Browse files
committed
rustc_const_eval: track the length and index in IndexOutOfBounds.
1 parent afc598e commit 1447fbf

File tree

9 files changed

+40
-17
lines changed

9 files changed

+40
-17
lines changed

src/librustc_const_eval/eval.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ pub enum ErrKind {
390390
IndexedNonVec,
391391
IndexNegative,
392392
IndexNotInt,
393-
IndexOutOfBounds,
393+
IndexOutOfBounds { len: u64, index: u64 },
394394
RepeatCountNotNatural,
395395
RepeatCountNotInt,
396396

@@ -441,7 +441,10 @@ impl ConstEvalErr {
441441
IndexedNonVec => "indexing is only supported for arrays".into_cow(),
442442
IndexNegative => "indices must be non-negative integers".into_cow(),
443443
IndexNotInt => "indices must be integers".into_cow(),
444-
IndexOutOfBounds => "array index out of bounds".into_cow(),
444+
IndexOutOfBounds { len, index } => {
445+
format!("index out of bounds: the len is {} but the index is {}",
446+
len, index).into_cow()
447+
}
445448
RepeatCountNotNatural => "repeat count must be a natural number".into_cow(),
446449
RepeatCountNotInt => "repeat count must be integers".into_cow(),
447450

@@ -835,23 +838,29 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
835838
};
836839
assert_eq!(idx as usize as u64, idx);
837840
match arr {
838-
Array(_, n) if idx >= n => signal!(e, IndexOutOfBounds),
841+
Array(_, n) if idx >= n => {
842+
signal!(e, IndexOutOfBounds { len: n, index: idx })
843+
}
839844
Array(v, n) => if let hir::ExprVec(ref v) = tcx.map.expect_expr(v).node {
840845
assert_eq!(n as usize as u64, n);
841846
eval_const_expr_partial(tcx, &v[idx as usize], ty_hint, fn_args)?
842847
} else {
843848
bug!()
844849
},
845850

846-
Repeat(_, n) if idx >= n => signal!(e, IndexOutOfBounds),
851+
Repeat(_, n) if idx >= n => {
852+
signal!(e, IndexOutOfBounds { len: n, index: idx })
853+
}
847854
Repeat(elem, _) => eval_const_expr_partial(
848855
tcx,
849856
&tcx.map.expect_expr(elem),
850857
ty_hint,
851858
fn_args,
852859
)?,
853860

854-
ByteStr(ref data) if idx >= data.len() as u64 => signal!(e, IndexOutOfBounds),
861+
ByteStr(ref data) if idx >= data.len() as u64 => {
862+
signal!(e, IndexOutOfBounds { len: data.len() as u64, index: idx })
863+
}
855864
ByteStr(data) => {
856865
Integral(U8(data[idx as usize]))
857866
},

src/librustc_trans/consts.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -716,7 +716,10 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
716716
if iv >= len {
717717
// FIXME #3170: report this earlier on in the const-eval
718718
// pass. Reporting here is a bit late.
719-
const_err(cx, e.span, Err(ErrKind::IndexOutOfBounds), trueconst)?;
719+
const_err(cx, e.span, Err(ErrKind::IndexOutOfBounds {
720+
len: len,
721+
index: iv
722+
}), trueconst)?;
720723
C_undef(val_ty(arr).element_type())
721724
} else {
722725
const_get_elt(arr, &[iv as c_uint])

src/librustc_trans/mir/constant.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,8 +298,13 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
298298
let cond_bool = common::const_to_uint(cond.llval) != 0;
299299
if cond_bool != expected {
300300
let err = match *msg {
301-
mir::AssertMessage::BoundsCheck {..} => {
302-
ErrKind::IndexOutOfBounds
301+
mir::AssertMessage::BoundsCheck { ref len, ref index } => {
302+
let len = self.const_operand(len, span)?;
303+
let index = self.const_operand(index, span)?;
304+
ErrKind::IndexOutOfBounds {
305+
len: common::const_to_uint(len.llval),
306+
index: common::const_to_uint(index.llval)
307+
}
303308
}
304309
mir::AssertMessage::Math(ref err) => {
305310
ErrKind::Math(err.clone())

src/test/compile-fail/array_const_index-0.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
const A: &'static [i32] = &[];
1212
const B: i32 = (&A)[1];
13-
//~^ ERROR: array index out of bounds
13+
//~^ ERROR index out of bounds: the len is 0 but the index is 1
1414

1515
fn main() {
1616
let _ = B;

src/test/compile-fail/array_const_index-1.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
// except according to those terms.
1010

1111
const A: [i32; 0] = [];
12-
const B: i32 = A[1]; //~ ERROR: array index out of bounds
12+
const B: i32 = A[1];
13+
//~^ ERROR index out of bounds: the len is 0 but the index is 1
1314

1415
fn main() {
1516
let _ = B;

src/test/compile-fail/const-array-oob.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// ignore-tidy-linelength
12+
1113
#![feature(const_indexing)]
1214

1315
const FOO: [u32; 3] = [1, 2, 3];
1416
const BAR: u32 = FOO[5]; // no error, because the error below occurs before regular const eval
1517

1618
const BLUB: [u32; FOO[4]] = [5, 6];
17-
//~^ ERROR array length constant evaluation error: array index out of bounds [E0250]
19+
//~^ ERROR array length constant evaluation error: index out of bounds: the len is 3 but the index is 4 [E0250]
1820

1921
fn main() {
2022
let _ = BAR;

src/test/compile-fail/const-err-early.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@ pub const A: i8 = -std::i8::MIN; //~ ERROR attempted to negate with overflow
1515
pub const B: u8 = 200u8 + 200u8; //~ ERROR attempted to add with overflow
1616
pub const C: u8 = 200u8 * 4; //~ ERROR attempted to multiply with overflow
1717
pub const D: u8 = 42u8 - (42u8 + 1); //~ ERROR attempted to subtract with overflow
18-
pub const E: u8 = [5u8][1]; //~ ERROR index out of bounds
18+
pub const E: u8 = [5u8][1];
19+
//~^ ERROR index out of bounds: the len is 1 but the index is 1
1920

2021
fn main() {
21-
let _e = [6u8][1]; //~ ERROR: array index out of bounds
22+
let _e = [6u8][1];
23+
//~^ ERROR index out of bounds: the len is 1 but the index is 1
2224
}

src/test/compile-fail/const-err.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ fn black_box<T>(_: T) {
2020

2121
// Make sure that the two uses get two errors.
2222
const FOO: u8 = [5u8][1];
23-
//~^ ERROR array index out of bounds
24-
//~^^ ERROR array index out of bounds
23+
//~^ ERROR index out of bounds: the len is 1 but the index is 1
24+
//~^^ ERROR index out of bounds: the len is 1 but the index is 1
2525

2626
fn main() {
2727
let a = -std::i8::MIN;
@@ -34,7 +34,7 @@ fn main() {
3434
let d = 42u8 - (42u8 + 1);
3535
//~^ WARN attempted to subtract with overflow
3636
let _e = [5u8][1];
37-
//~^ WARN array index out of bounds
37+
//~^ WARN index out of bounds: the len is 1 but the index is 1
3838
black_box(a);
3939
black_box(b);
4040
black_box(c);

src/test/compile-fail/const-slice-oob.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
// except according to those terms.
1010

1111
const FOO: &'static[u32] = &[1, 2, 3];
12-
const BAR: u32 = FOO[5]; //~ ERROR array index out of bounds
12+
const BAR: u32 = FOO[5];
13+
//~^ ERROR index out of bounds: the len is 3 but the index is 5
1314

1415
fn main() {
1516
let _ = BAR;

0 commit comments

Comments
 (0)