From da8aa1873af5cce84c1599ad300779d3d2ab3f09 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Thu, 29 Aug 2024 09:22:13 +0000 Subject: [PATCH] improve(traverse)!: `TraverseCtx::ancestors` iterator do not yield `Ancestor::None` (#5295) `TraverseCtx::ancestors` iterator would previously yield `Some(Ancestor::None)` before finally yielding `None`. Skip `Ancestor::None` as it's pointless. --- crates/oxc_traverse/src/context/ancestry.rs | 9 +++++++-- crates/oxc_traverse/src/context/mod.rs | 4 +++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/crates/oxc_traverse/src/context/ancestry.rs b/crates/oxc_traverse/src/context/ancestry.rs index 8ec37e4c22501..5df99e456cb5d 100644 --- a/crates/oxc_traverse/src/context/ancestry.rs +++ b/crates/oxc_traverse/src/context/ancestry.rs @@ -90,9 +90,14 @@ impl<'a> TraverseAncestry<'a> { } } - /// Get iterator over ancestors, starting with closest ancestor + /// Get iterator over ancestors, starting with parent and working up. + /// + /// Last `Ancestor` returned will be `Program`. `Ancestor::None` is not included in iteration. pub fn ancestors<'t>(&'t self) -> impl Iterator> { - self.stack.iter().rev().map(|&ancestor| { + debug_assert!(!self.stack.is_empty()); + // SAFETY: Stack always has at least 1 entry + let stack_without_first = unsafe { self.stack.get_unchecked(1..) }; + stack_without_first.iter().rev().map(|&ancestor| { // Shrink `Ancestor`'s `'t` lifetime to lifetime of `&'t self`. // SAFETY: The `Ancestor` is guaranteed valid for `'t`. It is not possible to obtain // a `&mut` ref to any AST node which this `Ancestor` gives access to during `'t`. diff --git a/crates/oxc_traverse/src/context/mod.rs b/crates/oxc_traverse/src/context/mod.rs index 5092c5a3891e6..5714a0abe00f3 100644 --- a/crates/oxc_traverse/src/context/mod.rs +++ b/crates/oxc_traverse/src/context/mod.rs @@ -151,7 +151,9 @@ impl<'a> TraverseCtx<'a> { self.ancestry.ancestor(level) } - /// Get iterator over ancestors, starting with closest ancestor. + /// Get iterator over ancestors, starting with parent and working up. + /// + /// Last `Ancestor` returned will be `Program`. `Ancestor::None` is not included in iteration. /// /// Shortcut for `ctx.ancestry.ancestors`. #[inline]