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