@@ -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