Skip to content

Commit 9622840

Browse files
make tree_visitor generic
1 parent 88c2c81 commit 9622840

File tree

2 files changed

+75
-72
lines changed

2 files changed

+75
-72
lines changed

src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs

Lines changed: 48 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ use smallvec::SmallVec;
2020

2121
use super::Permission;
2222
use super::diagnostics::{
23-
self, AccessCause, NodeDebugInfo, TbError, TransitionError,
24-
no_valid_exposed_references_error,
23+
self, AccessCause, NodeDebugInfo, TbError, TransitionError, no_valid_exposed_references_error,
2524
};
2625
use super::foreign_access_skipping::IdempotentForeignAccess;
2726
use super::perms::PermTransition;
@@ -562,42 +561,43 @@ impl<'tcx> Tree {
562561
// Checks the tree containing `idx` for strong protector violations.
563562
// It does this in traversal order.
564563
let mut check_tree = |idx| {
565-
TreeVisitor { nodes: &mut self.nodes, loc }.traverse_this_parents_children_other(
566-
idx,
567-
// Visit all children, skipping none.
568-
|_| ContinueTraversal::Recurse,
569-
|args: NodeAppArgs<'_>| {
570-
let node = args.nodes.get(args.idx).unwrap();
564+
TreeVisitor { nodes: &mut self.nodes, data: loc }
565+
.traverse_this_parents_children_other(
566+
idx,
567+
// Visit all children, skipping none.
568+
|_| ContinueTraversal::Recurse,
569+
|args: NodeAppArgs<'_, _>| {
570+
let node = args.nodes.get(args.idx).unwrap();
571571

572-
let perm = args
573-
.loc
574-
.perms
575-
.get(args.idx)
576-
.copied()
577-
.unwrap_or_else(|| node.default_location_state());
578-
if global.borrow().protected_tags.get(&node.tag)
579-
== Some(&ProtectorKind::StrongProtector)
580-
// Don't check for protector if it is a Cell (see `unsafe_cell_deallocate` in `interior_mutability.rs`).
581-
// Related to https://github.com/rust-lang/rust/issues/55005.
582-
&& !perm.permission.is_cell()
583-
// Only trigger UB if the accessed bit is set, i.e. if the protector is actually protecting this offset. See #4579.
584-
&& perm.accessed
585-
{
586-
Err(TbError {
587-
conflicting_info: &node.debug_info,
588-
access_cause: diagnostics::AccessCause::Dealloc,
589-
alloc_id,
590-
error_offset: loc_range.start,
591-
error_kind: TransitionError::ProtectedDealloc,
592-
accessed_info: start_idx
593-
.map(|idx| &args.nodes.get(idx).unwrap().debug_info),
572+
let perm = args
573+
.data
574+
.perms
575+
.get(args.idx)
576+
.copied()
577+
.unwrap_or_else(|| node.default_location_state());
578+
if global.borrow().protected_tags.get(&node.tag)
579+
== Some(&ProtectorKind::StrongProtector)
580+
// Don't check for protector if it is a Cell (see `unsafe_cell_deallocate` in `interior_mutability.rs`).
581+
// Related to https://github.com/rust-lang/rust/issues/55005.
582+
&& !perm.permission.is_cell()
583+
// Only trigger UB if the accessed bit is set, i.e. if the protector is actually protecting this offset. See #4579.
584+
&& perm.accessed
585+
{
586+
Err(TbError {
587+
conflicting_info: &node.debug_info,
588+
access_cause: diagnostics::AccessCause::Dealloc,
589+
alloc_id,
590+
error_offset: loc_range.start,
591+
error_kind: TransitionError::ProtectedDealloc,
592+
accessed_info: start_idx
593+
.map(|idx| &args.nodes.get(idx).unwrap().debug_info),
594+
}
595+
.build())
596+
} else {
597+
Ok(())
594598
}
595-
.build())
596-
} else {
597-
Ok(())
598-
}
599-
},
600-
)
599+
},
600+
)
601601
};
602602
// If we have a start index we first check its subtree in traversal order.
603603
// This results in us showing the error of the closest node instead of an
@@ -967,16 +967,16 @@ impl<'tcx> LocationTree {
967967
//
968968
// `loc_range` is only for diagnostics (it is the range of
969969
// the `RangeMap` on which we are currently working).
970-
let node_skipper = |args: &NodeAppArgs<'_>| -> ContinueTraversal {
970+
let node_skipper = |args: &NodeAppArgs<'_, LocationTree>| -> ContinueTraversal {
971971
let node = args.nodes.get(args.idx).unwrap();
972-
let perm = args.loc.perms.get(args.idx);
972+
let perm = args.data.perms.get(args.idx);
973973

974974
let old_state = perm.copied().unwrap_or_else(|| node.default_location_state());
975975
old_state.skip_if_known_noop(access_kind, args.rel_pos)
976976
};
977-
let node_app = |args: NodeAppArgs<'_>| {
977+
let node_app = |args: NodeAppArgs<'_, LocationTree>| {
978978
let node = args.nodes.get_mut(args.idx).unwrap();
979-
let mut perm = args.loc.perms.entry(args.idx);
979+
let mut perm = args.data.perms.entry(args.idx);
980980

981981
let state = perm.or_insert(node.default_location_state());
982982

@@ -985,7 +985,7 @@ impl<'tcx> LocationTree {
985985
.perform_transition(
986986
args.idx,
987987
args.nodes,
988-
&mut args.loc.wildcard_accesses,
988+
&mut args.data.wildcard_accesses,
989989
access_kind,
990990
access_cause,
991991
access_range,
@@ -1007,7 +1007,7 @@ impl<'tcx> LocationTree {
10071007
})
10081008
};
10091009

1010-
let visitor = TreeVisitor { nodes, loc: self };
1010+
let visitor = TreeVisitor { nodes, data: self };
10111011
match visit_children {
10121012
ChildrenVisitMode::VisitChildrenOfAccessed =>
10131013
visitor.traverse_this_parents_children_other(access_source, node_skipper, node_app),
@@ -1061,16 +1061,16 @@ impl<'tcx> LocationTree {
10611061
// marked as having an exposed foreign node, but actually that foreign node cannot be
10621062
// the source of the access due to `max_local_tag`. The wildcard tracking cannot know
10631063
// about `max_local_tag` so we will incorrectly assume that this might be a foreign access.
1064-
TreeVisitor { loc: self, nodes }.traverse_children_this(
1064+
TreeVisitor { data: self, nodes }.traverse_children_this(
10651065
root,
10661066
|args| -> ContinueTraversal {
10671067
let node = args.nodes.get(args.idx).unwrap();
1068-
let perm = args.loc.perms.get(args.idx);
1068+
let perm = args.data.perms.get(args.idx);
10691069

10701070
let old_state = perm.copied().unwrap_or_else(|| node.default_location_state());
10711071
// If we know where, relative to this node, the wildcard access occurs,
10721072
// then check if we can skip the entire subtree.
1073-
if let Some(relatedness) = get_relatedness(args.idx, node, args.loc)
1073+
if let Some(relatedness) = get_relatedness(args.idx, node, args.data)
10741074
&& let Some(relatedness) = relatedness.to_relatedness()
10751075
{
10761076
// We can use the usual SIFA machinery to skip nodes.
@@ -1084,7 +1084,7 @@ impl<'tcx> LocationTree {
10841084

10851085
let protected = global.borrow().protected_tags.contains_key(&node.tag);
10861086

1087-
let Some(wildcard_relatedness) = get_relatedness(args.idx, node, args.loc) else {
1087+
let Some(wildcard_relatedness) = get_relatedness(args.idx, node, args.data) else {
10881088
// There doesn't exist a valid exposed reference for this access to
10891089
// happen through.
10901090
// This can only happen if `root` is the main root: We set
@@ -1105,13 +1105,13 @@ impl<'tcx> LocationTree {
11051105
return Ok(());
11061106
};
11071107

1108-
let mut entry = args.loc.perms.entry(args.idx);
1108+
let mut entry = args.data.perms.entry(args.idx);
11091109
let perm = entry.or_insert(node.default_location_state());
11101110
// We know the exact relatedness, so we can actually do precise checks.
11111111
perm.perform_transition(
11121112
args.idx,
11131113
args.nodes,
1114-
&mut args.loc.wildcard_accesses,
1114+
&mut args.data.wildcard_accesses,
11151115
access_kind,
11161116
access_cause,
11171117
access_range,

src/tools/miri/src/borrow_tracker/tree_borrows/tree_visitor.rs

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,25 @@
1-
use super::tree::{AccessRelatedness, LocationTree, Node};
1+
use std::marker::PhantomData;
2+
3+
use super::tree::{AccessRelatedness, Node};
24
use super::unimap::{UniIndex, UniValMap};
35

46
/// Data given to the transition function
5-
pub struct NodeAppArgs<'visit> {
7+
pub struct NodeAppArgs<'visit, T> {
68
/// The index of the current node.
79
pub idx: UniIndex,
810
/// Relative position of the access.
911
pub rel_pos: AccessRelatedness,
1012
/// The node map of this tree.
1113
pub nodes: &'visit mut UniValMap<Node>,
12-
/// The permissions map of this tree.
13-
pub loc: &'visit mut LocationTree,
14+
/// Additional data we want to be able to modify in f_propagate and read in f_continue.
15+
pub data: &'visit mut T,
1416
}
1517
/// Internal contents of `Tree` with the minimum of mutable access for
1618
/// For soundness do not modify the children or parent indexes of nodes
1719
/// during traversal.
18-
pub struct TreeVisitor<'tree> {
20+
pub struct TreeVisitor<'tree, T> {
1921
pub nodes: &'tree mut UniValMap<Node>,
20-
pub loc: &'tree mut LocationTree,
22+
pub data: &'tree mut T,
2123
}
2224

2325
/// Whether to continue exploring the children recursively or not.
@@ -41,7 +43,7 @@ enum RecursionState {
4143
/// Stack of nodes left to explore in a tree traversal.
4244
/// See the docs of `traverse_this_parents_children_other` for details on the
4345
/// traversal order.
44-
struct TreeVisitorStack<NodeContinue, NodeApp> {
46+
struct TreeVisitorStack<NodeContinue, NodeApp, T> {
4547
/// Function describing whether to continue at a tag.
4648
/// This is only invoked for foreign accesses.
4749
f_continue: NodeContinue,
@@ -56,36 +58,37 @@ struct TreeVisitorStack<NodeContinue, NodeApp> {
5658
/// This is just an artifact of how you hand-roll recursion,
5759
/// it does not have a deeper meaning otherwise.
5860
stack: Vec<(UniIndex, AccessRelatedness, RecursionState)>,
61+
phantom: PhantomData<T>,
5962
}
6063

61-
impl<NodeContinue, NodeApp, Err> TreeVisitorStack<NodeContinue, NodeApp>
64+
impl<NodeContinue, NodeApp, T, Err> TreeVisitorStack<NodeContinue, NodeApp, T>
6265
where
63-
NodeContinue: Fn(&NodeAppArgs<'_>) -> ContinueTraversal,
64-
NodeApp: FnMut(NodeAppArgs<'_>) -> Result<(), Err>,
66+
NodeContinue: Fn(&NodeAppArgs<'_, T>) -> ContinueTraversal,
67+
NodeApp: FnMut(NodeAppArgs<'_, T>) -> Result<(), Err>,
6568
{
6669
fn should_continue_at(
6770
&self,
68-
this: &mut TreeVisitor<'_>,
71+
this: &mut TreeVisitor<'_, T>,
6972
idx: UniIndex,
7073
rel_pos: AccessRelatedness,
7174
) -> ContinueTraversal {
72-
let args = NodeAppArgs { idx, rel_pos, nodes: this.nodes, loc: this.loc };
75+
let args = NodeAppArgs { idx, rel_pos, nodes: this.nodes, data: this.data };
7376
(self.f_continue)(&args)
7477
}
7578

7679
fn propagate_at(
7780
&mut self,
78-
this: &mut TreeVisitor<'_>,
81+
this: &mut TreeVisitor<'_, T>,
7982
idx: UniIndex,
8083
rel_pos: AccessRelatedness,
8184
) -> Result<(), Err> {
82-
(self.f_propagate)(NodeAppArgs { idx, rel_pos, nodes: this.nodes, loc: this.loc })
85+
(self.f_propagate)(NodeAppArgs { idx, rel_pos, nodes: this.nodes, data: this.data })
8386
}
8487

8588
/// Returns the root of this tree.
8689
fn go_upwards_from_accessed(
8790
&mut self,
88-
this: &mut TreeVisitor<'_>,
91+
this: &mut TreeVisitor<'_, T>,
8992
accessed_node: UniIndex,
9093
visit_children: ChildrenVisitMode,
9194
) -> Result<UniIndex, Err> {
@@ -136,7 +139,7 @@ where
136139
Ok(last_node)
137140
}
138141

139-
fn finish_foreign_accesses(&mut self, this: &mut TreeVisitor<'_>) -> Result<(), Err> {
142+
fn finish_foreign_accesses(&mut self, this: &mut TreeVisitor<'_, T>) -> Result<(), Err> {
140143
while let Some((idx, rel_pos, step)) = self.stack.last_mut() {
141144
let idx = *idx;
142145
let rel_pos = *rel_pos;
@@ -173,11 +176,11 @@ where
173176
}
174177

175178
fn new(f_continue: NodeContinue, f_propagate: NodeApp) -> Self {
176-
Self { f_continue, f_propagate, stack: Vec::new() }
179+
Self { f_continue, f_propagate, stack: Vec::new(), phantom: PhantomData }
177180
}
178181
}
179182

180-
impl<'tree> TreeVisitor<'tree> {
183+
impl<'tree, T> TreeVisitor<'tree, T> {
181184
/// Applies `f_propagate` to every vertex of the tree in a piecewise bottom-up way: First, visit
182185
/// all ancestors of `start_idx` (starting with `start_idx` itself), then children of `start_idx`, then the rest,
183186
/// going bottom-up in each of these two "pieces" / sections.
@@ -219,8 +222,8 @@ impl<'tree> TreeVisitor<'tree> {
219222
pub fn traverse_this_parents_children_other<Err>(
220223
mut self,
221224
start_idx: UniIndex,
222-
f_continue: impl Fn(&NodeAppArgs<'_>) -> ContinueTraversal,
223-
f_propagate: impl FnMut(NodeAppArgs<'_>) -> Result<(), Err>,
225+
f_continue: impl Fn(&NodeAppArgs<'_, T>) -> ContinueTraversal,
226+
f_propagate: impl FnMut(NodeAppArgs<'_, T>) -> Result<(), Err>,
224227
) -> Result<UniIndex, Err> {
225228
let mut stack = TreeVisitorStack::new(f_continue, f_propagate);
226229
// Visits the accessed node itself, and all its parents, i.e. all nodes
@@ -245,8 +248,8 @@ impl<'tree> TreeVisitor<'tree> {
245248
pub fn traverse_nonchildren<Err>(
246249
mut self,
247250
start_idx: UniIndex,
248-
f_continue: impl Fn(&NodeAppArgs<'_>) -> ContinueTraversal,
249-
f_propagate: impl FnMut(NodeAppArgs<'_>) -> Result<(), Err>,
251+
f_continue: impl Fn(&NodeAppArgs<'_, T>) -> ContinueTraversal,
252+
f_propagate: impl FnMut(NodeAppArgs<'_, T>) -> Result<(), Err>,
250253
) -> Result<UniIndex, Err> {
251254
let mut stack = TreeVisitorStack::new(f_continue, f_propagate);
252255
// Visits the accessed node itself, and all its parents, i.e. all nodes
@@ -271,8 +274,8 @@ impl<'tree> TreeVisitor<'tree> {
271274
pub fn traverse_children_this<Err>(
272275
mut self,
273276
start_idx: UniIndex,
274-
f_continue: impl Fn(&NodeAppArgs<'_>) -> ContinueTraversal,
275-
f_propagate: impl FnMut(NodeAppArgs<'_>) -> Result<(), Err>,
277+
f_continue: impl Fn(&NodeAppArgs<'_, T>) -> ContinueTraversal,
278+
f_propagate: impl FnMut(NodeAppArgs<'_, T>) -> Result<(), Err>,
276279
) -> Result<(), Err> {
277280
let mut stack = TreeVisitorStack::new(f_continue, f_propagate);
278281

0 commit comments

Comments
 (0)