Skip to content

Commit 9f984ca

Browse files
committed
Print more in SB error diagnostics
This tries to clarify exactly why an access is not valid by printing what memory range the access was over, which in combination with tag-tracking may help a user figure out the source of the problem.
1 parent 538aedf commit 9f984ca

File tree

1 file changed

+56
-18
lines changed

1 file changed

+56
-18
lines changed

src/stacked_borrows.rs

Lines changed: 56 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -338,16 +338,20 @@ impl<'tcx> Stack {
338338
&mut self,
339339
access: AccessKind,
340340
tag: SbTag,
341-
dbg_ptr: Pointer<AllocId>, // just for debug printing amd error messages
341+
(alloc_id, range): (AllocId, AllocRange), // just for debug printing amd error messages
342342
global: &GlobalState,
343343
) -> InterpResult<'tcx> {
344344
// Two main steps: Find granting item, remove incompatible items above.
345345

346346
// Step 1: Find granting item.
347347
let granting_idx = self.find_granting(access, tag).ok_or_else(|| {
348348
err_sb_ub(format!(
349-
"no item granting {} to tag {:?} at {:?} found in borrow stack.",
350-
access, tag, dbg_ptr,
349+
"no item granting {} to tag {:?} over {}[{:#x}..{:#x}] found in borrow stack.",
350+
access,
351+
tag,
352+
alloc_id,
353+
range.start.bytes(),
354+
range.end().bytes(),
351355
))
352356
})?;
353357

@@ -416,19 +420,17 @@ impl<'tcx> Stack {
416420
&mut self,
417421
derived_from: SbTag,
418422
new: Item,
419-
dbg_ptr: Pointer<AllocId>,
423+
(alloc_id, alloc_range): (AllocId, AllocRange),
420424
global: &GlobalState,
421425
) -> InterpResult<'tcx> {
422426
// Figure out which access `perm` corresponds to.
423427
let access =
424428
if new.perm.grants(AccessKind::Write) { AccessKind::Write } else { AccessKind::Read };
425429
// Now we figure out which item grants our parent (`derived_from`) this kind of access.
426430
// We use that to determine where to put the new item.
427-
let granting_idx = self.find_granting(access, derived_from)
428-
.ok_or_else(|| err_sb_ub(format!(
429-
"trying to reborrow for {:?} at {:?}, but parent tag {:?} does not have an appropriate item in the borrow stack",
430-
new.perm, dbg_ptr, derived_from,
431-
)))?;
431+
let granting_idx = self
432+
.find_granting(access, derived_from)
433+
.ok_or_else(|| self.grant_error(derived_from, new, alloc_id, alloc_range))?;
432434

433435
// Compute where to put the new item.
434436
// Either way, we ensure that we insert the new item in a way such that between
@@ -447,7 +449,7 @@ impl<'tcx> Stack {
447449
// A "safe" reborrow for a pointer that actually expects some aliasing guarantees.
448450
// Here, creating a reference actually counts as an access.
449451
// This ensures F2b for `Unique`, by removing offending `SharedReadOnly`.
450-
self.access(access, derived_from, dbg_ptr, global)?;
452+
self.access(access, derived_from, (alloc_id, alloc_range), global)?;
451453

452454
// We insert "as far up as possible": We know only compatible items are remaining
453455
// on top of `derived_from`, and we want the new item at the top so that we
@@ -467,6 +469,41 @@ impl<'tcx> Stack {
467469

468470
Ok(())
469471
}
472+
473+
/// Report a descriptive error when `new` could not be granted from `derived_from`.
474+
fn grant_error(
475+
&self,
476+
derived_from: SbTag,
477+
new: Item,
478+
alloc_id: AllocId,
479+
alloc_range: AllocRange,
480+
) -> InterpError<'static> {
481+
let action = format!(
482+
"trying to reborrow for {:?} over {:?}[{:#x}..{:#x}]",
483+
new.perm,
484+
alloc_id,
485+
alloc_range.start.bytes(),
486+
alloc_range.end().bytes()
487+
);
488+
if derived_from == SbTag::Untagged {
489+
err_sb_ub(format!(
490+
"{}, but parent tag {:?} does not grant the required permission over memory range",
491+
action, derived_from
492+
))
493+
} else {
494+
if let Some(parent) = self.borrows.iter().rev().find(|item| derived_from == item.tag) {
495+
err_sb_ub(format!(
496+
"{}, but parent tag {:?} grants insufficient permission: {:?}",
497+
action, derived_from, parent.perm
498+
))
499+
} else {
500+
err_sb_ub(format!(
501+
"{}, but parent tag {:?} does not exist in the borrow stack for this memory range",
502+
action, derived_from
503+
))
504+
}
505+
}
506+
}
470507
}
471508
// # Stacked Borrows Core End
472509

@@ -565,8 +602,8 @@ impl Stacks {
565602
range.size.bytes()
566603
);
567604
let global = &*extra.borrow();
568-
self.for_each(range, move |offset, stack| {
569-
stack.access(AccessKind::Read, tag, Pointer::new(alloc_id, offset), global)
605+
self.for_each(range, move |_offset, stack| {
606+
stack.access(AccessKind::Read, tag, (alloc_id, range), global)
570607
})
571608
}
572609

@@ -585,8 +622,8 @@ impl Stacks {
585622
range.size.bytes()
586623
);
587624
let global = extra.get_mut();
588-
self.for_each_mut(range, move |offset, stack| {
589-
stack.access(AccessKind::Write, tag, Pointer::new(alloc_id, offset), global)
625+
self.for_each_mut(range, move |_offset, stack| {
626+
stack.access(AccessKind::Write, tag, (alloc_id, range), global)
590627
})
591628
}
592629

@@ -692,8 +729,8 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
692729
Permission::SharedReadWrite
693730
};
694731
let item = Item { perm, tag: new_tag, protector };
695-
stacked_borrows.for_each(range, |offset, stack| {
696-
stack.grant(orig_tag, item, Pointer::new(alloc_id, offset), &*global)
732+
stacked_borrows.for_each(range, |_offset, stack| {
733+
stack.grant(orig_tag, item, (alloc_id, range), &*global)
697734
})
698735
})?;
699736
return Ok(());
@@ -707,8 +744,9 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
707744
alloc_extra.stacked_borrows.as_mut().expect("we should have Stacked Borrows data");
708745
let global = memory_extra.stacked_borrows.as_mut().unwrap().get_mut();
709746
let item = Item { perm, tag: new_tag, protector };
710-
stacked_borrows.for_each_mut(alloc_range(base_offset, size), |offset, stack| {
711-
stack.grant(orig_tag, item, Pointer::new(alloc_id, offset), global)
747+
let range = alloc_range(base_offset, size);
748+
stacked_borrows.for_each_mut(alloc_range(base_offset, size), |_offset, stack| {
749+
stack.grant(orig_tag, item, (alloc_id, range), global)
712750
})?;
713751
Ok(())
714752
}

0 commit comments

Comments
 (0)