@@ -3,7 +3,6 @@ use rustc_middle::mir::{Mutability, RetagKind};
3
3
use rustc_middle:: ty:: layout:: HasTypingEnv ;
4
4
use rustc_middle:: ty:: { self , Ty } ;
5
5
6
- use self :: tree:: LocationState ;
7
6
use crate :: borrow_tracker:: { GlobalState , GlobalStateInner , ProtectorKind } ;
8
7
use crate :: concurrency:: data_race:: NaReadType ;
9
8
use crate :: * ;
@@ -218,6 +217,15 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
218
217
) -> InterpResult < ' tcx , Option < Provenance > > {
219
218
// Make sure the new permissions make sense as the initial permissions of a fresh tag.
220
219
assert ! ( new_perm. freeze_perm. is_initial( ) && new_perm. nonfreeze_perm. is_initial( ) ) ;
220
+ // SIFA of the frozen part must be weaker than SIFA of the non-frozen part, otherwise
221
+ // `self.update_last_accessed_after_retag` will break the SIFA invariant (see `foreign_access_skipping.rs`).
222
+ assert ! (
223
+ new_perm. freeze_perm. strongest_idempotent_foreign_access( new_perm. protector. is_some( ) )
224
+ <= new_perm
225
+ . nonfreeze_perm
226
+ . strongest_idempotent_foreign_access( new_perm. protector. is_some( ) )
227
+ ) ;
228
+
221
229
let this = self . eval_context_mut ( ) ;
222
230
// Ensure we bail out if the pointer goes out-of-bounds (see miri#1050).
223
231
this. check_ptr_access ( place. ptr ( ) , ptr_size, CheckInAllocMsg :: Dereferenceable ) ?;
@@ -315,76 +323,72 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
315
323
let span = this. machine . current_span ( ) ;
316
324
let alloc_extra = this. get_alloc_extra ( alloc_id) ?;
317
325
let mut tree_borrows = alloc_extra. borrow_tracker_tb ( ) . borrow_mut ( ) ;
318
- let prot = new_perm. protector . is_some ( ) ;
319
326
320
327
// Store initial permissions and their corresponding range.
321
- let mut perms_map: RangeMap < LocationState > = RangeMap :: new (
328
+ let mut perms_map: RangeMap < Permission > = RangeMap :: new (
322
329
ptr_size,
323
- LocationState :: new_uninit (
324
- Permission :: new_disabled ( ) ,
325
- foreign_access_skipping:: IdempotentForeignAccess :: None ,
326
- ) ,
330
+ Permission :: new_disabled ( ) , // this will be overwritten
327
331
) ;
328
332
// Keep track of whether the node has any part that allows for interior mutability.
333
+ // FIXME: This misses `PhantomData<UnsafeCell<T>>` which could be considered a marker
334
+ // for requesting interior mutability.
329
335
let mut has_unsafe_cell = false ;
330
336
331
337
this. visit_freeze_sensitive ( place, ptr_size, |range, frozen| {
332
338
has_unsafe_cell = has_unsafe_cell || !frozen;
333
339
334
- // Adjust range.
335
- let mut range_with_offset = range;
336
- range_with_offset. start += base_offset;
337
-
338
340
// We are only ever `Frozen` inside the frozen bits.
339
- let ( perm , access) = if frozen {
341
+ let ( perm_init , access) = if frozen {
340
342
( new_perm. freeze_perm , new_perm. freeze_access )
341
343
} else {
342
344
( new_perm. nonfreeze_perm , new_perm. nonfreeze_access )
343
345
} ;
344
- let strongest_idempotent = perm. strongest_idempotent_foreign_access ( prot) ;
345
346
346
347
// Store initial permissions.
347
- let perm_init = LocationState :: new_init ( perm, strongest_idempotent) ;
348
348
for ( _perm_range, perm) in perms_map. iter_mut ( range. start , range. size ) {
349
349
* perm = perm_init;
350
350
}
351
351
352
352
// Some reborrows incur a read access to the parent.
353
353
if access {
354
+ // Adjust range to be relative to allocation start (rather than to `place`).
355
+ let mut range_in_alloc = range;
356
+ range_in_alloc. start += base_offset;
357
+
354
358
tree_borrows. perform_access (
355
359
orig_tag,
356
- Some ( ( range_with_offset , AccessKind :: Read , diagnostics:: AccessCause :: Reborrow ) ) ,
360
+ Some ( ( range_in_alloc , AccessKind :: Read , diagnostics:: AccessCause :: Reborrow ) ) ,
357
361
this. machine . borrow_tracker . as_ref ( ) . unwrap ( ) ,
358
362
alloc_id,
359
363
this. machine . current_span ( ) ,
360
- ) ?
361
- }
362
-
363
- // Also inform the data race model (but only if any bytes are actually affected).
364
- if range . size . bytes ( ) > 0 && access {
365
- if let Some ( data_race ) = alloc_extra . data_race . as_vclocks_ref ( ) {
366
- data_race . read (
367
- alloc_id ,
368
- range_with_offset ,
369
- NaReadType :: Retag ,
370
- Some ( place . layout . ty ) ,
371
- & this . machine ,
372
- ) ?
364
+ ) ?;
365
+
366
+ // Also inform the data race model (but only if any bytes are actually affected).
367
+ if range . size . bytes ( ) > 0 {
368
+ if let Some ( data_race ) = alloc_extra . data_race . as_vclocks_ref ( ) {
369
+ data_race. read (
370
+ alloc_id ,
371
+ range_in_alloc ,
372
+ NaReadType :: Retag ,
373
+ Some ( place . layout . ty ) ,
374
+ & this . machine ,
375
+ ) ?
376
+ }
373
377
}
374
378
}
375
379
interp_ok ( ( ) )
376
380
} ) ?;
377
381
378
382
// Record the parent-child pair in the tree.
379
383
tree_borrows. new_child (
380
- ptr_size,
381
384
base_offset,
382
385
orig_tag,
383
386
new_tag,
384
- new_perm,
385
387
perms_map,
388
+ // Allow lazily writing to surrounding data if we found an `UnsafeCell`.
389
+ if has_unsafe_cell { new_perm. nonfreeze_perm } else { new_perm. freeze_perm } ,
390
+ new_perm. protector . is_some ( ) ,
386
391
span,
387
- has_unsafe_cell,
388
392
) ?;
389
393
drop ( tree_borrows) ;
390
394
0 commit comments