perf(ast): delegate inherited enum variants in clone_in and estree derives (#23555)

## What

Enums built with the `inherit_variants!` macro (`Argument`,
`PropertyKey`, `ForStatementInit`, `Statement`, `AssignmentTarget`, ...)
inline a parent enum's variants (e.g. all ~30 of `Expression`'s) with
**matching discriminants**. The `clone_in` and `estree` derives
previously re-emitted a `match` arm for every inherited variant, so the
parent enum's entire dispatch was duplicated into each inheriting enum,
in each operation.

This delegates inherited variants to the parent enum's own impl instead
of expanding them:

- read-only (`estree`): `... =>
self.to_expression().serialize(serializer)`
- producing (`clone_in`): `... =>
Self::from(CloneIn::clone_in(self.to_expression(), allocator))`

using the `to_<parent>()` reference cast and the `From<Parent>` impl
that `inherit_variants!` **already generates**. Both are zero-cost
transmutes, sound because the inherited variants share discriminants and
layout with the parent enum.

Only the generators in
`tasks/ast_tools/src/derives/{clone_in,estree}.rs` are hand-edited; the
rest is regenerated.

## Why

These inheritance enums account for a large share of `oxc_ast`'s
generated code. The duplication is the dominant size cost in the AST
derives (most visible in downstream consumers like rolldown, where
`ESTree` serialize is also monomorphized per serializer config).
Delegation is behaviour-identical and removes ~1,250 net lines of
generated code.

## Verification

- ESTree output is **byte-identical**: `cargo coverage estree` unchanged
(same pass rate, same pre-existing mismatches, no snapshot diff).
- `clone_in`: `oxc_transformer` / `oxc_semantic` / `oxc_minifier` test
suites pass; `cargo llvm-lines -p oxc_ast` shows -17% `CloneIn` IR.
This commit is contained in:
Boshen authored and GitHub committed 2026-07-12 11:14:10 +01:00
1 parent a66f0fd99b
commit f85f0d88b8
4 files changed
+1184 -2431

No files matched your search

File diff suppressed because it is too large. Load diff
+357 -352
View File
@@ -62,9 +62,9 @@ impl ESTree for Expression<'_> {
Self::TSNonNullExpression(it) => it.serialize(serializer),
Self::TSInstantiationExpression(it) => it.serialize(serializer),
Self::V8IntrinsicExpression(it) => it.serialize(serializer),
Self::ComputedMemberExpression(it) => it.serialize(serializer),
Self::StaticMemberExpression(it) => it.serialize(serializer),
Self::PrivateFieldExpression(it) => it.serialize(serializer),
Self::ComputedMemberExpression(_)
| Self::StaticMemberExpression(_)
| Self::PrivateFieldExpression(_) => self.to_member_expression().serialize(serializer),
}
}
}
@@ -148,49 +148,49 @@ impl ESTree for ArrayExpressionElement<'_> {
match self {
Self::SpreadElement(it) => it.serialize(serializer),
Self::Elision(it) => it.serialize(serializer),
Self::BooleanLiteral(it) => it.serialize(serializer),
Self::NullLiteral(it) => it.serialize(serializer),
Self::NumericLiteral(it) => it.serialize(serializer),
Self::BigIntLiteral(it) => it.serialize(serializer),
Self::RegExpLiteral(it) => it.serialize(serializer),
Self::StringLiteral(it) => it.serialize(serializer),
Self::TemplateLiteral(it) => it.serialize(serializer),
Self::Identifier(it) => it.serialize(serializer),
Self::MetaProperty(it) => it.serialize(serializer),
Self::Super(it) => it.serialize(serializer),
Self::ArrayExpression(it) => it.serialize(serializer),
Self::ArrowFunctionExpression(it) => it.serialize(serializer),
Self::AssignmentExpression(it) => it.serialize(serializer),
Self::AwaitExpression(it) => it.serialize(serializer),
Self::BinaryExpression(it) => it.serialize(serializer),
Self::CallExpression(it) => it.serialize(serializer),
Self::ChainExpression(it) => it.serialize(serializer),
Self::ClassExpression(it) => it.serialize(serializer),
Self::ConditionalExpression(it) => it.serialize(serializer),
Self::FunctionExpression(it) => it.serialize(serializer),
Self::ImportExpression(it) => it.serialize(serializer),
Self::LogicalExpression(it) => it.serialize(serializer),
Self::NewExpression(it) => it.serialize(serializer),
Self::ObjectExpression(it) => it.serialize(serializer),
Self::ParenthesizedExpression(it) => it.serialize(serializer),
Self::SequenceExpression(it) => it.serialize(serializer),
Self::TaggedTemplateExpression(it) => it.serialize(serializer),
Self::ThisExpression(it) => it.serialize(serializer),
Self::UnaryExpression(it) => it.serialize(serializer),
Self::UpdateExpression(it) => it.serialize(serializer),
Self::YieldExpression(it) => it.serialize(serializer),
Self::PrivateInExpression(it) => it.serialize(serializer),
Self::JSXElement(it) => it.serialize(serializer),
Self::JSXFragment(it) => it.serialize(serializer),
Self::TSAsExpression(it) => it.serialize(serializer),
Self::TSSatisfiesExpression(it) => it.serialize(serializer),
Self::TSTypeAssertion(it) => it.serialize(serializer),
Self::TSNonNullExpression(it) => it.serialize(serializer),
Self::TSInstantiationExpression(it) => it.serialize(serializer),
Self::V8IntrinsicExpression(it) => it.serialize(serializer),
Self::ComputedMemberExpression(it) => it.serialize(serializer),
Self::StaticMemberExpression(it) => it.serialize(serializer),
Self::PrivateFieldExpression(it) => it.serialize(serializer),
Self::BooleanLiteral(_)
| Self::NullLiteral(_)
| Self::NumericLiteral(_)
| Self::BigIntLiteral(_)
| Self::RegExpLiteral(_)
| Self::StringLiteral(_)
| Self::TemplateLiteral(_)
| Self::Identifier(_)
| Self::MetaProperty(_)
| Self::Super(_)
| Self::ArrayExpression(_)
| Self::ArrowFunctionExpression(_)
| Self::AssignmentExpression(_)
| Self::AwaitExpression(_)
| Self::BinaryExpression(_)
| Self::CallExpression(_)
| Self::ChainExpression(_)
| Self::ClassExpression(_)
| Self::ConditionalExpression(_)
| Self::FunctionExpression(_)
| Self::ImportExpression(_)
| Self::LogicalExpression(_)
| Self::NewExpression(_)
| Self::ObjectExpression(_)
| Self::ParenthesizedExpression(_)
| Self::SequenceExpression(_)
| Self::TaggedTemplateExpression(_)
| Self::ThisExpression(_)
| Self::UnaryExpression(_)
| Self::UpdateExpression(_)
| Self::YieldExpression(_)
| Self::PrivateInExpression(_)
| Self::JSXElement(_)
| Self::JSXFragment(_)
| Self::TSAsExpression(_)
| Self::TSSatisfiesExpression(_)
| Self::TSTypeAssertion(_)
| Self::TSNonNullExpression(_)
| Self::TSInstantiationExpression(_)
| Self::V8IntrinsicExpression(_)
| Self::ComputedMemberExpression(_)
| Self::StaticMemberExpression(_)
| Self::PrivateFieldExpression(_) => self.to_expression().serialize(serializer),
}
}
}
@@ -241,49 +241,49 @@ impl ESTree for PropertyKey<'_> {
match self {
Self::StaticIdentifier(it) => it.serialize(serializer),
Self::PrivateIdentifier(it) => it.serialize(serializer),
Self::BooleanLiteral(it) => it.serialize(serializer),
Self::NullLiteral(it) => it.serialize(serializer),
Self::NumericLiteral(it) => it.serialize(serializer),
Self::BigIntLiteral(it) => it.serialize(serializer),
Self::RegExpLiteral(it) => it.serialize(serializer),
Self::StringLiteral(it) => it.serialize(serializer),
Self::TemplateLiteral(it) => it.serialize(serializer),
Self::Identifier(it) => it.serialize(serializer),
Self::MetaProperty(it) => it.serialize(serializer),
Self::Super(it) => it.serialize(serializer),
Self::ArrayExpression(it) => it.serialize(serializer),
Self::ArrowFunctionExpression(it) => it.serialize(serializer),
Self::AssignmentExpression(it) => it.serialize(serializer),
Self::AwaitExpression(it) => it.serialize(serializer),
Self::BinaryExpression(it) => it.serialize(serializer),
Self::CallExpression(it) => it.serialize(serializer),
Self::ChainExpression(it) => it.serialize(serializer),
Self::ClassExpression(it) => it.serialize(serializer),
Self::ConditionalExpression(it) => it.serialize(serializer),
Self::FunctionExpression(it) => it.serialize(serializer),
Self::ImportExpression(it) => it.serialize(serializer),
Self::LogicalExpression(it) => it.serialize(serializer),
Self::NewExpression(it) => it.serialize(serializer),
Self::ObjectExpression(it) => it.serialize(serializer),
Self::ParenthesizedExpression(it) => it.serialize(serializer),
Self::SequenceExpression(it) => it.serialize(serializer),
Self::TaggedTemplateExpression(it) => it.serialize(serializer),
Self::ThisExpression(it) => it.serialize(serializer),
Self::UnaryExpression(it) => it.serialize(serializer),
Self::UpdateExpression(it) => it.serialize(serializer),
Self::YieldExpression(it) => it.serialize(serializer),
Self::PrivateInExpression(it) => it.serialize(serializer),
Self::JSXElement(it) => it.serialize(serializer),
Self::JSXFragment(it) => it.serialize(serializer),
Self::TSAsExpression(it) => it.serialize(serializer),
Self::TSSatisfiesExpression(it) => it.serialize(serializer),
Self::TSTypeAssertion(it) => it.serialize(serializer),
Self::TSNonNullExpression(it) => it.serialize(serializer),
Self::TSInstantiationExpression(it) => it.serialize(serializer),
Self::V8IntrinsicExpression(it) => it.serialize(serializer),
Self::ComputedMemberExpression(it) => it.serialize(serializer),
Self::StaticMemberExpression(it) => it.serialize(serializer),
Self::PrivateFieldExpression(it) => it.serialize(serializer),
Self::BooleanLiteral(_)
| Self::NullLiteral(_)
| Self::NumericLiteral(_)
| Self::BigIntLiteral(_)
| Self::RegExpLiteral(_)
| Self::StringLiteral(_)
| Self::TemplateLiteral(_)
| Self::Identifier(_)
| Self::MetaProperty(_)
| Self::Super(_)
| Self::ArrayExpression(_)
| Self::ArrowFunctionExpression(_)
| Self::AssignmentExpression(_)
| Self::AwaitExpression(_)
| Self::BinaryExpression(_)
| Self::CallExpression(_)
| Self::ChainExpression(_)
| Self::ClassExpression(_)
| Self::ConditionalExpression(_)
| Self::FunctionExpression(_)
| Self::ImportExpression(_)
| Self::LogicalExpression(_)
| Self::NewExpression(_)
| Self::ObjectExpression(_)
| Self::ParenthesizedExpression(_)
| Self::SequenceExpression(_)
| Self::TaggedTemplateExpression(_)
| Self::ThisExpression(_)
| Self::UnaryExpression(_)
| Self::UpdateExpression(_)
| Self::YieldExpression(_)
| Self::PrivateInExpression(_)
| Self::JSXElement(_)
| Self::JSXFragment(_)
| Self::TSAsExpression(_)
| Self::TSSatisfiesExpression(_)
| Self::TSTypeAssertion(_)
| Self::TSNonNullExpression(_)
| Self::TSInstantiationExpression(_)
| Self::V8IntrinsicExpression(_)
| Self::ComputedMemberExpression(_)
| Self::StaticMemberExpression(_)
| Self::PrivateFieldExpression(_) => self.to_expression().serialize(serializer),
}
}
}
@@ -435,49 +435,49 @@ impl ESTree for Argument<'_> {
fn serialize<S: Serializer>(&self, serializer: S) {
match self {
Self::SpreadElement(it) => it.serialize(serializer),
Self::BooleanLiteral(it) => it.serialize(serializer),
Self::NullLiteral(it) => it.serialize(serializer),
Self::NumericLiteral(it) => it.serialize(serializer),
Self::BigIntLiteral(it) => it.serialize(serializer),
Self::RegExpLiteral(it) => it.serialize(serializer),
Self::StringLiteral(it) => it.serialize(serializer),
Self::TemplateLiteral(it) => it.serialize(serializer),
Self::Identifier(it) => it.serialize(serializer),
Self::MetaProperty(it) => it.serialize(serializer),
Self::Super(it) => it.serialize(serializer),
Self::ArrayExpression(it) => it.serialize(serializer),
Self::ArrowFunctionExpression(it) => it.serialize(serializer),
Self::AssignmentExpression(it) => it.serialize(serializer),
Self::AwaitExpression(it) => it.serialize(serializer),
Self::BinaryExpression(it) => it.serialize(serializer),
Self::CallExpression(it) => it.serialize(serializer),
Self::ChainExpression(it) => it.serialize(serializer),
Self::ClassExpression(it) => it.serialize(serializer),
Self::ConditionalExpression(it) => it.serialize(serializer),
Self::FunctionExpression(it) => it.serialize(serializer),
Self::ImportExpression(it) => it.serialize(serializer),
Self::LogicalExpression(it) => it.serialize(serializer),
Self::NewExpression(it) => it.serialize(serializer),
Self::ObjectExpression(it) => it.serialize(serializer),
Self::ParenthesizedExpression(it) => it.serialize(serializer),
Self::SequenceExpression(it) => it.serialize(serializer),
Self::TaggedTemplateExpression(it) => it.serialize(serializer),
Self::ThisExpression(it) => it.serialize(serializer),
Self::UnaryExpression(it) => it.serialize(serializer),
Self::UpdateExpression(it) => it.serialize(serializer),
Self::YieldExpression(it) => it.serialize(serializer),
Self::PrivateInExpression(it) => it.serialize(serializer),
Self::JSXElement(it) => it.serialize(serializer),
Self::JSXFragment(it) => it.serialize(serializer),
Self::TSAsExpression(it) => it.serialize(serializer),
Self::TSSatisfiesExpression(it) => it.serialize(serializer),
Self::TSTypeAssertion(it) => it.serialize(serializer),
Self::TSNonNullExpression(it) => it.serialize(serializer),
Self::TSInstantiationExpression(it) => it.serialize(serializer),
Self::V8IntrinsicExpression(it) => it.serialize(serializer),
Self::ComputedMemberExpression(it) => it.serialize(serializer),
Self::StaticMemberExpression(it) => it.serialize(serializer),
Self::PrivateFieldExpression(it) => it.serialize(serializer),
Self::BooleanLiteral(_)
| Self::NullLiteral(_)
| Self::NumericLiteral(_)
| Self::BigIntLiteral(_)
| Self::RegExpLiteral(_)
| Self::StringLiteral(_)
| Self::TemplateLiteral(_)
| Self::Identifier(_)
| Self::MetaProperty(_)
| Self::Super(_)
| Self::ArrayExpression(_)
| Self::ArrowFunctionExpression(_)
| Self::AssignmentExpression(_)
| Self::AwaitExpression(_)
| Self::BinaryExpression(_)
| Self::CallExpression(_)
| Self::ChainExpression(_)
| Self::ClassExpression(_)
| Self::ConditionalExpression(_)
| Self::FunctionExpression(_)
| Self::ImportExpression(_)
| Self::LogicalExpression(_)
| Self::NewExpression(_)
| Self::ObjectExpression(_)
| Self::ParenthesizedExpression(_)
| Self::SequenceExpression(_)
| Self::TaggedTemplateExpression(_)
| Self::ThisExpression(_)
| Self::UnaryExpression(_)
| Self::UpdateExpression(_)
| Self::YieldExpression(_)
| Self::PrivateInExpression(_)
| Self::JSXElement(_)
| Self::JSXFragment(_)
| Self::TSAsExpression(_)
| Self::TSSatisfiesExpression(_)
| Self::TSTypeAssertion(_)
| Self::TSNonNullExpression(_)
| Self::TSInstantiationExpression(_)
| Self::V8IntrinsicExpression(_)
| Self::ComputedMemberExpression(_)
| Self::StaticMemberExpression(_)
| Self::PrivateFieldExpression(_) => self.to_expression().serialize(serializer),
}
}
}
@@ -569,16 +569,19 @@ impl ESTree for AssignmentExpression<'_> {
impl ESTree for AssignmentTarget<'_> {
fn serialize<S: Serializer>(&self, serializer: S) {
match self {
Self::AssignmentTargetIdentifier(it) => it.serialize(serializer),
Self::TSAsExpression(it) => it.serialize(serializer),
Self::TSSatisfiesExpression(it) => it.serialize(serializer),
Self::TSNonNullExpression(it) => it.serialize(serializer),
Self::TSTypeAssertion(it) => it.serialize(serializer),
Self::ComputedMemberExpression(it) => it.serialize(serializer),
Self::StaticMemberExpression(it) => it.serialize(serializer),
Self::PrivateFieldExpression(it) => it.serialize(serializer),
Self::ArrayAssignmentTarget(it) => it.serialize(serializer),
Self::ObjectAssignmentTarget(it) => it.serialize(serializer),
Self::AssignmentTargetIdentifier(_)
| Self::TSAsExpression(_)
| Self::TSSatisfiesExpression(_)
| Self::TSNonNullExpression(_)
| Self::TSTypeAssertion(_)
| Self::ComputedMemberExpression(_)
| Self::StaticMemberExpression(_)
| Self::PrivateFieldExpression(_) => {
self.to_simple_assignment_target().serialize(serializer)
}
Self::ArrayAssignmentTarget(_) | Self::ObjectAssignmentTarget(_) => {
self.to_assignment_target_pattern().serialize(serializer)
}
}
}
}
@@ -591,9 +594,9 @@ impl ESTree for SimpleAssignmentTarget<'_> {
Self::TSSatisfiesExpression(it) => it.serialize(serializer),
Self::TSNonNullExpression(it) => it.serialize(serializer),
Self::TSTypeAssertion(it) => it.serialize(serializer),
Self::ComputedMemberExpression(it) => it.serialize(serializer),
Self::StaticMemberExpression(it) => it.serialize(serializer),
Self::PrivateFieldExpression(it) => it.serialize(serializer),
Self::ComputedMemberExpression(_)
| Self::StaticMemberExpression(_)
| Self::PrivateFieldExpression(_) => self.to_member_expression().serialize(serializer),
}
}
}
@@ -651,16 +654,16 @@ impl ESTree for AssignmentTargetMaybeDefault<'_> {
fn serialize<S: Serializer>(&self, serializer: S) {
match self {
Self::AssignmentTargetWithDefault(it) => it.serialize(serializer),
Self::AssignmentTargetIdentifier(it) => it.serialize(serializer),
Self::TSAsExpression(it) => it.serialize(serializer),
Self::TSSatisfiesExpression(it) => it.serialize(serializer),
Self::TSNonNullExpression(it) => it.serialize(serializer),
Self::TSTypeAssertion(it) => it.serialize(serializer),
Self::ComputedMemberExpression(it) => it.serialize(serializer),
Self::StaticMemberExpression(it) => it.serialize(serializer),
Self::PrivateFieldExpression(it) => it.serialize(serializer),
Self::ArrayAssignmentTarget(it) => it.serialize(serializer),
Self::ObjectAssignmentTarget(it) => it.serialize(serializer),
Self::AssignmentTargetIdentifier(_)
| Self::TSAsExpression(_)
| Self::TSSatisfiesExpression(_)
| Self::TSNonNullExpression(_)
| Self::TSTypeAssertion(_)
| Self::ComputedMemberExpression(_)
| Self::StaticMemberExpression(_)
| Self::PrivateFieldExpression(_)
| Self::ArrayAssignmentTarget(_)
| Self::ObjectAssignmentTarget(_) => self.to_assignment_target().serialize(serializer),
}
}
}
@@ -767,9 +770,9 @@ impl ESTree for ChainElement<'_> {
match self {
Self::CallExpression(it) => it.serialize(serializer),
Self::TSNonNullExpression(it) => it.serialize(serializer),
Self::ComputedMemberExpression(it) => it.serialize(serializer),
Self::StaticMemberExpression(it) => it.serialize(serializer),
Self::PrivateFieldExpression(it) => it.serialize(serializer),
Self::ComputedMemberExpression(_)
| Self::StaticMemberExpression(_)
| Self::PrivateFieldExpression(_) => self.to_member_expression().serialize(serializer),
}
}
}
@@ -801,21 +804,23 @@ impl ESTree for Statement<'_> {
Self::TryStatement(it) => it.serialize(serializer),
Self::WhileStatement(it) => it.serialize(serializer),
Self::WithStatement(it) => it.serialize(serializer),
Self::VariableDeclaration(it) => it.serialize(serializer),
Self::FunctionDeclaration(it) => it.serialize(serializer),
Self::ClassDeclaration(it) => it.serialize(serializer),
Self::TSTypeAliasDeclaration(it) => it.serialize(serializer),
Self::TSInterfaceDeclaration(it) => it.serialize(serializer),
Self::TSEnumDeclaration(it) => it.serialize(serializer),
Self::TSModuleDeclaration(it) => it.serialize(serializer),
Self::TSGlobalDeclaration(it) => it.serialize(serializer),
Self::TSImportEqualsDeclaration(it) => it.serialize(serializer),
Self::ImportDeclaration(it) => it.serialize(serializer),
Self::ExportAllDeclaration(it) => it.serialize(serializer),
Self::ExportDefaultDeclaration(it) => it.serialize(serializer),
Self::ExportNamedDeclaration(it) => it.serialize(serializer),
Self::TSExportAssignment(it) => it.serialize(serializer),
Self::TSNamespaceExportDeclaration(it) => it.serialize(serializer),
Self::VariableDeclaration(_)
| Self::FunctionDeclaration(_)
| Self::ClassDeclaration(_)
| Self::TSTypeAliasDeclaration(_)
| Self::TSInterfaceDeclaration(_)
| Self::TSEnumDeclaration(_)
| Self::TSModuleDeclaration(_)
| Self::TSGlobalDeclaration(_)
| Self::TSImportEqualsDeclaration(_) => self.to_declaration().serialize(serializer),
Self::ImportDeclaration(_)
| Self::ExportAllDeclaration(_)
| Self::ExportDefaultDeclaration(_)
| Self::ExportNamedDeclaration(_)
| Self::TSExportAssignment(_)
| Self::TSNamespaceExportDeclaration(_) => {
self.to_module_declaration().serialize(serializer)
}
}
}
}
@@ -977,49 +982,49 @@ impl ESTree for ForStatementInit<'_> {
fn serialize<S: Serializer>(&self, serializer: S) {
match self {
Self::VariableDeclaration(it) => it.serialize(serializer),
Self::BooleanLiteral(it) => it.serialize(serializer),
Self::NullLiteral(it) => it.serialize(serializer),
Self::NumericLiteral(it) => it.serialize(serializer),
Self::BigIntLiteral(it) => it.serialize(serializer),
Self::RegExpLiteral(it) => it.serialize(serializer),
Self::StringLiteral(it) => it.serialize(serializer),
Self::TemplateLiteral(it) => it.serialize(serializer),
Self::Identifier(it) => it.serialize(serializer),
Self::MetaProperty(it) => it.serialize(serializer),
Self::Super(it) => it.serialize(serializer),
Self::ArrayExpression(it) => it.serialize(serializer),
Self::ArrowFunctionExpression(it) => it.serialize(serializer),
Self::AssignmentExpression(it) => it.serialize(serializer),
Self::AwaitExpression(it) => it.serialize(serializer),
Self::BinaryExpression(it) => it.serialize(serializer),
Self::CallExpression(it) => it.serialize(serializer),
Self::ChainExpression(it) => it.serialize(serializer),
Self::ClassExpression(it) => it.serialize(serializer),
Self::ConditionalExpression(it) => it.serialize(serializer),
Self::FunctionExpression(it) => it.serialize(serializer),
Self::ImportExpression(it) => it.serialize(serializer),
Self::LogicalExpression(it) => it.serialize(serializer),
Self::NewExpression(it) => it.serialize(serializer),
Self::ObjectExpression(it) => it.serialize(serializer),
Self::ParenthesizedExpression(it) => it.serialize(serializer),
Self::SequenceExpression(it) => it.serialize(serializer),
Self::TaggedTemplateExpression(it) => it.serialize(serializer),
Self::ThisExpression(it) => it.serialize(serializer),
Self::UnaryExpression(it) => it.serialize(serializer),
Self::UpdateExpression(it) => it.serialize(serializer),
Self::YieldExpression(it) => it.serialize(serializer),
Self::PrivateInExpression(it) => it.serialize(serializer),
Self::JSXElement(it) => it.serialize(serializer),
Self::JSXFragment(it) => it.serialize(serializer),
Self::TSAsExpression(it) => it.serialize(serializer),
Self::TSSatisfiesExpression(it) => it.serialize(serializer),
Self::TSTypeAssertion(it) => it.serialize(serializer),
Self::TSNonNullExpression(it) => it.serialize(serializer),
Self::TSInstantiationExpression(it) => it.serialize(serializer),
Self::V8IntrinsicExpression(it) => it.serialize(serializer),
Self::ComputedMemberExpression(it) => it.serialize(serializer),
Self::StaticMemberExpression(it) => it.serialize(serializer),
Self::PrivateFieldExpression(it) => it.serialize(serializer),
Self::BooleanLiteral(_)
| Self::NullLiteral(_)
| Self::NumericLiteral(_)
| Self::BigIntLiteral(_)
| Self::RegExpLiteral(_)
| Self::StringLiteral(_)
| Self::TemplateLiteral(_)
| Self::Identifier(_)
| Self::MetaProperty(_)
| Self::Super(_)
| Self::ArrayExpression(_)
| Self::ArrowFunctionExpression(_)
| Self::AssignmentExpression(_)
| Self::AwaitExpression(_)
| Self::BinaryExpression(_)
| Self::CallExpression(_)
| Self::ChainExpression(_)
| Self::ClassExpression(_)
| Self::ConditionalExpression(_)
| Self::FunctionExpression(_)
| Self::ImportExpression(_)
| Self::LogicalExpression(_)
| Self::NewExpression(_)
| Self::ObjectExpression(_)
| Self::ParenthesizedExpression(_)
| Self::SequenceExpression(_)
| Self::TaggedTemplateExpression(_)
| Self::ThisExpression(_)
| Self::UnaryExpression(_)
| Self::UpdateExpression(_)
| Self::YieldExpression(_)
| Self::PrivateInExpression(_)
| Self::JSXElement(_)
| Self::JSXFragment(_)
| Self::TSAsExpression(_)
| Self::TSSatisfiesExpression(_)
| Self::TSTypeAssertion(_)
| Self::TSNonNullExpression(_)
| Self::TSInstantiationExpression(_)
| Self::V8IntrinsicExpression(_)
| Self::ComputedMemberExpression(_)
| Self::StaticMemberExpression(_)
| Self::PrivateFieldExpression(_) => self.to_expression().serialize(serializer),
}
}
}
@@ -1040,16 +1045,16 @@ impl ESTree for ForStatementLeft<'_> {
fn serialize<S: Serializer>(&self, serializer: S) {
match self {
Self::VariableDeclaration(it) => it.serialize(serializer),
Self::AssignmentTargetIdentifier(it) => it.serialize(serializer),
Self::TSAsExpression(it) => it.serialize(serializer),
Self::TSSatisfiesExpression(it) => it.serialize(serializer),
Self::TSNonNullExpression(it) => it.serialize(serializer),
Self::TSTypeAssertion(it) => it.serialize(serializer),
Self::ComputedMemberExpression(it) => it.serialize(serializer),
Self::StaticMemberExpression(it) => it.serialize(serializer),
Self::PrivateFieldExpression(it) => it.serialize(serializer),
Self::ArrayAssignmentTarget(it) => it.serialize(serializer),
Self::ObjectAssignmentTarget(it) => it.serialize(serializer),
Self::AssignmentTargetIdentifier(_)
| Self::TSAsExpression(_)
| Self::TSSatisfiesExpression(_)
| Self::TSNonNullExpression(_)
| Self::TSTypeAssertion(_)
| Self::ComputedMemberExpression(_)
| Self::StaticMemberExpression(_)
| Self::PrivateFieldExpression(_)
| Self::ArrayAssignmentTarget(_)
| Self::ObjectAssignmentTarget(_) => self.to_assignment_target().serialize(serializer),
}
}
}
@@ -1736,49 +1741,49 @@ impl ESTree for ExportDefaultDeclarationKind<'_> {
Self::FunctionDeclaration(it) => it.serialize(serializer),
Self::ClassDeclaration(it) => it.serialize(serializer),
Self::TSInterfaceDeclaration(it) => it.serialize(serializer),
Self::BooleanLiteral(it) => it.serialize(serializer),
Self::NullLiteral(it) => it.serialize(serializer),
Self::NumericLiteral(it) => it.serialize(serializer),
Self::BigIntLiteral(it) => it.serialize(serializer),
Self::RegExpLiteral(it) => it.serialize(serializer),
Self::StringLiteral(it) => it.serialize(serializer),
Self::TemplateLiteral(it) => it.serialize(serializer),
Self::Identifier(it) => it.serialize(serializer),
Self::MetaProperty(it) => it.serialize(serializer),
Self::Super(it) => it.serialize(serializer),
Self::ArrayExpression(it) => it.serialize(serializer),
Self::ArrowFunctionExpression(it) => it.serialize(serializer),
Self::AssignmentExpression(it) => it.serialize(serializer),
Self::AwaitExpression(it) => it.serialize(serializer),
Self::BinaryExpression(it) => it.serialize(serializer),
Self::CallExpression(it) => it.serialize(serializer),
Self::ChainExpression(it) => it.serialize(serializer),
Self::ClassExpression(it) => it.serialize(serializer),
Self::ConditionalExpression(it) => it.serialize(serializer),
Self::FunctionExpression(it) => it.serialize(serializer),
Self::ImportExpression(it) => it.serialize(serializer),
Self::LogicalExpression(it) => it.serialize(serializer),
Self::NewExpression(it) => it.serialize(serializer),
Self::ObjectExpression(it) => it.serialize(serializer),
Self::ParenthesizedExpression(it) => it.serialize(serializer),
Self::SequenceExpression(it) => it.serialize(serializer),
Self::TaggedTemplateExpression(it) => it.serialize(serializer),
Self::ThisExpression(it) => it.serialize(serializer),
Self::UnaryExpression(it) => it.serialize(serializer),
Self::UpdateExpression(it) => it.serialize(serializer),
Self::YieldExpression(it) => it.serialize(serializer),
Self::PrivateInExpression(it) => it.serialize(serializer),
Self::JSXElement(it) => it.serialize(serializer),
Self::JSXFragment(it) => it.serialize(serializer),
Self::TSAsExpression(it) => it.serialize(serializer),
Self::TSSatisfiesExpression(it) => it.serialize(serializer),
Self::TSTypeAssertion(it) => it.serialize(serializer),
Self::TSNonNullExpression(it) => it.serialize(serializer),
Self::TSInstantiationExpression(it) => it.serialize(serializer),
Self::V8IntrinsicExpression(it) => it.serialize(serializer),
Self::ComputedMemberExpression(it) => it.serialize(serializer),
Self::StaticMemberExpression(it) => it.serialize(serializer),
Self::PrivateFieldExpression(it) => it.serialize(serializer),
Self::BooleanLiteral(_)
| Self::NullLiteral(_)
| Self::NumericLiteral(_)
| Self::BigIntLiteral(_)
| Self::RegExpLiteral(_)
| Self::StringLiteral(_)
| Self::TemplateLiteral(_)
| Self::Identifier(_)
| Self::MetaProperty(_)
| Self::Super(_)
| Self::ArrayExpression(_)
| Self::ArrowFunctionExpression(_)
| Self::AssignmentExpression(_)
| Self::AwaitExpression(_)
| Self::BinaryExpression(_)
| Self::CallExpression(_)
| Self::ChainExpression(_)
| Self::ClassExpression(_)
| Self::ConditionalExpression(_)
| Self::FunctionExpression(_)
| Self::ImportExpression(_)
| Self::LogicalExpression(_)
| Self::NewExpression(_)
| Self::ObjectExpression(_)
| Self::ParenthesizedExpression(_)
| Self::SequenceExpression(_)
| Self::TaggedTemplateExpression(_)
| Self::ThisExpression(_)
| Self::UnaryExpression(_)
| Self::UpdateExpression(_)
| Self::YieldExpression(_)
| Self::PrivateInExpression(_)
| Self::JSXElement(_)
| Self::JSXFragment(_)
| Self::TSAsExpression(_)
| Self::TSSatisfiesExpression(_)
| Self::TSTypeAssertion(_)
| Self::TSNonNullExpression(_)
| Self::TSInstantiationExpression(_)
| Self::V8IntrinsicExpression(_)
| Self::ComputedMemberExpression(_)
| Self::StaticMemberExpression(_)
| Self::PrivateFieldExpression(_) => self.to_expression().serialize(serializer),
}
}
}
@@ -2034,49 +2039,49 @@ impl ESTree for JSXExpression<'_> {
fn serialize<S: Serializer>(&self, serializer: S) {
match self {
Self::EmptyExpression(it) => it.serialize(serializer),
Self::BooleanLiteral(it) => it.serialize(serializer),
Self::NullLiteral(it) => it.serialize(serializer),
Self::NumericLiteral(it) => it.serialize(serializer),
Self::BigIntLiteral(it) => it.serialize(serializer),
Self::RegExpLiteral(it) => it.serialize(serializer),
Self::StringLiteral(it) => it.serialize(serializer),
Self::TemplateLiteral(it) => it.serialize(serializer),
Self::Identifier(it) => it.serialize(serializer),
Self::MetaProperty(it) => it.serialize(serializer),
Self::Super(it) => it.serialize(serializer),
Self::ArrayExpression(it) => it.serialize(serializer),
Self::ArrowFunctionExpression(it) => it.serialize(serializer),
Self::AssignmentExpression(it) => it.serialize(serializer),
Self::AwaitExpression(it) => it.serialize(serializer),
Self::BinaryExpression(it) => it.serialize(serializer),
Self::CallExpression(it) => it.serialize(serializer),
Self::ChainExpression(it) => it.serialize(serializer),
Self::ClassExpression(it) => it.serialize(serializer),
Self::ConditionalExpression(it) => it.serialize(serializer),
Self::FunctionExpression(it) => it.serialize(serializer),
Self::ImportExpression(it) => it.serialize(serializer),
Self::LogicalExpression(it) => it.serialize(serializer),
Self::NewExpression(it) => it.serialize(serializer),
Self::ObjectExpression(it) => it.serialize(serializer),
Self::ParenthesizedExpression(it) => it.serialize(serializer),
Self::SequenceExpression(it) => it.serialize(serializer),
Self::TaggedTemplateExpression(it) => it.serialize(serializer),
Self::ThisExpression(it) => it.serialize(serializer),
Self::UnaryExpression(it) => it.serialize(serializer),
Self::UpdateExpression(it) => it.serialize(serializer),
Self::YieldExpression(it) => it.serialize(serializer),
Self::PrivateInExpression(it) => it.serialize(serializer),
Self::JSXElement(it) => it.serialize(serializer),
Self::JSXFragment(it) => it.serialize(serializer),
Self::TSAsExpression(it) => it.serialize(serializer),
Self::TSSatisfiesExpression(it) => it.serialize(serializer),
Self::TSTypeAssertion(it) => it.serialize(serializer),
Self::TSNonNullExpression(it) => it.serialize(serializer),
Self::TSInstantiationExpression(it) => it.serialize(serializer),
Self::V8IntrinsicExpression(it) => it.serialize(serializer),
Self::ComputedMemberExpression(it) => it.serialize(serializer),
Self::StaticMemberExpression(it) => it.serialize(serializer),
Self::PrivateFieldExpression(it) => it.serialize(serializer),
Self::BooleanLiteral(_)
| Self::NullLiteral(_)
| Self::NumericLiteral(_)
| Self::BigIntLiteral(_)
| Self::RegExpLiteral(_)
| Self::StringLiteral(_)
| Self::TemplateLiteral(_)
| Self::Identifier(_)
| Self::MetaProperty(_)
| Self::Super(_)
| Self::ArrayExpression(_)
| Self::ArrowFunctionExpression(_)
| Self::AssignmentExpression(_)
| Self::AwaitExpression(_)
| Self::BinaryExpression(_)
| Self::CallExpression(_)
| Self::ChainExpression(_)
| Self::ClassExpression(_)
| Self::ConditionalExpression(_)
| Self::FunctionExpression(_)
| Self::ImportExpression(_)
| Self::LogicalExpression(_)
| Self::NewExpression(_)
| Self::ObjectExpression(_)
| Self::ParenthesizedExpression(_)
| Self::SequenceExpression(_)
| Self::TaggedTemplateExpression(_)
| Self::ThisExpression(_)
| Self::UnaryExpression(_)
| Self::UpdateExpression(_)
| Self::YieldExpression(_)
| Self::PrivateInExpression(_)
| Self::JSXElement(_)
| Self::JSXFragment(_)
| Self::TSAsExpression(_)
| Self::TSSatisfiesExpression(_)
| Self::TSTypeAssertion(_)
| Self::TSNonNullExpression(_)
| Self::TSInstantiationExpression(_)
| Self::V8IntrinsicExpression(_)
| Self::ComputedMemberExpression(_)
| Self::StaticMemberExpression(_)
| Self::PrivateFieldExpression(_) => self.to_expression().serialize(serializer),
}
}
}
@@ -2447,43 +2452,43 @@ impl ESTree for TSTupleElement<'_> {
match self {
Self::TSOptionalType(it) => it.serialize(serializer),
Self::TSRestType(it) => it.serialize(serializer),
Self::TSAnyKeyword(it) => it.serialize(serializer),
Self::TSBigIntKeyword(it) => it.serialize(serializer),
Self::TSBooleanKeyword(it) => it.serialize(serializer),
Self::TSIntrinsicKeyword(it) => it.serialize(serializer),
Self::TSNeverKeyword(it) => it.serialize(serializer),
Self::TSNullKeyword(it) => it.serialize(serializer),
Self::TSNumberKeyword(it) => it.serialize(serializer),
Self::TSObjectKeyword(it) => it.serialize(serializer),
Self::TSStringKeyword(it) => it.serialize(serializer),
Self::TSSymbolKeyword(it) => it.serialize(serializer),
Self::TSUndefinedKeyword(it) => it.serialize(serializer),
Self::TSUnknownKeyword(it) => it.serialize(serializer),
Self::TSVoidKeyword(it) => it.serialize(serializer),
Self::TSArrayType(it) => it.serialize(serializer),
Self::TSConditionalType(it) => it.serialize(serializer),
Self::TSConstructorType(it) => it.serialize(serializer),
Self::TSFunctionType(it) => it.serialize(serializer),
Self::TSImportType(it) => it.serialize(serializer),
Self::TSIndexedAccessType(it) => it.serialize(serializer),
Self::TSInferType(it) => it.serialize(serializer),
Self::TSIntersectionType(it) => it.serialize(serializer),
Self::TSLiteralType(it) => it.serialize(serializer),
Self::TSMappedType(it) => it.serialize(serializer),
Self::TSNamedTupleMember(it) => it.serialize(serializer),
Self::TSTemplateLiteralType(it) => it.serialize(serializer),
Self::TSThisType(it) => it.serialize(serializer),
Self::TSTupleType(it) => it.serialize(serializer),
Self::TSTypeLiteral(it) => it.serialize(serializer),
Self::TSTypeOperatorType(it) => it.serialize(serializer),
Self::TSTypePredicate(it) => it.serialize(serializer),
Self::TSTypeQuery(it) => it.serialize(serializer),
Self::TSTypeReference(it) => it.serialize(serializer),
Self::TSUnionType(it) => it.serialize(serializer),
Self::TSParenthesizedType(it) => it.serialize(serializer),
Self::JSDocNullableType(it) => it.serialize(serializer),
Self::JSDocNonNullableType(it) => it.serialize(serializer),
Self::JSDocUnknownType(it) => it.serialize(serializer),
Self::TSAnyKeyword(_)
| Self::TSBigIntKeyword(_)
| Self::TSBooleanKeyword(_)
| Self::TSIntrinsicKeyword(_)
| Self::TSNeverKeyword(_)
| Self::TSNullKeyword(_)
| Self::TSNumberKeyword(_)
| Self::TSObjectKeyword(_)
| Self::TSStringKeyword(_)
| Self::TSSymbolKeyword(_)
| Self::TSUndefinedKeyword(_)
| Self::TSUnknownKeyword(_)
| Self::TSVoidKeyword(_)
| Self::TSArrayType(_)
| Self::TSConditionalType(_)
| Self::TSConstructorType(_)
| Self::TSFunctionType(_)
| Self::TSImportType(_)
| Self::TSIndexedAccessType(_)
| Self::TSInferType(_)
| Self::TSIntersectionType(_)
| Self::TSLiteralType(_)
| Self::TSMappedType(_)
| Self::TSNamedTupleMember(_)
| Self::TSTemplateLiteralType(_)
| Self::TSThisType(_)
| Self::TSTupleType(_)
| Self::TSTypeLiteral(_)
| Self::TSTypeOperatorType(_)
| Self::TSTypePredicate(_)
| Self::TSTypeQuery(_)
| Self::TSTypeReference(_)
| Self::TSUnionType(_)
| Self::TSParenthesizedType(_)
| Self::JSDocNullableType(_)
| Self::JSDocNonNullableType(_)
| Self::JSDocUnknownType(_) => self.to_ts_type().serialize(serializer),
}
}
}
@@ -2977,9 +2982,9 @@ impl ESTree for TSTypeQueryExprName<'_> {
fn serialize<S: Serializer>(&self, serializer: S) {
match self {
Self::TSImportType(it) => it.serialize(serializer),
Self::IdentifierReference(it) => it.serialize(serializer),
Self::QualifiedName(it) => it.serialize(serializer),
Self::ThisExpression(it) => it.serialize(serializer),
Self::IdentifierReference(_) | Self::QualifiedName(_) | Self::ThisExpression(_) => {
self.to_ts_type_name().serialize(serializer)
}
}
}
}
+56 -29
View File
@@ -7,6 +7,7 @@ use syn::Ident;
use crate::{
Result,
schema::{Def, EnumDef, FieldDef, Schema, StructDef, TypeDef},
utils::create_ident,
};
use super::{
@@ -149,35 +150,10 @@ fn derive_enum(enum_def: &EnumDef, schema: &Schema) -> TokenStream {
let clone_in_body = quote!(*self);
(clone_in_body.clone(), clone_in_body)
} else {
let match_arms = enum_def.all_variants(schema).map(|variant| {
let ident = variant.ident();
if variant.is_fieldless() {
quote!( Self::#ident => #type_ident::#ident )
} else {
quote!( Self::#ident(it) => #type_ident::#ident(CloneIn::clone_in(it, allocator)) )
}
});
let clone_in_body = quote! {
match self {
#(#match_arms),*
}
};
let match_arms = enum_def.all_variants(schema).map(|variant| {
let ident = variant.ident();
if variant.is_fieldless() {
quote!( Self::#ident => #type_ident::#ident )
} else {
quote!( Self::#ident(it) => #type_ident::#ident(CloneIn::clone_in_with_semantic_ids(it, allocator)) )
}
});
let clone_in_with_semantic_ids_body = quote! {
match self {
#(#match_arms),*
}
};
(clone_in_body, clone_in_with_semantic_ids_body)
(
derive_enum_body(enum_def, &type_ident, schema, false),
derive_enum_body(enum_def, &type_ident, schema, true),
)
};
// Note: Add `#[inline(always)]` to methods for fieldless enums, because they're no-ops
@@ -190,6 +166,57 @@ fn derive_enum(enum_def: &EnumDef, schema: &Schema) -> TokenStream {
)
}
/// Generate the `match` body for an enum's `clone_in` / `clone_in_with_semantic_ids` method.
///
/// Own variants are cloned arm-by-arm. Variants inherited via `inherit_variants!` are *not*
/// expanded individually. Instead they are delegated to the inherited enum's own `CloneIn` impl,
/// using the `to_*` reference cast (narrow `&Self` to `&Inherited`) and the generated `From` impl
/// (widen the cloned `Inherited` back to `Self`). Both casts are zero-cost because the inherited
/// variants share discriminants and layout with the parent enum.
///
/// This avoids re-emitting the parent enum's variant arms (e.g. all of `Expression`'s ~30 variants)
/// in every inheriting enum (`Argument`, `PropertyKey`, ...), which is a large source of binary
/// bloat, and is behaviour-identical to expanding the arms inline.
fn derive_enum_body(
enum_def: &EnumDef,
type_ident: &Ident,
schema: &Schema,
with_semantic_ids: bool,
) -> TokenStream {
let clone_method =
if with_semantic_ids { quote!(clone_in_with_semantic_ids) } else { quote!(clone_in) };
let own_arms = enum_def.variants.iter().map(|variant| {
let ident = variant.ident();
if variant.is_fieldless() {
quote!( Self::#ident => #type_ident::#ident )
} else {
quote!( Self::#ident(it) => #type_ident::#ident(CloneIn::#clone_method(it, allocator)) )
}
});
let inherited_arms = enum_def.inherits.iter().map(|&inherits_id| {
let inherited = schema.enum_def(inherits_id);
let patterns = inherited.all_variants(schema).map(|variant| {
let ident = variant.ident();
if variant.is_fieldless() { quote!( Self::#ident ) } else { quote!( Self::#ident(_) ) }
});
let to_inherited = create_ident(&format!("to_{}", inherited.snake_name()));
quote! {
#(#patterns)|* => {
#type_ident::from(CloneIn::#clone_method(self.#to_inherited(), allocator))
}
}
});
quote! {
match self {
#(#own_arms,)*
#(#inherited_arms,)*
}
}
}
fn generate_impl(
type_ident: &Ident,
clone_in_body: &TokenStream,
+25 -3
View File
@@ -9,7 +9,7 @@ use crate::{
Result,
codegen::{Codegen, DeriveId},
schema::{Def, EnumDef, FieldDef, File, Schema, StructDef, TypeDef, VariantDef, Visibility},
utils::create_safe_ident,
utils::{create_ident, create_safe_ident},
};
use super::{
@@ -567,7 +567,7 @@ impl<'s> StructSerializerGenerator<'s> {
/// Generate body of `serialize` method for an enum.
fn generate_body_for_enum(enum_def: &EnumDef, schema: &Schema) -> TokenStream {
let match_branches = enum_def.all_variants(schema).map(|variant| {
let own_branches = enum_def.variants.iter().map(|variant| {
let variant_ident = variant.ident();
if should_skip_enum_variant(variant) {
@@ -605,9 +605,31 @@ fn generate_body_for_enum(enum_def: &EnumDef, schema: &Schema) -> TokenStream {
}
});
// Variants inherited via `inherit_variants!` are delegated to the inherited enum's `ESTree`
// impl through the generated `to_*` reference cast, instead of re-emitting an arm for each.
// Inherited variants carry the parent's serialization config, so this is byte-identical, and
// it avoids duplicating the parent enum's arms (e.g. all of `Expression`'s variants) in every
// inheriting enum (`Argument`, `PropertyKey`, ...).
let inherited_branches = enum_def.inherits.iter().map(|&inherits_id| {
let inherited = schema.enum_def(inherits_id);
let patterns = inherited.all_variants(schema).map(|variant| {
let variant_ident = variant.ident();
if variant.is_fieldless() {
quote!( Self::#variant_ident )
} else {
quote!( Self::#variant_ident(_) )
}
});
let to_inherited = create_ident(&format!("to_{}", inherited.snake_name()));
quote! {
#(#patterns)|* => self.#to_inherited().serialize(serializer),
}
});
quote! {
match self {
#(#match_branches)*
#(#own_branches)*
#(#inherited_branches)*
}
}
}