@@ -11,7 +11,7 @@ use log::trace;
11
11
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
12
12
use rustc_middle:: mir:: RetagKind ;
13
13
use rustc_middle:: ty;
14
- use rustc_target:: abi:: Size ;
14
+ use rustc_target:: abi:: { LayoutOf , Size } ;
15
15
use rustc_hir:: Mutability ;
16
16
17
17
use crate :: * ;
@@ -569,7 +569,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
569
569
val : ImmTy < ' tcx , Tag > ,
570
570
kind : RefKind ,
571
571
protect : bool ,
572
- ) -> InterpResult < ' tcx , Immediate < Tag > > {
572
+ ) -> InterpResult < ' tcx , ImmTy < ' tcx , Tag > > {
573
573
let this = self . eval_context_mut ( ) ;
574
574
// We want a place for where the ptr *points to*, so we get one.
575
575
let place = this. ref_to_mplace ( val) ?;
@@ -582,7 +582,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
582
582
let place = this. mplace_access_checked ( place) ?;
583
583
if size == Size :: ZERO {
584
584
// Nothing to do for ZSTs.
585
- return Ok ( * val) ;
585
+ return Ok ( val) ;
586
586
}
587
587
588
588
// Compute new borrow.
@@ -603,7 +603,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
603
603
let new_place = place. replace_tag ( new_tag) ;
604
604
605
605
// Return new pointer.
606
- Ok ( new_place. to_ref ( ) )
606
+ Ok ( ImmTy :: from_immediate ( new_place. to_ref ( ) , val . layout ) )
607
607
}
608
608
}
609
609
@@ -640,9 +640,42 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
640
640
// Fast path.
641
641
let val = this. read_immediate ( this. place_to_op ( place) ?) ?;
642
642
let val = this. retag_reference ( val, mutbl, protector) ?;
643
- this. write_immediate ( val, place) ?;
643
+ this. write_immediate ( * val, place) ?;
644
644
}
645
645
646
646
Ok ( ( ) )
647
647
}
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
+ }
648
681
}
0 commit comments