diff --git a/src/eval_context.rs b/src/eval_context.rs index f364f829f903..b923ef24dccd 100644 --- a/src/eval_context.rs +++ b/src/eval_context.rs @@ -1720,15 +1720,12 @@ impl<'tcx> Frame<'tcx> { return Ok(()); } - pub fn storage_live(&mut self, local: mir::Local) -> EvalResult<'tcx> { + pub fn storage_live(&mut self, local: mir::Local) -> EvalResult<'tcx, Option> { trace!("{:?} is now live", local); - if self.locals[local.index() - 1].is_some() { - // The variables comes live now, but was already accessed previously, when it was still dead - return Err(EvalError::DeadLocal); - } else { - self.locals[local.index() - 1] = Some(Value::ByVal(PrimVal::Undef)); - } - return Ok(()); + + let old = self.locals[local.index() - 1]; + self.locals[local.index() - 1] = Some(Value::ByVal(PrimVal::Undef)); // StorageLive *always* kills the value that's currently stored + return Ok(old); } /// Returns the old value of the local diff --git a/src/step.rs b/src/step.rs index 1df55a8b620d..aef73f8eb0d9 100644 --- a/src/step.rs +++ b/src/step.rs @@ -132,13 +132,12 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Lvalue::Local{ frame, local, field: None } if self.stack.len() == frame+1 => (frame, local), _ => return Err(EvalError::Unimplemented("Stroage annotations must refer to locals of the topmost stack frame.".to_owned())) // FIXME maybe this should get its own error type }; - match stmt.kind { + let old_val = match stmt.kind { StorageLive(_) => self.stack[frame].storage_live(local)?, - _ => { - let old_val = self.stack[frame].storage_dead(local)?; - self.deallocate_local(old_val)?; - } + StorageDead(_) => self.stack[frame].storage_dead(local)?, + _ => bug!("We already checked that we are a storage stmt") }; + self.deallocate_local(old_val)?; } // Defined to do nothing. These are added by optimization passes, to avoid changing the