diff --git a/crates/oxc_semantic/src/builder.rs b/crates/oxc_semantic/src/builder.rs index c470cea55442e..e2ce70a285d1f 100644 --- a/crates/oxc_semantic/src/builder.rs +++ b/crates/oxc_semantic/src/builder.rs @@ -618,6 +618,14 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> { self.create_ast_node(kind); } + /// Both this function and `checker::check` must be inlined. Each `visit_*` method calls + /// `leave_node` with a statically known `AstKind`, so inlining allows the compiler to + /// constant-fold `checker::check`'s match, eliminating all non-matching arms. + #[expect( + clippy::inline_always, + reason = "enables compile-time match elimination in checker::check" + )] + #[inline(always)] fn leave_node(&mut self, kind: AstKind<'a>) { if self.check_syntax_error { checker::check(kind, self); diff --git a/crates/oxc_semantic/src/checker/mod.rs b/crates/oxc_semantic/src/checker/mod.rs index f470ea32b588e..9da22c14aeaf2 100644 --- a/crates/oxc_semantic/src/checker/mod.rs +++ b/crates/oxc_semantic/src/checker/mod.rs @@ -9,6 +9,12 @@ use typescript as ts; pub use javascript::is_function_part_of_if_statement; +/// Perform syntax error checking for the given AST node. +/// +/// Must be inlined along with `SemanticBuilder::leave_node` so the compiler can see the +/// concrete `AstKind` variant at each call site and eliminate non-matching arms. +#[expect(clippy::inline_always, reason = "enables compile-time match elimination, see doc comment")] +#[inline(always)] pub fn check<'a>(kind: AstKind<'a>, ctx: &SemanticBuilder<'a>) { match kind { AstKind::Program(program) => {