(&mut self, f: &mut F)
| 309 | |
| 310 | #[allow(clippy::as_conversions)] |
| 311 | fn try_visit_mut_post<F, E>(&mut self, f: &mut F) -> Result<(), E> |
| 312 | where |
| 313 | F: FnMut(&mut Self) -> Result<(), E>, |
| 314 | { |
| 315 | // This code uses `unsafe`. The core safety argument is that: |
| 316 | // |
| 317 | // - `children_mut()` produces disjoint children |
| 318 | // - no aliasing means each `Enter` is processed separately, and we `Leave` each node exactly once |
| 319 | // |
| 320 | // Put another way, our `stack` mirrors the function call stack, which allows multiple `&mut` refs at once, |
| 321 | // since only one stack frame can be active at a time. |
| 322 | |
| 323 | use VisitMutAction::*; |
| 324 | let mut stack = vec![Enter(self as *mut T)]; |
| 325 | while let Some(action) = stack.pop() { |
| 326 | match action { |
| 327 | Enter(ptr) => { |
| 328 | stack.push(Leave(ptr)); |
| 329 | let elt = unsafe { &mut *ptr }; |
| 330 | // Push children in reverse so they pop (and are visited) left-to-right. |
| 331 | stack.extend(elt.children_mut().rev().map(|child| Enter(child as *mut T))); |
| 332 | } |
| 333 | Leave(ptr) => f(unsafe { &mut *ptr })?, |
| 334 | } |
| 335 | } |
| 336 | |
| 337 | Ok(()) |
| 338 | } |
| 339 | |
| 340 | fn visit_pre<F>(&self, f: &mut F) |
| 341 | where |
no test coverage detected