Skip to content
Open
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
6026a86
disable tree-borrows strict provenance requirement
royAmmerschuber Oct 13, 2025
9bbea12
respect idempotent foreign access optimization
royAmmerschuber Oct 19, 2025
ee5cdc0
fix formatting
royAmmerschuber Oct 19, 2025
94d48d3
properly handle conflicted protected tags
royAmmerschuber Oct 26, 2025
dc9034e
smaller changes
royAmmerschuber Oct 26, 2025
ff3cd3c
improve comments
royAmmerschuber Oct 26, 2025
2e94e3a
fix verify_consistency
royAmmerschuber Oct 27, 2025
4e6b57a
fix formatting & improve error messages
royAmmerschuber Oct 27, 2025
52d4c1f
make update_exposure clearer & fix some bugs
royAmmerschuber Oct 28, 2025
7a59d7a
add `exposed_as` field to WildcardAccessTracking
royAmmerschuber Oct 28, 2025
a63d86f
run fmt/clippy & rename child_access to local_access and pointer/refe…
royAmmerschuber Oct 28, 2025
c21dea8
stop garbage collecting exposed tags through which an access could ha…
royAmmerschuber Oct 29, 2025
1e50350
formatting...
royAmmerschuber Oct 29, 2025
822f2c6
rename `Location`, `WildcardAccessTracking` an `rperms`
royAmmerschuber Oct 29, 2025
1c7b3c1
visitor takes LocationTree instead of individual maps
royAmmerschuber Nov 2, 2025
5dd98dc
repair build, changes based on review
royAmmerschuber Nov 2, 2025
eb9979e
bless tests
royAmmerschuber Nov 2, 2025
45877a4
simplify tree traversals & small changes from review
royAmmerschuber Nov 5, 2025
15d0a0c
revert reborrow changes
royAmmerschuber Nov 5, 2025
c460728
clippy & fmt
royAmmerschuber Nov 5, 2025
ed28cdb
try_into instead of as
royAmmerschuber Nov 5, 2025
dceb60a
reorganize tests
royAmmerschuber Nov 7, 2025
f0d8e2c
fix conditional compiler warnings
royAmmerschuber Nov 7, 2025
2d4207b
correct comments
royAmmerschuber Nov 7, 2025
b5b8291
add test for `strongest_allowed_child_access`
royAmmerschuber Nov 7, 2025
9dc5770
factor out transition & assert on no_exposed_references
royAmmerschuber Nov 10, 2025
903d4e6
improve comments
royAmmerschuber Nov 11, 2025
a918b00
doc comment
royAmmerschuber Nov 11, 2025
b5fbb37
test comments formatting changes
royAmmerschuber Nov 11, 2025
c1b3bf4
add strongly protected test
royAmmerschuber Nov 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 77 additions & 71 deletions src/borrow_tracker/tree_borrows/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_span::Span;
use smallvec::SmallVec;

use super::diagnostics::AccessCause;
use super::wildcard::WildcardState;
use crate::borrow_tracker::tree_borrows::Permission;
use crate::borrow_tracker::tree_borrows::diagnostics::{
Expand Down Expand Up @@ -82,6 +83,47 @@ impl LocationState {
self.permission
}

fn perform_transition(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a doc comment to this function.

&mut self,
idx: UniIndex,
nodes: &mut UniValMap<Node>,
wildcard_accesses: &mut UniValMap<WildcardState>,
access_kind: AccessKind,
access_cause: AccessCause,
access_range: Option<AllocRange>,
relatedness: AccessRelatedness,
span: Span,
location_range: Range<u64>,
protected: bool,
) -> Result<(), TransitionError> {
// Call this function now (i.e. only if we know `relatedness`), which
// ensures it is only called when `skip_if_known_noop` returns
// `Recurse`, due to the contract of `traverse_this_parents_children_other`.
self.record_new_access(access_kind, relatedness);

let transition = self.perform_access(access_kind, relatedness, protected)?;
if !transition.is_noop() {
let node = nodes.get_mut(idx).unwrap();
// Record the event as part of the history.
node.debug_info.history.push(diagnostics::Event {
transition,
is_foreign: relatedness.is_foreign(),
access_cause,
access_range,
transition_range: location_range,
span,
});

// We need to update the wildcard state, if the permission
// of an exposed pointer changes.
if node.is_exposed {
let access_type = self.permission.strongest_allowed_child_access(protected);
WildcardState::update_exposure(idx, access_type, nodes, wildcard_accesses);
}
}
Ok(())
}

/// Apply the effect of an access to one location, including
/// - applying `Permission::perform_access` to the inner `Permission`,
/// - emitting protector UB if the location is accessed,
Expand Down Expand Up @@ -870,37 +912,20 @@ impl<'tcx> Tree {
let mut perm = args.loc.perms.entry(args.idx);

let state = perm.or_insert(node.default_location_state());
// Call this function now, which ensures it is only called when
// `skip_if_known_noop` returns `Recurse`, due to the contract of
// `traverse_this_parents_children_other`.
state.record_new_access(access_kind, args.rel_pos);

let protected = global.borrow().protected_tags.contains_key(&node.tag);
let transition = state.perform_access(access_kind, args.rel_pos, protected)?;
// Record the event as part of the history
if !transition.is_noop() {
node.debug_info.history.push(diagnostics::Event {
transition,
is_foreign: args.rel_pos.is_foreign(),
access_cause,
access_range: access_range_and_kind.map(|x| x.0),
transition_range: perms_range,
span,
});

// We need to update the wildcard access tracking information,
// if the permission of an exposed pointer changes
if node.is_exposed {
let access_type = state.permission.strongest_allowed_child_access(protected);
WildcardState::update_exposure(
args.idx,
access_type,
args.nodes,
&mut args.loc.wildcard_accesses,
);
}
}
Ok(())
state.perform_transition(
args.idx,
args.nodes,
&mut args.loc.wildcard_accesses,
access_kind,
access_cause,
/* access_range */ access_range_and_kind.map(|x| x.0),
args.rel_pos,
span,
perms_range,
protected,
)
};

// Error handler in case `node_app` goes wrong.
Expand Down Expand Up @@ -1180,6 +1205,7 @@ impl<'tcx> Tree {
// There doesn't exist a valid exposed reference for this access to
// happen through.
// If this fails for one id, then it fails for all ids.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that mean we always trigger this on the root? Can we assert here that the current node is the root?

assert_eq!(self.root, args.idx);
return Err(no_valid_exposed_references_error(
alloc_id,
loc_range.start,
Expand All @@ -1192,50 +1218,30 @@ impl<'tcx> Tree {
// to this node, but we still update each of its children.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// to this node, but we still update each of its children.
// to this node, but we still update each of its children.
// This is an imprecision! In the future, maybe we can still do some sort
// of best-effort update here.

return Ok(());
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
};
};
// We know the exact relatedness, so we can actually do precise checks.


// Call this function now (i.e. only if we know `relatedness`), which
// ensures it is only called when `skip_if_known_noop` returns
// `Recurse`, due to the contract of `traverse_this_parents_children_other`.
perm.record_new_access(access_kind, relatedness);

let transition = perm
.perform_access(access_kind, relatedness, protected)
.map_err(|trans| {
TbError {
conflicting_info: &node.debug_info,
access_cause,
alloc_id,
error_offset: loc_range.start,
error_kind: trans,
accessed_info: None,
}
.build()
})?;
if !transition.is_noop() {
// Record the event as part of the history.
node.debug_info.history.push(diagnostics::Event {
transition,
is_foreign: relatedness.is_foreign(),
perm.perform_transition(
args.idx,
args.nodes,
&mut args.loc.wildcard_accesses,
access_kind,
access_cause,
Some(access_range),
relatedness,
span,
loc_range.clone(),
protected,
)
.map_err(|trans| {
let node = args.nodes.get(args.idx).unwrap();
TbError {
conflicting_info: &node.debug_info,
access_cause,
access_range: access_range_and_kind.map(|x| x.0),
transition_range: loc_range.clone(),
span,
});

// We need to update the wildcard state, if the permission
// of an exposed pointer changes.
if node.is_exposed {
let access_type =
perm.permission.strongest_allowed_child_access(protected);
WildcardState::update_exposure(
args.idx,
access_type,
args.nodes,
&mut args.loc.wildcard_accesses,
);
alloc_id,
error_offset: loc_range.start,
error_kind: trans,
accessed_info: None,
}
}
Ok(())
.build()
})
},
|err| err.error_kind,
)?;
Expand Down