@@ -976,27 +976,30 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
976976 // Raw pointers need to be enabled.
977977 ty:: RawPtr ( tym) if kind == RetagKind :: Raw =>
978978 Some ( ( RefKind :: Raw { mutable : tym. mutbl == Mutability :: Mut } , false ) ) ,
979- // Boxes do not get a protector: protectors reflect that references outlive the call
980- // they were passed in to; that's just not the case for boxes.
981- ty:: Adt ( ..) if ty. is_box ( ) => Some ( ( RefKind :: Unique { two_phase : false } , false ) ) ,
979+ // Boxes are handled separately due to that allocator situation.
982980 _ => None ,
983981 }
984982 }
985983
986984 // We need a visitor to visit all references. However, that requires
987- // a `MPlaceTy` (or `OpTy), so we have a fast path for reference types that
985+ // a `MPlaceTy` (or `OpTy` ), so we have a fast path for reference types that
988986 // avoids allocating.
989987
990- if let Some ( ( mutbl , protector) ) = qualify ( place. layout . ty , kind) {
988+ if let Some ( ( ref_kind , protector) ) = qualify ( place. layout . ty , kind) {
991989 // Fast path.
992990 let val = this. read_immediate ( & this. place_to_op ( place) ?) ?;
993- let val = this. retag_reference ( & val, mutbl , protector) ?;
991+ let val = this. retag_reference ( & val, ref_kind , protector) ?;
994992 this. write_immediate ( * val, place) ?;
995993 return Ok ( ( ) ) ;
996994 }
997995
998996 // If we don't want to recurse, we are already done.
999- if !this. machine . stacked_borrows . as_mut ( ) . unwrap ( ) . get_mut ( ) . retag_fields {
997+ // EXCEPT if this is a `Box`, then we have to recurse because allocators.
998+ // (Yes this means we technically also recursively retag the allocator itself even if field
999+ // retagging is not enabled. *shrug*)
1000+ if !this. machine . stacked_borrows . as_mut ( ) . unwrap ( ) . get_mut ( ) . retag_fields
1001+ && !place. layout . ty . ty_adt_def ( ) . is_some_and ( |adt| adt. is_box ( ) )
1002+ {
10001003 return Ok ( ( ) ) ;
10011004 }
10021005
@@ -1034,10 +1037,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
10341037 self . ecx
10351038 }
10361039
1040+ fn visit_box ( & mut self , place : & MPlaceTy < ' tcx , Tag > ) -> InterpResult < ' tcx > {
1041+ // Boxes do not get a protector: protectors reflect that references outlive the call
1042+ // they were passed in to; that's just not the case for boxes.
1043+ let ( ref_kind, protector) = ( RefKind :: Unique { two_phase : false } , false ) ;
1044+
1045+ let val = self . ecx . read_immediate ( & place. into ( ) ) ?;
1046+ let val = self . ecx . retag_reference ( & val, ref_kind, protector) ?;
1047+ self . ecx . write_immediate ( * val, & place. into ( ) ) ?;
1048+ Ok ( ( ) )
1049+ }
1050+
10371051 fn visit_value ( & mut self , place : & MPlaceTy < ' tcx , Tag > ) -> InterpResult < ' tcx > {
1038- if let Some ( ( mutbl , protector) ) = qualify ( place. layout . ty , self . kind ) {
1052+ if let Some ( ( ref_kind , protector) ) = qualify ( place. layout . ty , self . kind ) {
10391053 let val = self . ecx . read_immediate ( & place. into ( ) ) ?;
1040- let val = self . ecx . retag_reference ( & val, mutbl , protector) ?;
1054+ let val = self . ecx . retag_reference ( & val, ref_kind , protector) ?;
10411055 self . ecx . write_immediate ( * val, & place. into ( ) ) ?;
10421056 } else if matches ! ( place. layout. ty. kind( ) , ty:: RawPtr ( ..) ) {
10431057 // Wide raw pointers *do* have fields and their types are strange.
0 commit comments