about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_mir/interpret/step.rs2
-rw-r--r--src/librustc_mir/transform/const_prop.rs49
2 files changed, 26 insertions, 25 deletions
diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs
index affca10bf52..daca7a25787 100644
--- a/src/librustc_mir/interpret/step.rs
+++ b/src/librustc_mir/interpret/step.rs
@@ -132,7 +132,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     ///
     /// There is no separate `eval_rvalue` function. Instead, the code for handling each rvalue
     /// type writes its results directly into the memory specified by the place.
-    fn eval_rvalue_into_place(
+    pub fn eval_rvalue_into_place(
         &mut self,
         rvalue: &mir::Rvalue<'tcx>,
         place: &mir::Place<'tcx>,
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index ff1a7c2c48f..d92eb4706bb 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -300,11 +300,16 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         rvalue: &Rvalue<'tcx>,
         place_layout: TyLayout<'tcx>,
         source_info: SourceInfo,
+        place: &Place<'tcx>,
     ) -> Option<Const<'tcx>> {
         let span = source_info.span;
         match *rvalue {
-            Rvalue::Use(ref op) => {
-                self.eval_operand(op, source_info)
+            Rvalue::Use(_) |
+            Rvalue::Len(_) => {
+                self.use_ecx(source_info, |this| {
+                    this.ecx.eval_rvalue_into_place(rvalue, place)?;
+                    this.ecx.eval_place_to_op(place, Some(place_layout))
+                })
             },
             Rvalue::Ref(_, _, ref place) => {
                 let src = self.eval_place(place, source_info)?;
@@ -324,22 +329,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                     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.kind {
-                    let len = mplace.meta.unwrap().to_usize(&self.ecx).unwrap();
-
-                    Some(ImmTy::from_uint(
-                        len,
-                        self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?,
-                    ).into())
-                } else {
-                    trace!("not slice: {:?}", mplace.layout.ty.kind);
-                    None
-                }
-            },
             Rvalue::NullaryOp(NullOp::SizeOf, ty) => {
                 type_size_of(self.tcx, self.param_env, ty).and_then(|n| Some(
                     ImmTy::from_uint(
@@ -626,15 +615,15 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
                 .ty(&self.local_decls, self.tcx)
                 .ty;
             if let Ok(place_layout) = self.tcx.layout_of(self.param_env.and(place_ty)) {
-                if let Some(value) = self.const_prop(rval, place_layout, statement.source_info) {
-                    if let Place {
-                        base: PlaceBase::Local(local),
-                        projection: box [],
-                    } = *place {
+                if let Place {
+                    base: PlaceBase::Local(local),
+                    projection: box [],
+                } = *place {
+                    if let Some(value) = self.const_prop(rval, place_layout, statement.source_info, place) {
                         trace!("checking whether {:?} can be stored to {:?}", value, local);
                         if self.can_const_prop[local] {
                             trace!("storing {:?} to {:?}", value, local);
-                            assert!(self.get_const(local).is_none());
+                            assert!(self.get_const(local).is_none() || self.get_const(local) == Some(value));
                             self.set_const(local, value);
 
                             if self.should_const_prop() {
@@ -648,6 +637,18 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
                     }
                 }
             }
+        } else if let StatementKind::StorageLive(local) = statement.kind {
+            if self.can_const_prop[local] {
+                let frame = self.ecx.frame_mut();
+
+                frame.locals[local].value = LocalValue::Uninitialized;
+            }
+        } else if let StatementKind::StorageDead(local) = statement.kind {
+            if self.can_const_prop[local] {
+                let frame = self.ecx.frame_mut();
+
+                frame.locals[local].value = LocalValue::Dead;
+            }
         }
         self.super_statement(statement, location);
     }