@@ -840,36 +840,31 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
840
840
Ok(())
841
841
}
842
842
843
- /// Mark a storage as live, killing the previous content and returning it.
844
- /// Remember to deallocate that!
845
- pub fn storage_live(
846
- &mut self,
847
- local: mir::Local,
848
- ) -> InterpResult<'tcx, LocalValue<M::PointerTag>> {
843
+ /// Mark a storage as live, killing the previous content.
844
+ pub fn storage_live(&mut self, local: mir::Local) -> InterpResult<'tcx> {
849
845
assert!(local != mir::RETURN_PLACE, "Cannot make return place live");
850
846
trace!("{:?} is now live", local);
851
847
852
848
let local_val = LocalValue::Uninitialized;
853
- // StorageLive *always* kills the value that's currently stored.
854
- // However, we do not error if the variable already is live;
855
- // see <https://github.com/rust-lang/rust/issues/42371>.
856
- Ok(mem::replace(&mut self.frame_mut().locals[local].value, local_val))
849
+ // StorageLive expects the local to be dead, and marks it live.
850
+ let old = mem::replace(&mut self.frame_mut().locals[local].value, local_val);
851
+ if !matches!(old, LocalValue::Dead) {
852
+ throw_ub_format!("StorageLive on a local that was already live");
853
+ }
854
+ Ok(())
857
855
}
858
856
859
- /// Returns the old value of the local.
860
- /// Remember to deallocate that!
861
- pub fn storage_dead(&mut self, local: mir::Local) -> LocalValue<M::PointerTag> {
857
+ pub fn storage_dead(&mut self, local: mir::Local) -> InterpResult<'tcx> {
862
858
assert!(local != mir::RETURN_PLACE, "Cannot make return place dead");
863
859
trace!("{:?} is now dead", local);
864
860
865
- mem::replace(&mut self.frame_mut().locals[local].value, LocalValue::Dead)
861
+ // It is entirely okay for this local to be already dead (at least that's how we currently generate MIR)
862
+ let old = mem::replace(&mut self.frame_mut().locals[local].value, LocalValue::Dead);
863
+ self.deallocate_local(old)?;
864
+ Ok(())
866
865
}
867
866
868
- pub(super) fn deallocate_local(
869
- &mut self,
870
- local: LocalValue<M::PointerTag>,
871
- ) -> InterpResult<'tcx> {
872
- // FIXME: should we tell the user that there was a local which was never written to?
867
+ fn deallocate_local(&mut self, local: LocalValue<M::PointerTag>) -> InterpResult<'tcx> {
873
868
if let LocalValue::Live(Operand::Indirect(MemPlace { ptr, .. })) = local {
874
869
// All locals have a backing allocation, even if the allocation is empty
875
870
// due to the local having ZST type.
0 commit comments