pub use stack::Stack;
pub mod diagnostics;
-pub type AllocExtra = Stacks;
+pub type AllocState = Stacks;
/// Extra per-allocation state.
#[derive(Clone, Debug)]
/// new pointer.
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
enum RefKind {
- /// `&mut` and `Box`.
+ /// `Box`.
+ Box,
+ /// `&mut`.
Unique { two_phase: bool },
/// `&` with or without interior mutability.
Shared,
impl fmt::Display for RefKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
+ RefKind::Box => write!(f, "Box"),
RefKind::Unique { two_phase: false } => write!(f, "unique reference"),
RefKind::Unique { two_phase: true } => write!(f, "unique reference (two-phase)"),
RefKind::Shared => write!(f, "shared reference"),
})?;
Ok(())
}
-
- fn expose_tag(&mut self, tag: BorTag) {
- self.exposed_tags.insert(tag);
- }
}
/// Retagging/reborrowing. There is some policy in here, such as which permissions
// uncovers a non-supported `extern static`.
let extra = this.get_alloc_extra(alloc_id)?;
let mut stacked_borrows = extra
- .borrow_tracker
- .as_ref()
- .expect("We should have borrow tracking data")
- .assert_sb()
+ .borrow_tracker_sb()
.borrow_mut();
// Note that we create a *second* `DiagnosticCxBuilder` below for the actual retag.
// FIXME: can this be done cleaner?
let (perm, access) = match kind {
RefKind::Unique { two_phase } => {
// Permission is Unique only if the type is `Unpin` and this is not twophase
- let perm = if !two_phase && place.layout.ty.is_unpin(*this.tcx, this.param_env()) {
- Permission::Unique
+ if !two_phase && place.layout.ty.is_unpin(*this.tcx, this.param_env()) {
+ (Permission::Unique, Some(AccessKind::Write))
} else {
- Permission::SharedReadWrite
- };
- // We do an access for all full borrows, even if `!Unpin`.
- let access = if !two_phase { Some(AccessKind::Write) } else { None };
- (perm, access)
+ // FIXME: We emit `dereferenceable` for `!Unpin` mutable references, so we
+ // should do fake accesses here. But then we run into
+ // <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>, so for now
+ // we don't do that.
+ (Permission::SharedReadWrite, None)
+ }
}
+ RefKind::Box => (Permission::Unique, Some(AccessKind::Write)),
RefKind::Raw { mutable: true } => {
// Creating a raw ptr does not count as an access
(Permission::SharedReadWrite, None)
// We have to use shared references to alloc/memory_extra here since
// `visit_freeze_sensitive` needs to access the global state.
let alloc_extra = this.get_alloc_extra(alloc_id)?;
- let mut stacked_borrows = alloc_extra
- .borrow_tracker
- .as_ref()
- .expect("We should have borrow tracking data")
- .assert_sb()
- .borrow_mut();
+ let mut stacked_borrows = alloc_extra.borrow_tracker_sb().borrow_mut();
this.visit_freeze_sensitive(place, size, |mut range, frozen| {
// Adjust range.
range.start += base_offset;
// Note that this asserts that the allocation is mutable -- but since we are creating a
// mutable pointer, that seems reasonable.
let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc_id)?;
- let stacked_borrows = alloc_extra
- .borrow_tracker
- .as_mut()
- .expect("We should have borrow tracking data")
- .assert_sb_mut()
- .get_mut();
+ let stacked_borrows = alloc_extra.borrow_tracker_sb_mut().get_mut();
let item = Item::new(new_tag, perm, protect.is_some());
let range = alloc_range(base_offset, size);
let global = machine.borrow_tracker.as_ref().unwrap().borrow();
// Boxes get a weak protectors, since they may be deallocated.
self.retag_place(
place,
- RefKind::Unique { two_phase: false },
+ RefKind::Box,
self.retag_cause,
/*protector*/
(self.kind == RetagKind::FnEntry).then_some(ProtectorKind::WeakProtector),
// uncovers a non-supported `extern static`.
let alloc_extra = this.get_alloc_extra(alloc_id)?;
trace!("Stacked Borrows tag {tag:?} exposed in {alloc_id:?}");
- alloc_extra
- .borrow_tracker
- .as_ref()
- .expect("We should have borrow tracking data")
- .assert_sb()
- .borrow_mut()
- .expose_tag(tag);
+ alloc_extra.borrow_tracker_sb().borrow_mut().exposed_tags.insert(tag);
}
AllocKind::Function | AllocKind::VTable | AllocKind::Dead => {
// No stacked borrows on these allocations.
fn print_stacks(&mut self, alloc_id: AllocId) -> InterpResult<'tcx> {
let this = self.eval_context_mut();
let alloc_extra = this.get_alloc_extra(alloc_id)?;
- let stacks = alloc_extra
- .borrow_tracker
- .as_ref()
- .expect("We should have borrow tracking data")
- .assert_sb()
- .borrow();
+ let stacks = alloc_extra.borrow_tracker_sb().borrow();
for (range, stack) in stacks.stacks.iter_all() {
print!("{range:?}: [");
if let Some(bottom) = stack.unknown_bottom() {