@@ -65,7 +65,7 @@ pub struct FrameExtra {
65
65
/// incremental updates of the global list of protected tags stored in the
66
66
/// `stacked_borrows::GlobalState` upon function return, and if we attempt to pop a protected
67
67
/// tag, to identify which call is responsible for protecting the tag.
68
- /// See `Stack::item_popped ` for more explanation.
68
+ /// See `Stack::item_invalidated ` for more explanation.
69
69
///
70
70
/// This will contain one tag per reference passed to the function, so
71
71
/// a size of 2 is enough for the vast majority of functions.
@@ -126,7 +126,7 @@ pub struct GlobalStateInner {
126
126
/// An item is protected if its tag is in this set, *and* it has the "protected" bit set.
127
127
/// We add tags to this when they are created with a protector in `reborrow`, and
128
128
/// we remove tags from this when the call which is protecting them returns, in
129
- /// `GlobalStateInner::end_call`. See `Stack::item_popped ` for more details.
129
+ /// `GlobalStateInner::end_call`. See `Stack::item_invalidated ` for more details.
130
130
protected_tags : FxHashMap < SbTag , ProtectorKind > ,
131
131
/// The pointer ids to trace
132
132
tracked_pointer_tags : FxHashSet < SbTag > ,
@@ -292,6 +292,13 @@ impl Permission {
292
292
}
293
293
}
294
294
295
+ /// Determines whether an item was invalidated by a conflicting access, or by deallocation.
296
+ #[ derive( Copy , Clone , Debug ) ]
297
+ enum ItemInvalidationCause {
298
+ Conflict ,
299
+ Dealloc ,
300
+ }
301
+
295
302
/// Core per-location operations: access, dealloc, reborrow.
296
303
impl < ' tcx > Stack {
297
304
/// Find the first write-incompatible item above the given one --
@@ -330,11 +337,11 @@ impl<'tcx> Stack {
330
337
/// Within `provoking_access, the `AllocRange` refers the entire operation, and
331
338
/// the `Size` refers to the specific location in the `AllocRange` that we are
332
339
/// currently checking.
333
- fn item_popped (
340
+ fn item_invalidated (
334
341
item : & Item ,
335
342
global : & GlobalStateInner ,
336
343
dcx : & mut DiagnosticCx < ' _ , ' _ , ' _ , ' _ , ' tcx > ,
337
- deallocation : bool ,
344
+ cause : ItemInvalidationCause ,
338
345
) -> InterpResult < ' tcx > {
339
346
if !global. tracked_pointer_tags . is_empty ( ) {
340
347
dcx. check_tracked_tag_popped ( item, global) ;
@@ -358,7 +365,10 @@ impl<'tcx> Stack {
358
365
// which ends up about linear in the number of protected tags in the program into a
359
366
// constant time check (and a slow linear, because the tags in the frames aren't contiguous).
360
367
if let Some ( & protector_kind) = global. protected_tags . get ( & item. tag ( ) ) {
361
- let allowed = deallocation && matches ! ( protector_kind, ProtectorKind :: WeakProtector ) ;
368
+ // The only way this is okay is if the protector is weak and we are deallocating with
369
+ // the right pointer.
370
+ let allowed = matches ! ( cause, ItemInvalidationCause :: Dealloc )
371
+ && matches ! ( protector_kind, ProtectorKind :: WeakProtector ) ;
362
372
if !allowed {
363
373
return Err ( dcx. protector_error ( item, protector_kind) . into ( ) ) ;
364
374
}
@@ -401,7 +411,7 @@ impl<'tcx> Stack {
401
411
0
402
412
} ;
403
413
self . pop_items_after ( first_incompatible_idx, |item| {
404
- Stack :: item_popped ( & item, global, dcx, /* deallocation */ false ) ?;
414
+ Stack :: item_invalidated ( & item, global, dcx, ItemInvalidationCause :: Conflict ) ?;
405
415
dcx. log_invalidation ( item. tag ( ) ) ;
406
416
Ok ( ( ) )
407
417
} ) ?;
@@ -422,7 +432,7 @@ impl<'tcx> Stack {
422
432
0
423
433
} ;
424
434
self . disable_uniques_starting_at ( first_incompatible_idx, |item| {
425
- Stack :: item_popped ( & item, global, dcx, /* deallocation */ false ) ?;
435
+ Stack :: item_invalidated ( & item, global, dcx, ItemInvalidationCause :: Conflict ) ?;
426
436
dcx. log_invalidation ( item. tag ( ) ) ;
427
437
Ok ( ( ) )
428
438
} ) ?;
@@ -472,7 +482,7 @@ impl<'tcx> Stack {
472
482
// Step 2: Pretend we remove the remaining items, checking if any are strongly protected.
473
483
for idx in ( 0 ..self . len ( ) ) . rev ( ) {
474
484
let item = self . get ( idx) . unwrap ( ) ;
475
- Stack :: item_popped ( & item, global, dcx, /* deallocation */ true ) ?;
485
+ Stack :: item_invalidated ( & item, global, dcx, ItemInvalidationCause :: Dealloc ) ?;
476
486
}
477
487
478
488
Ok ( ( ) )
@@ -847,7 +857,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
847
857
) ;
848
858
849
859
if let Some ( protect) = protect {
850
- // See comment in `Stack::item_popped ` for why we store the tag twice.
860
+ // See comment in `Stack::item_invalidated ` for why we store the tag twice.
851
861
this. frame_mut ( ) . extra . stacked_borrows . as_mut ( ) . unwrap ( ) . protected_tags . push ( new_tag) ;
852
862
this. machine
853
863
. stacked_borrows
0 commit comments