MCPcopy Create free account
hub / github.com/MaterializeInc/materialize / visit_mut_pre_post

Method visit_mut_pre_post

src/expr/src/visit.rs:439–477  ·  view source on GitHub ↗
(&mut self, pre: &mut F1, post: &mut F2)

Source from the content-addressed store, hash-verified

437
438 #[allow(clippy::as_conversions)]
439 fn visit_mut_pre_post<F1, F2>(&mut self, pre: &mut F1, post: &mut F2)
440 where
441 F1: FnMut(&mut Self) -> Option<Vec<&mut Self>>,
442 F2: FnMut(&mut Self),
443 {
444 // This code uses `unsafe`. The core safety argument is that:
445 //
446 // - `children_mut()` produces disjoint children
447 // - no aliasing means each `Enter` is processed separately, and we `Leave` each node exactly once
448 // - even if `pre` modifies the pointer, we retake it before computing children
449 //
450 // Put another way, our `stack` mirrors the function call stack, which allows multiple `&mut` refs at once,
451 // since only one stack frame can be active at a time.
452
453 use VisitMutAction::*;
454 let mut stack = vec![Enter(self as *mut T)];
455 while let Some(action) = stack.pop() {
456 match action {
457 Enter(ptr) => {
458 let elt = unsafe { &mut *ptr };
459 stack.push(Leave(ptr));
460
461 if let Some(children) = pre(elt) {
462 for child in children.into_iter().rev() {
463 stack.push(Enter(child));
464 }
465 } else {
466 let elt = unsafe { &mut *ptr };
467 for child in elt.children_mut().rev() {
468 stack.push(Enter(child));
469 }
470 }
471 }
472 Leave(ptr) => {
473 post(unsafe { &mut *ptr });
474 }
475 }
476 }
477 }
478}
479
480#[cfg(test)]

Callers 6

memoize_exprFunction · 0.80
reduceFunction · 0.80
optimizeFunction · 0.80

Calls 4

popMethod · 0.45
pushMethod · 0.45
into_iterMethod · 0.45
children_mutMethod · 0.45