@@ -312,8 +312,6 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
312
312
}
313
313
314
314
let span = this. machine . current_span ( ) ;
315
- let alloc_extra = this. get_alloc_extra ( alloc_id) ?;
316
- let mut tree_borrows = alloc_extra. borrow_tracker_tb ( ) . borrow_mut ( ) ;
317
315
318
316
// Store initial permissions and their corresponding range.
319
317
let mut perms_map: RangeMap < LocationState > = RangeMap :: new (
@@ -342,36 +340,83 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
342
340
assert ! ( new_perm. freeze_access) ;
343
341
344
342
let protected = new_perm. protector . is_some ( ) ;
345
- this. visit_freeze_sensitive ( place, ptr_size, |range, frozen| {
346
- has_unsafe_cell = has_unsafe_cell || !frozen;
347
-
348
- // We are only ever `Frozen` inside the frozen bits.
349
- let ( perm, access) = if frozen {
343
+ let precise_interior_mut = this
344
+ . machine
345
+ . borrow_tracker
346
+ . as_mut ( )
347
+ . unwrap ( )
348
+ . get_mut ( )
349
+ . borrow_tracker_method
350
+ . get_tree_borrows_params ( )
351
+ . precise_interior_mut ;
352
+
353
+ let default_perm = if !precise_interior_mut {
354
+ // NOTE: Using `ty_is_freeze` doesn't give the same result as going through the range
355
+ // and computing `has_unsafe_cell`. This is because of zero-sized `UnsafeCell`, for which
356
+ // `has_unsafe_cell` is false, but `!ty_is_freeze` is true.
357
+ let ty_is_freeze = place. layout . ty . is_freeze ( * this. tcx , this. typing_env ( ) ) ;
358
+ let ( perm, access) = if ty_is_freeze {
350
359
( new_perm. freeze_perm , new_perm. freeze_access )
351
360
} else {
352
361
( new_perm. nonfreeze_perm , new_perm. nonfreeze_access )
353
362
} ;
363
+ let sifa = perm. strongest_idempotent_foreign_access ( protected) ;
364
+ let new_loc = if access {
365
+ LocationState :: new_accessed ( perm, sifa)
366
+ } else {
367
+ LocationState :: new_non_accessed ( perm, sifa)
368
+ } ;
369
+
370
+ for ( _loc_range, loc) in perms_map. iter_mut_all ( ) {
371
+ * loc = new_loc;
372
+ }
373
+
374
+ perm
375
+ } else {
376
+ this. visit_freeze_sensitive ( place, ptr_size, |range, frozen| {
377
+ has_unsafe_cell = has_unsafe_cell || !frozen;
354
378
355
- // Store initial permissions.
356
- for ( _loc_range, loc) in perms_map. iter_mut ( range. start , range. size ) {
379
+ // We are only ever `Frozen` inside the frozen bits.
380
+ let ( perm, access) = if frozen {
381
+ ( new_perm. freeze_perm , new_perm. freeze_access )
382
+ } else {
383
+ ( new_perm. nonfreeze_perm , new_perm. nonfreeze_access )
384
+ } ;
357
385
let sifa = perm. strongest_idempotent_foreign_access ( protected) ;
358
386
// NOTE: Currently, `access` is false if and only if `perm` is Cell, so this `if`
359
387
// doesn't not change whether any code is UB or not. We could just always use
360
388
// `new_accessed` and everything would stay the same. But that seems conceptually
361
389
// odd, so we keep the initial "accessed" bit of the `LocationState` in sync with whether
362
390
// a read access is performed below.
363
- if access {
364
- * loc = LocationState :: new_accessed ( perm, sifa) ;
391
+ let new_loc = if access {
392
+ LocationState :: new_accessed ( perm, sifa)
365
393
} else {
366
- * loc = LocationState :: new_non_accessed ( perm, sifa) ;
394
+ LocationState :: new_non_accessed ( perm, sifa)
395
+ } ;
396
+
397
+ // Store initial permissions.
398
+ for ( _loc_range, loc) in perms_map. iter_mut ( range. start , range. size ) {
399
+ * loc = new_loc;
367
400
}
368
- }
369
401
370
- // Some reborrows incur a read access to the parent.
371
- if access {
402
+ interp_ok ( ( ) )
403
+ } ) ?;
404
+
405
+ // Allow lazily writing to surrounding data if we found an `UnsafeCell`.
406
+ if has_unsafe_cell { new_perm. nonfreeze_perm } else { new_perm. freeze_perm }
407
+ } ;
408
+
409
+ let alloc_extra = this. get_alloc_extra ( alloc_id) ?;
410
+ let mut tree_borrows = alloc_extra. borrow_tracker_tb ( ) . borrow_mut ( ) ;
411
+
412
+ for ( perm_range, perm) in perms_map. iter_mut_all ( ) {
413
+ if perm. is_accessed ( ) {
414
+ // Some reborrows incur a read access to the parent.
372
415
// Adjust range to be relative to allocation start (rather than to `place`).
373
- let mut range_in_alloc = range;
374
- range_in_alloc. start += base_offset;
416
+ let range_in_alloc = AllocRange {
417
+ start : Size :: from_bytes ( perm_range. start ) + base_offset,
418
+ size : Size :: from_bytes ( perm_range. end - perm_range. start ) ,
419
+ } ;
375
420
376
421
tree_borrows. perform_access (
377
422
orig_tag,
@@ -382,7 +427,7 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
382
427
) ?;
383
428
384
429
// Also inform the data race model (but only if any bytes are actually affected).
385
- if range . size . bytes ( ) > 0 {
430
+ if range_in_alloc . size . bytes ( ) > 0 {
386
431
if let Some ( data_race) = alloc_extra. data_race . as_vclocks_ref ( ) {
387
432
data_race. read (
388
433
alloc_id,
@@ -394,17 +439,15 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
394
439
}
395
440
}
396
441
}
397
- interp_ok ( ( ) )
398
- } ) ?;
442
+ }
399
443
400
444
// Record the parent-child pair in the tree.
401
445
tree_borrows. new_child (
402
446
base_offset,
403
447
orig_tag,
404
448
new_tag,
405
449
perms_map,
406
- // Allow lazily writing to surrounding data if we found an `UnsafeCell`.
407
- if has_unsafe_cell { new_perm. nonfreeze_perm } else { new_perm. freeze_perm } ,
450
+ default_perm,
408
451
protected,
409
452
span,
410
453
) ?;
0 commit comments