about summary refs log tree commit diff
diff options
context:
space:
mode:
authorWesley Wiser <wwiser@gmail.com>2019-05-20 05:46:33 -0400
committerWesley Wiser <wwiser@gmail.com>2019-06-06 08:31:54 -0400
commitdee05ab2cca6d6d19cc73c6f900eee32e2dd5cbd (patch)
treed3c946fe8a4f2fbb6bd7480c6b12e0c5aa4796f1
parent1e50e01bb7c3200c48c8739435d4e7cece83ed6c (diff)
downloadrust-dee05ab2cca6d6d19cc73c6f900eee32e2dd5cbd.tar.gz
rust-dee05ab2cca6d6d19cc73c6f900eee32e2dd5cbd.zip
[const-prop] Handle Rvalue::Len
-rw-r--r--src/librustc_mir/transform/const_prop.rs29
-rw-r--r--src/test/mir-opt/const_prop/slice_len.rs40
2 files changed, 46 insertions, 23 deletions
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 693fc9ba2f3..0d389b31f90 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -17,8 +17,7 @@ use syntax_pos::{Span, DUMMY_SP};
 use rustc::ty::subst::InternalSubsts;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc::ty::layout::{
-    LayoutOf, TyLayout, LayoutError,
-    HasTyCtxt, TargetDataLayout, HasDataLayout,
+    LayoutOf, TyLayout, LayoutError, HasTyCtxt, TargetDataLayout, HasDataLayout, Size,
 };
 
 use crate::interpret::{
@@ -386,10 +385,30 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
                     this.ecx.cast(op, kind, dest.into())?;
                     Ok(dest.into())
                 })
-            }
+            },
+            Rvalue::Len(ref place) => {
+                let place = self.eval_place(&place, source_info)?;
+                let mplace = place.try_as_mplace().ok()?;
+
+                if let ty::Slice(_) = mplace.layout.ty.sty {
+                    let len = mplace.meta.unwrap().to_usize(&self.ecx).unwrap();
 
-            // FIXME(oli-obk): evaluate static/constant slice lengths
-            Rvalue::Len(_) => None,
+                    Some(ImmTy {
+                        imm: Immediate::Scalar(
+                            Scalar::from_uint(
+                                len,
+                                Size::from_bits(
+                                    self.tcx.sess.target.usize_ty.bit_width().unwrap() as u64
+                                )
+                            ).into(),
+                        ),
+                        layout: self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?,
+                    }.into())
+                } else {
+                    trace!("not slice: {:?}", mplace.layout.ty.sty);
+                    None
+                }
+            },
             Rvalue::NullaryOp(NullOp::SizeOf, ty) => {
                 type_size_of(self.tcx, self.param_env, ty).and_then(|n| Some(
                     ImmTy {
diff --git a/src/test/mir-opt/const_prop/slice_len.rs b/src/test/mir-opt/const_prop/slice_len.rs
index 3435ca07f4c..5babeb195a8 100644
--- a/src/test/mir-opt/const_prop/slice_len.rs
+++ b/src/test/mir-opt/const_prop/slice_len.rs
@@ -1,22 +1,22 @@
-fn test() -> &'static [u32] {
-    &[1, 2]
-}
-
 fn main() {
-    let x = test()[0];
+    (&[1u32, 2, 3] as &[u32])[1];
 }
 
 // END RUST SOURCE
 // START rustc.main.ConstProp.before.mir
-//  bb1: {
+//  bb0: {
 //      ...
-//      _3 = const 0usize;
-//      _4 = Len((*_2));
-//      _5 = Lt(_3, _4);
-//      assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> bb2;
+//      _4 = &(promoted[0]: [u32; 3]);
+//      _3 = _4;
+//      _2 = move _3 as &[u32] (Pointer(Unsize));
+//      ...
+//      _6 = const 1usize;
+//      _7 = Len((*_2));
+//      _8 = Lt(_6, _7);
+//      assert(move _8, "index out of bounds: the len is move _7 but the index is _6") -> bb1;
 //  }
-//  bb2: {
-//      _1 = (*_2)[_3];
+//  bb1: {
+//      _1 = (*_2)[_6];
 //      ...
 //      return;
 //  }
@@ -24,13 +24,17 @@ fn main() {
 // START rustc.main.ConstProp.after.mir
 //  bb0: {
 //      ...
-//      _3 = const 0usize;
-//      _4 = Len((*_2));
-//      _5 = Lt(_3, _4);
-//      assert(move _5, "index out of bounds: the len is move _4 but the index is _3") -> bb2;
+//      _4 = const Scalar(AllocId(0).0x0) : &[u32; 3];
+//      _3 = const Scalar(AllocId(0).0x0) : &[u32; 3];
+//      _2 = move _3 as &[u32] (Pointer(Unsize));
+//      ...
+//      _6 = const 1usize;
+//      _7 = const 3usize;
+//      _8 = const true;
+//      assert(const true, "index out of bounds: the len is move _7 but the index is _6") -> bb1;
 //  }
-//  bb2: {
-//      _1 = (*_2)[_3];
+//  bb1: {
+//      _1 = (*_2)[_6];
 //      ...
 //      return;
 //  }