Skip to content

Commit 62a3f8e

Browse files
Add further comments explaining "piecewise bottom-up"
1 parent db9ee53 commit 62a3f8e

File tree

1 file changed

+40
-11
lines changed
  • src/borrow_tracker/tree_borrows

1 file changed

+40
-11
lines changed

src/borrow_tracker/tree_borrows/tree.rs

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,12 @@ enum ContinueTraversal {
302302
SkipSelfAndChildren,
303303
}
304304

305+
#[derive(Clone, Copy)]
306+
pub enum ChildrenVisitMode {
307+
VisitChildrenOfAccessed,
308+
SkipChildrenOfAccessed,
309+
}
310+
305311
/// Stack of nodes left to explore in a tree traversal.
306312
struct TreeVisitorStack<NodeContinue, NodeApp, ErrHandler> {
307313
/// Identifier of the original access.
@@ -316,9 +322,9 @@ struct TreeVisitorStack<NodeContinue, NodeApp, ErrHandler> {
316322
/// Mutable state of the visit: the tags left to handle.
317323
/// Every tag pushed should eventually be handled,
318324
/// and the precise order is relevant for diagnostics.
319-
/// Since the traversal is bottom-up, we need to remember
320-
/// whether we're here initially (false) or after visiting all
321-
/// children (true). The bool indicates this.
325+
/// Since the traversal is piecewise bottom-up, we need to
326+
/// remember whether we're here initially (false) or after
327+
/// visiting all children (true). The bool indicates this.
322328
stack: Vec<(UniIndex, AccessRelatedness, bool)>,
323329
}
324330

@@ -362,15 +368,15 @@ where
362368
&mut self,
363369
this: &mut TreeVisitor<'_>,
364370
accessed_node: UniIndex,
365-
push_children_of_accessed: bool,
371+
visit_children: ChildrenVisitMode,
366372
) -> Result<(), OutErr> {
367373
assert!(self.stack.is_empty());
368374
// First, handle accessed node. A bunch of things need to
369375
// be handled differently here compared to the further parents
370376
// of `accesssed_node`.
371377
{
372378
self.propagate_at(this, accessed_node, AccessRelatedness::This)?;
373-
if push_children_of_accessed {
379+
if matches!(visit_children, ChildrenVisitMode::VisitChildrenOfAccessed) {
374380
let accessed_node = this.nodes.get(accessed_node).unwrap();
375381
for &child in accessed_node.children.iter().rev() {
376382
self.stack.push((child, AccessRelatedness::AncestorAccess, false));
@@ -437,19 +443,34 @@ where
437443
}
438444

439445
impl<'tree> TreeVisitor<'tree> {
440-
// Applies `f_propagate` to every vertex of the tree bottom-up in the following order: first
446+
// Applies `f_propagate` to every vertex of the tree in a piecewise bottom-up way: First, visit
441447
// all ancestors of `start` (starting with `start` itself), then children of `start`, then the rest,
442-
// always going bottom-up.
448+
// going bottom-up in each of these two "pieces" / sections.
443449
// This ensures that errors are triggered in the following order
444450
// - first invalid accesses with insufficient permissions, closest to the accessed node first,
445451
// - then protector violations, bottom-up, starting with the children of the accessed node, and then
446452
// going upwards and outwards.
453+
// The following graphic visualizes it, with numbers indicating visitation order and `start` being
454+
// the node that is visited first ("1"):
455+
//
456+
// 3
457+
// |
458+
// 2
459+
// /|\
460+
// / | \
461+
// 7 1 8
462+
// / \
463+
// 4 6
464+
// |
465+
// 5
447466
//
448467
// `f_propagate` should follow the following format: for a given `Node` it updates its
449468
// `Permission` depending on the position relative to `start` (given by an
450469
// `AccessRelatedness`).
451-
// `f_continue` is called before on foreign nodes, and describes whether to continue
452-
// with the subtree at that node.
470+
// `f_continue` is called earlier on foreign nodes, and describes whether to even start
471+
// visiting the subtree at that node. If it e.g. returns `SkipSelfAndChildren` on node 6
472+
// above, then nodes 5 _and_ 6 would not be visited by `f_propagate`. It is not used for
473+
// notes having a child access (nodes 1, 2, 3).
453474
fn traverse_this_parents_children_other<InnErr, OutErr>(
454475
mut self,
455476
start: BorTag,
@@ -463,7 +484,11 @@ impl<'tree> TreeVisitor<'tree> {
463484
// undergoing a child access. Also pushes the children and the other
464485
// cousin nodes (i.e. all nodes undergoing a foreign access) to the stack
465486
// to be processed later.
466-
stack.go_upwards_from_accessed(&mut self, start_idx, true)?;
487+
stack.go_upwards_from_accessed(
488+
&mut self,
489+
start_idx,
490+
ChildrenVisitMode::VisitChildrenOfAccessed,
491+
)?;
467492
// Now visit all the foreign nodes we remembered earlier.
468493
// For this we go bottom-up, but also allow f_continue to skip entire
469494
// subtrees from being visited if it would be a NOP.
@@ -483,7 +508,11 @@ impl<'tree> TreeVisitor<'tree> {
483508
// Visits the accessed node itself, and all its parents, i.e. all nodes
484509
// undergoing a child access. Also pushes the other cousin nodes to the
485510
// stack, but not the children of the accessed node.
486-
stack.go_upwards_from_accessed(&mut self, start_idx, false)?;
511+
stack.go_upwards_from_accessed(
512+
&mut self,
513+
start_idx,
514+
ChildrenVisitMode::SkipChildrenOfAccessed,
515+
)?;
487516
// Now visit all the foreign nodes we remembered earlier.
488517
// For this we go bottom-up, but also allow f_continue to skip entire
489518
// subtrees from being visited if it would be a NOP.

0 commit comments

Comments
 (0)