Skip to content

Commit dee05ab

Browse files
committed
[const-prop] Handle Rvalue::Len
1 parent 1e50e01 commit dee05ab

File tree

2 files changed

+46
-23
lines changed

2 files changed

+46
-23
lines changed

src/librustc_mir/transform/const_prop.rs

+24-5
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ use syntax_pos::{Span, DUMMY_SP};
1717
use rustc::ty::subst::InternalSubsts;
1818
use rustc_data_structures::indexed_vec::IndexVec;
1919
use rustc::ty::layout::{
20-
LayoutOf, TyLayout, LayoutError,
21-
HasTyCtxt, TargetDataLayout, HasDataLayout,
20+
LayoutOf, TyLayout, LayoutError, HasTyCtxt, TargetDataLayout, HasDataLayout, Size,
2221
};
2322

2423
use crate::interpret::{
@@ -386,10 +385,30 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
386385
this.ecx.cast(op, kind, dest.into())?;
387386
Ok(dest.into())
388387
})
389-
}
388+
},
389+
Rvalue::Len(ref place) => {
390+
let place = self.eval_place(&place, source_info)?;
391+
let mplace = place.try_as_mplace().ok()?;
392+
393+
if let ty::Slice(_) = mplace.layout.ty.sty {
394+
let len = mplace.meta.unwrap().to_usize(&self.ecx).unwrap();
390395

391-
// FIXME(oli-obk): evaluate static/constant slice lengths
392-
Rvalue::Len(_) => None,
396+
Some(ImmTy {
397+
imm: Immediate::Scalar(
398+
Scalar::from_uint(
399+
len,
400+
Size::from_bits(
401+
self.tcx.sess.target.usize_ty.bit_width().unwrap() as u64
402+
)
403+
).into(),
404+
),
405+
layout: self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?,
406+
}.into())
407+
} else {
408+
trace!("not slice: {:?}", mplace.layout.ty.sty);
409+
None
410+
}
411+
},
393412
Rvalue::NullaryOp(NullOp::SizeOf, ty) => {
394413
type_size_of(self.tcx, self.param_env, ty).and_then(|n| Some(
395414
ImmTy {

src/test/mir-opt/const_prop/slice_len.rs

+22-18
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,40 @@
1-
fn test() -> &'static [u32] {
2-
&[1, 2]
3-
}
4-
51
fn main() {
6-
let x = test()[0];
2+
(&[1u32, 2, 3] as &[u32])[1];
73
}
84

95
// END RUST SOURCE
106
// START rustc.main.ConstProp.before.mir
11-
// bb1: {
7+
// bb0: {
128
// ...
13-
// _3 = const 0usize;
14-
// _4 = Len((*_2));
15-
// _5 = Lt(_3, _4);
16-
// assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> bb2;
9+
// _4 = &(promoted[0]: [u32; 3]);
10+
// _3 = _4;
11+
// _2 = move _3 as &[u32] (Pointer(Unsize));
12+
// ...
13+
// _6 = const 1usize;
14+
// _7 = Len((*_2));
15+
// _8 = Lt(_6, _7);
16+
// assert(move _8, "index out of bounds: the len is move _7 but the index is _6") -> bb1;
1717
// }
18-
// bb2: {
19-
// _1 = (*_2)[_3];
18+
// bb1: {
19+
// _1 = (*_2)[_6];
2020
// ...
2121
// return;
2222
// }
2323
// END rustc.main.ConstProp.before.mir
2424
// START rustc.main.ConstProp.after.mir
2525
// bb0: {
2626
// ...
27-
// _3 = const 0usize;
28-
// _4 = Len((*_2));
29-
// _5 = Lt(_3, _4);
30-
// assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> bb2;
27+
// _4 = const Scalar(AllocId(0).0x0) : &[u32; 3];
28+
// _3 = const Scalar(AllocId(0).0x0) : &[u32; 3];
29+
// _2 = move _3 as &[u32] (Pointer(Unsize));
30+
// ...
31+
// _6 = const 1usize;
32+
// _7 = const 3usize;
33+
// _8 = const true;
34+
// assert(const true, "index out of bounds: the len is move _7 but the index is _6") -> bb1;
3135
// }
32-
// bb2: {
33-
// _1 = (*_2)[_3];
36+
// bb1: {
37+
// _1 = (*_2)[_6];
3438
// ...
3539
// return;
3640
// }

0 commit comments

Comments
 (0)