Skip to content

Commit 13be5d9

Browse files
tree borrows: split perform_protector_end_access from perform_access
1 parent 4e1f862 commit 13be5d9

File tree

2 files changed

+71
-58
lines changed

2 files changed

+71
-58
lines changed

src/borrow_tracker/tree_borrows/mod.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ impl<'tcx> Tree {
5959
let span = machine.current_user_relevant_span();
6060
self.perform_access(
6161
prov,
62-
Some((range, access_kind, diagnostics::AccessCause::Explicit(access_kind))),
62+
range,
63+
access_kind,
64+
diagnostics::AccessCause::Explicit(access_kind),
6365
global,
6466
alloc_id,
6567
span,
@@ -93,8 +95,7 @@ impl<'tcx> Tree {
9395
alloc_id: AllocId, // diagnostics
9496
) -> InterpResult<'tcx> {
9597
let span = machine.current_user_relevant_span();
96-
// `None` makes it the magic on-protector-end operation
97-
self.perform_access(ProvenanceExtra::Concrete(tag), None, global, alloc_id, span)?;
98+
self.perform_protector_end_access(tag, global, alloc_id, span)?;
9899

99100
self.update_exposure_for_protector_release(tag);
100101

@@ -343,7 +344,9 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
343344

344345
tree_borrows.perform_access(
345346
parent_prov,
346-
Some((range_in_alloc, AccessKind::Read, diagnostics::AccessCause::Reborrow)),
347+
range_in_alloc,
348+
AccessKind::Read,
349+
diagnostics::AccessCause::Reborrow,
347350
this.machine.borrow_tracker.as_ref().unwrap(),
348351
alloc_id,
349352
this.machine.current_user_relevant_span(),

src/borrow_tracker/tree_borrows/tree.rs

Lines changed: 64 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -828,7 +828,9 @@ impl<'tcx> Tree {
828828
) -> InterpResult<'tcx> {
829829
self.perform_access(
830830
prov,
831-
Some((access_range, AccessKind::Write, diagnostics::AccessCause::Dealloc)),
831+
access_range,
832+
AccessKind::Write,
833+
diagnostics::AccessCause::Dealloc,
832834
global,
833835
alloc_id,
834836
span,
@@ -903,14 +905,6 @@ impl<'tcx> Tree {
903905
/// to each location of the first component of `access_range_and_kind`,
904906
/// on every tag of the allocation.
905907
///
906-
/// If `access_range_and_kind` is `None`, this is interpreted as the special
907-
/// access that is applied on protector release:
908-
/// - the access will be applied only to accessed locations of the allocation,
909-
/// - it will not be visible to children,
910-
/// - it will be recorded as a `FnExit` diagnostic access
911-
/// - and it will be a read except if the location is `Unique`, i.e. has been written to,
912-
/// in which case it will be a write.
913-
///
914908
/// `LocationState::perform_access` will take care of raising transition
915909
/// errors and updating the `accessed` status of each location,
916910
/// this traversal adds to that:
@@ -920,7 +914,9 @@ impl<'tcx> Tree {
920914
pub fn perform_access(
921915
&mut self,
922916
prov: ProvenanceExtra,
923-
access_range_and_kind: Option<(AllocRange, AccessKind, diagnostics::AccessCause)>,
917+
access_range: AllocRange,
918+
access_kind: AccessKind,
919+
access_cause: AccessCause, // diagnostics
924920
global: &GlobalState,
925921
alloc_id: AllocId, // diagnostics
926922
span: Span, // diagnostics
@@ -934,61 +930,75 @@ impl<'tcx> Tree {
934930
ProvenanceExtra::Concrete(tag) => Some(self.tag_mapping.get(&tag).unwrap()),
935931
ProvenanceExtra::Wildcard => None,
936932
};
937-
if let Some((access_range, access_kind, access_cause)) = access_range_and_kind {
938-
// Default branch: this is a "normal" access through a known range.
939-
// We iterate over affected locations and traverse the tree for each of them.
940-
for (loc_range, loc) in self.locations.iter_mut(access_range.start, access_range.size) {
933+
// We iterate over affected locations and traverse the tree for each of them.
934+
for (loc_range, loc) in self.locations.iter_mut(access_range.start, access_range.size) {
935+
loc.perform_access(
936+
self.roots.iter().copied(),
937+
&mut self.nodes,
938+
source_idx,
939+
loc_range,
940+
Some(access_range),
941+
access_kind,
942+
access_cause,
943+
global,
944+
alloc_id,
945+
span,
946+
ChildrenVisitMode::VisitChildrenOfAccessed,
947+
)?;
948+
}
949+
interp_ok(())
950+
}
951+
/// This is the special access that is applied on protector release:
952+
/// - the access will be applied only to accessed locations of the allocation,
953+
/// - it will not be visible to children,
954+
/// - it will be recorded as a `FnExit` diagnostic access
955+
/// - and it will be a read except if the location is `Unique`, i.e. has been written to,
956+
/// in which case it will be a write.
957+
/// - otherwise identical to `Tree::perform_access`
958+
pub fn perform_protector_end_access(
959+
&mut self,
960+
tag: BorTag,
961+
global: &GlobalState,
962+
alloc_id: AllocId, // diagnostics
963+
span: Span, // diagnostics
964+
) -> InterpResult<'tcx> {
965+
#[cfg(feature = "expensive-consistency-checks")]
966+
if self.roots.len() > 1 {
967+
self.verify_wildcard_consistency(global);
968+
}
969+
970+
let source_idx = self.tag_mapping.get(&tag).unwrap();
971+
972+
// This is a special access through the entire allocation.
973+
// It actually only affects `accessed` locations, so we need
974+
// to filter on those before initiating the traversal.
975+
//
976+
// In addition this implicit access should not be visible to children,
977+
// thus the use of `traverse_nonchildren`.
978+
// See the test case `returned_mut_is_usable` from
979+
// `tests/pass/tree_borrows/tree-borrows.rs` for an example of
980+
// why this is important.
981+
for (loc_range, loc) in self.locations.iter_mut_all() {
982+
// Only visit accessed permissions
983+
if let Some(p) = loc.perms.get(source_idx)
984+
&& let Some(access_kind) = p.permission.protector_end_access()
985+
&& p.accessed
986+
{
987+
let access_cause = diagnostics::AccessCause::FnExit(access_kind);
941988
loc.perform_access(
942989
self.roots.iter().copied(),
943990
&mut self.nodes,
944-
source_idx,
991+
Some(source_idx),
945992
loc_range,
946-
Some(access_range),
993+
None,
947994
access_kind,
948995
access_cause,
949996
global,
950997
alloc_id,
951998
span,
952-
ChildrenVisitMode::VisitChildrenOfAccessed,
999+
ChildrenVisitMode::SkipChildrenOfAccessed,
9531000
)?;
9541001
}
955-
} else {
956-
// This is a special access through the entire allocation.
957-
// It actually only affects `accessed` locations, so we need
958-
// to filter on those before initiating the traversal.
959-
//
960-
// In addition this implicit access should not be visible to children,
961-
// thus the use of `traverse_nonchildren`.
962-
// See the test case `returned_mut_is_usable` from
963-
// `tests/pass/tree_borrows/tree-borrows.rs` for an example of
964-
// why this is important.
965-
966-
// Wildcard references are never protected. So this can never be
967-
// called with a wildcard reference.
968-
let source_idx = source_idx.unwrap();
969-
970-
for (loc_range, loc) in self.locations.iter_mut_all() {
971-
// Only visit accessed permissions
972-
if let Some(p) = loc.perms.get(source_idx)
973-
&& let Some(access_kind) = p.permission.protector_end_access()
974-
&& p.accessed
975-
{
976-
let access_cause = diagnostics::AccessCause::FnExit(access_kind);
977-
loc.perform_access(
978-
self.roots.iter().copied(),
979-
&mut self.nodes,
980-
Some(source_idx),
981-
loc_range,
982-
None,
983-
access_kind,
984-
access_cause,
985-
global,
986-
alloc_id,
987-
span,
988-
ChildrenVisitMode::SkipChildrenOfAccessed,
989-
)?;
990-
}
991-
}
9921002
}
9931003
interp_ok(())
9941004
}

0 commit comments

Comments
 (0)