| 261 | |
| 262 | #[allow(clippy::as_conversions)] |
| 263 | fn visit_mut_post<F>(&mut self, f: &mut F) |
| 264 | where |
| 265 | F: FnMut(&mut Self), |
| 266 | { |
| 267 | // This code uses `unsafe`. The core safety argument is that: |
| 268 | // |
| 269 | // - `children_mut()` produces disjoint children |
| 270 | // - no aliasing means each `Enter` is processed separately, and we `Leave` each node exactly once |
| 271 | // |
| 272 | // Put another way, our `stack` mirrors the function call stack, which allows multiple `&mut` refs at once, |
| 273 | // since only one stack frame can be active at a time. |
| 274 | |
| 275 | use VisitMutAction::*; |
| 276 | let mut stack = vec![Enter(self as *mut T)]; |
| 277 | while let Some(action) = stack.pop() { |
| 278 | match action { |
| 279 | Enter(ptr) => { |
| 280 | stack.push(Leave(ptr)); |
| 281 | let elt = unsafe { &mut *ptr }; |
| 282 | // Push children in reverse so they pop (and are visited) left-to-right. |
| 283 | stack.extend(elt.children_mut().rev().map(|child| Enter(child as *mut T))); |
| 284 | } |
| 285 | Leave(elt) => f(unsafe { &mut *elt }), |
| 286 | } |
| 287 | } |
| 288 | } |
| 289 | |
| 290 | fn try_visit_post<F, E>(&self, f: &mut F) -> Result<(), E> |
| 291 | where |