diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index affca10bf526..daca7a25787c 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 ff1a7c2c48fd..d92eb4706bb2 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> { 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); }