@@ -11,7 +11,7 @@ use log::trace;
1111use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
1212use rustc_middle:: mir:: RetagKind ;
1313use rustc_middle:: ty;
14- use rustc_target:: abi:: Size ;
14+ use rustc_target:: abi:: { LayoutOf , Size } ;
1515use rustc_hir:: Mutability ;
1616
1717use crate :: * ;
@@ -569,7 +569,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
569569 val : ImmTy < ' tcx , Tag > ,
570570 kind : RefKind ,
571571 protect : bool ,
572- ) -> InterpResult < ' tcx , Immediate < Tag > > {
572+ ) -> InterpResult < ' tcx , ImmTy < ' tcx , Tag > > {
573573 let this = self . eval_context_mut ( ) ;
574574 // We want a place for where the ptr *points to*, so we get one.
575575 let place = this. ref_to_mplace ( val) ?;
@@ -582,7 +582,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
582582 let place = this. mplace_access_checked ( place) ?;
583583 if size == Size :: ZERO {
584584 // Nothing to do for ZSTs.
585- return Ok ( * val) ;
585+ return Ok ( val) ;
586586 }
587587
588588 // Compute new borrow.
@@ -603,7 +603,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
603603 let new_place = place. replace_tag ( new_tag) ;
604604
605605 // Return new pointer.
606- Ok ( new_place. to_ref ( ) )
606+ Ok ( ImmTy :: from_immediate ( new_place. to_ref ( ) , val . layout ) )
607607 }
608608}
609609
@@ -640,9 +640,42 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
640640 // Fast path.
641641 let val = this. read_immediate ( this. place_to_op ( place) ?) ?;
642642 let val = this. retag_reference ( val, mutbl, protector) ?;
643- this. write_immediate ( val, place) ?;
643+ this. write_immediate ( * val, place) ?;
644644 }
645645
646646 Ok ( ( ) )
647647 }
648+
649+ /// After a stack frame got pushed, retag the return place so that we are sure
650+ /// it does not alias with anything.
651+ ///
652+ /// This is a HACK because there is nothing in MIR that would make the retag
653+ /// explicit. Also see https://github.com/rust-lang/rust/issues/71117.
654+ fn retag_return_place ( & mut self ) -> InterpResult < ' tcx > {
655+ let this = self . eval_context_mut ( ) ;
656+ let return_place = if let Some ( return_place) = this. frame_mut ( ) . return_place {
657+ return_place
658+ } else {
659+ // No return place, nothing to do.
660+ return Ok ( ( ) ) ;
661+ } ;
662+ if return_place. layout . is_zst ( ) {
663+ // There may not be any memory here, nothing to do.
664+ return Ok ( ( ) ) ;
665+ }
666+ // We need this to be in-memory to use tagged pointers.
667+ let return_place = this. force_allocation ( return_place) ?;
668+
669+ // We have to turn the place into a pointer to use the existing code.
670+ // (The pointer type does not matter, so we use a raw pointer.)
671+ let ptr_layout = this. layout_of ( this. tcx . mk_mut_ptr ( return_place. layout . ty ) ) ?;
672+ let val = ImmTy :: from_immediate ( return_place. to_ref ( ) , ptr_layout) ;
673+ // Reborrow it.
674+ let val = this. retag_reference ( val, RefKind :: Unique { two_phase : false } , /*protector*/ true ) ?;
675+ // And use reborrowed pointer for return place.
676+ let return_place = this. ref_to_mplace ( val) ?;
677+ this. frame_mut ( ) . return_place = Some ( return_place. into ( ) ) ;
678+
679+ Ok ( ( ) )
680+ }
648681}
0 commit comments