From 091b93a114f392f7cae1af3787ad80559361cb0c Mon Sep 17 00:00:00 2001 From: IWANABETHATGUY Date: Wed, 22 Jan 2025 17:12:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20update=20ast=20tools?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxc_allocator/src/clone_in.rs | 6 + crates/oxc_ast/src/ast/js.rs | 13 ++ .../oxc_ast/src/generated/derive_clone_in.rs | 214 ++++++++++++++++++ crates/oxc_semantic/src/symbol.rs | 4 +- tasks/ast_tools/src/derives/clone_in.rs | 71 ++++-- 5 files changed, 288 insertions(+), 20 deletions(-) diff --git a/crates/oxc_allocator/src/clone_in.rs b/crates/oxc_allocator/src/clone_in.rs index 0d85b405618e0..6274ae65c8643 100644 --- a/crates/oxc_allocator/src/clone_in.rs +++ b/crates/oxc_allocator/src/clone_in.rs @@ -28,6 +28,12 @@ pub trait CloneIn<'new_alloc>: Sized { /// Clone `self` into the given `allocator`. `allocator` may be the same one /// that `self` is already in. fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned; + + /// Almost same as `clone_in`, but for some special type, it will also clone the semantic ids. + #[inline] + fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { + self.clone_in(allocator) + } } impl<'alloc, T, C> CloneIn<'alloc> for Option diff --git a/crates/oxc_ast/src/ast/js.rs b/crates/oxc_ast/src/ast/js.rs index 5d54323e839c7..cdb06e507d41b 100644 --- a/crates/oxc_ast/src/ast/js.rs +++ b/crates/oxc_ast/src/ast/js.rs @@ -41,6 +41,7 @@ pub struct Program<'a> { pub directives: Vec<'a, Directive<'a>>, pub body: Vec<'a, Statement<'a>>, #[estree(skip)] + #[clone_in(default)] pub scope_id: Cell>, } @@ -226,6 +227,7 @@ pub struct IdentifierReference<'a> { /// set in the bind step of semantic analysis, and will always be [`None`] /// immediately after parsing. #[estree(skip)] + #[clone_in(default)] pub reference_id: Cell>, } @@ -249,6 +251,7 @@ pub struct BindingIdentifier<'a> { /// /// [`semantic analysis`]: #[estree(skip)] + #[clone_in(default)] pub symbol_id: Cell>, } @@ -1040,6 +1043,7 @@ pub struct BlockStatement<'a> { pub span: Span, pub body: Vec<'a, Statement<'a>>, #[estree(skip)] + #[clone_in(default)] pub scope_id: Cell>, } @@ -1183,6 +1187,7 @@ pub struct ForStatement<'a> { pub update: Option>, pub body: Statement<'a>, #[estree(skip)] + #[clone_in(default)] pub scope_id: Cell>, } @@ -1213,6 +1218,7 @@ pub struct ForInStatement<'a> { pub right: Expression<'a>, pub body: Statement<'a>, #[estree(skip)] + #[clone_in(default)] pub scope_id: Cell>, } @@ -1243,6 +1249,7 @@ pub struct ForOfStatement<'a> { pub right: Expression<'a>, pub body: Statement<'a>, #[estree(skip)] + #[clone_in(default)] pub scope_id: Cell>, } @@ -1294,6 +1301,7 @@ pub struct SwitchStatement<'a> { #[scope(enter_before)] pub cases: Vec<'a, SwitchCase<'a>>, #[estree(skip)] + #[clone_in(default)] pub scope_id: Cell>, } @@ -1383,6 +1391,7 @@ pub struct CatchClause<'a> { /// The statements run when an error is caught pub body: Box<'a, BlockStatement<'a>>, #[estree(skip)] + #[clone_in(default)] pub scope_id: Cell>, } @@ -1616,6 +1625,7 @@ pub struct Function<'a> { /// ``` pub body: Option>>, #[estree(skip)] + #[clone_in(default)] pub scope_id: Cell>, } @@ -1707,6 +1717,7 @@ pub struct ArrowFunctionExpression<'a> { /// See `expression` for whether this arrow expression returns an expression. pub body: Box<'a, FunctionBody<'a>>, #[estree(skip)] + #[clone_in(default)] pub scope_id: Cell>, } @@ -1793,6 +1804,7 @@ pub struct Class<'a> { /// Id of the scope created by the [`Class`], including type parameters and /// statements within the [`ClassBody`]. #[estree(skip)] + #[clone_in(default)] pub scope_id: Cell>, } @@ -2044,6 +2056,7 @@ pub struct StaticBlock<'a> { pub span: Span, pub body: Vec<'a, Statement<'a>>, #[estree(skip)] + #[clone_in(default)] pub scope_id: Cell>, } diff --git a/crates/oxc_ast/src/generated/derive_clone_in.rs b/crates/oxc_ast/src/generated/derive_clone_in.rs index 57f73ea9ce2de..0ac6bc9c89173 100644 --- a/crates/oxc_ast/src/generated/derive_clone_in.rs +++ b/crates/oxc_ast/src/generated/derive_clone_in.rs @@ -101,6 +101,18 @@ impl<'new_alloc> CloneIn<'new_alloc> for RegExpPattern<'_> { impl<'new_alloc> CloneIn<'new_alloc> for Program<'_> { type Cloned = Program<'new_alloc>; fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { + Program { + span: CloneIn::clone_in(&self.span, allocator), + source_type: CloneIn::clone_in(&self.source_type, allocator), + source_text: CloneIn::clone_in(&self.source_text, allocator), + comments: CloneIn::clone_in(&self.comments, allocator), + hashbang: CloneIn::clone_in(&self.hashbang, allocator), + directives: CloneIn::clone_in(&self.directives, allocator), + body: CloneIn::clone_in(&self.body, allocator), + scope_id: Default::default(), + } + } + fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { Program { span: CloneIn::clone_in(&self.span, allocator), source_type: CloneIn::clone_in(&self.source_type, allocator), @@ -241,6 +253,13 @@ impl<'new_alloc> CloneIn<'new_alloc> for IdentifierName<'_> { impl<'new_alloc> CloneIn<'new_alloc> for IdentifierReference<'_> { type Cloned = IdentifierReference<'new_alloc>; fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { + IdentifierReference { + span: CloneIn::clone_in(&self.span, allocator), + name: CloneIn::clone_in(&self.name, allocator), + reference_id: Default::default(), + } + } + fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { IdentifierReference { span: CloneIn::clone_in(&self.span, allocator), name: CloneIn::clone_in(&self.name, allocator), @@ -252,6 +271,13 @@ impl<'new_alloc> CloneIn<'new_alloc> for IdentifierReference<'_> { impl<'new_alloc> CloneIn<'new_alloc> for BindingIdentifier<'_> { type Cloned = BindingIdentifier<'new_alloc>; fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { + BindingIdentifier { + span: CloneIn::clone_in(&self.span, allocator), + name: CloneIn::clone_in(&self.name, allocator), + symbol_id: Default::default(), + } + } + fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { BindingIdentifier { span: CloneIn::clone_in(&self.span, allocator), name: CloneIn::clone_in(&self.name, allocator), @@ -1342,6 +1368,13 @@ impl<'new_alloc> CloneIn<'new_alloc> for Hashbang<'_> { impl<'new_alloc> CloneIn<'new_alloc> for BlockStatement<'_> { type Cloned = BlockStatement<'new_alloc>; fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { + BlockStatement { + span: CloneIn::clone_in(&self.span, allocator), + body: CloneIn::clone_in(&self.body, allocator), + scope_id: Default::default(), + } + } + fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { BlockStatement { span: CloneIn::clone_in(&self.span, allocator), body: CloneIn::clone_in(&self.body, allocator), @@ -1474,6 +1507,16 @@ impl<'new_alloc> CloneIn<'new_alloc> for WhileStatement<'_> { impl<'new_alloc> CloneIn<'new_alloc> for ForStatement<'_> { type Cloned = ForStatement<'new_alloc>; fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { + ForStatement { + span: CloneIn::clone_in(&self.span, allocator), + init: CloneIn::clone_in(&self.init, allocator), + test: CloneIn::clone_in(&self.test, allocator), + update: CloneIn::clone_in(&self.update, allocator), + body: CloneIn::clone_in(&self.body, allocator), + scope_id: Default::default(), + } + } + fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { ForStatement { span: CloneIn::clone_in(&self.span, allocator), init: CloneIn::clone_in(&self.init, allocator), @@ -1619,6 +1662,15 @@ impl<'new_alloc> CloneIn<'new_alloc> for ForStatementInit<'_> { impl<'new_alloc> CloneIn<'new_alloc> for ForInStatement<'_> { type Cloned = ForInStatement<'new_alloc>; fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { + ForInStatement { + span: CloneIn::clone_in(&self.span, allocator), + left: CloneIn::clone_in(&self.left, allocator), + right: CloneIn::clone_in(&self.right, allocator), + body: CloneIn::clone_in(&self.body, allocator), + scope_id: Default::default(), + } + } + fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { ForInStatement { span: CloneIn::clone_in(&self.span, allocator), left: CloneIn::clone_in(&self.left, allocator), @@ -1676,6 +1728,16 @@ impl<'new_alloc> CloneIn<'new_alloc> for ForStatementLeft<'_> { impl<'new_alloc> CloneIn<'new_alloc> for ForOfStatement<'_> { type Cloned = ForOfStatement<'new_alloc>; fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { + ForOfStatement { + span: CloneIn::clone_in(&self.span, allocator), + r#await: CloneIn::clone_in(&self.r#await, allocator), + left: CloneIn::clone_in(&self.left, allocator), + right: CloneIn::clone_in(&self.right, allocator), + body: CloneIn::clone_in(&self.body, allocator), + scope_id: Default::default(), + } + } + fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { ForOfStatement { span: CloneIn::clone_in(&self.span, allocator), r#await: CloneIn::clone_in(&self.r#await, allocator), @@ -1731,6 +1793,14 @@ impl<'new_alloc> CloneIn<'new_alloc> for WithStatement<'_> { impl<'new_alloc> CloneIn<'new_alloc> for SwitchStatement<'_> { type Cloned = SwitchStatement<'new_alloc>; fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { + SwitchStatement { + span: CloneIn::clone_in(&self.span, allocator), + discriminant: CloneIn::clone_in(&self.discriminant, allocator), + cases: CloneIn::clone_in(&self.cases, allocator), + scope_id: Default::default(), + } + } + fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { SwitchStatement { span: CloneIn::clone_in(&self.span, allocator), discriminant: CloneIn::clone_in(&self.discriminant, allocator), @@ -1787,6 +1857,14 @@ impl<'new_alloc> CloneIn<'new_alloc> for TryStatement<'_> { impl<'new_alloc> CloneIn<'new_alloc> for CatchClause<'_> { type Cloned = CatchClause<'new_alloc>; fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { + CatchClause { + span: CloneIn::clone_in(&self.span, allocator), + param: CloneIn::clone_in(&self.param, allocator), + body: CloneIn::clone_in(&self.body, allocator), + scope_id: Default::default(), + } + } + fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { CatchClause { span: CloneIn::clone_in(&self.span, allocator), param: CloneIn::clone_in(&self.param, allocator), @@ -1903,6 +1981,22 @@ impl<'new_alloc> CloneIn<'new_alloc> for BindingRestElement<'_> { impl<'new_alloc> CloneIn<'new_alloc> for Function<'_> { type Cloned = Function<'new_alloc>; fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { + Function { + span: CloneIn::clone_in(&self.span, allocator), + r#type: CloneIn::clone_in(&self.r#type, allocator), + id: CloneIn::clone_in(&self.id, allocator), + generator: CloneIn::clone_in(&self.generator, allocator), + r#async: CloneIn::clone_in(&self.r#async, allocator), + declare: CloneIn::clone_in(&self.declare, allocator), + type_parameters: CloneIn::clone_in(&self.type_parameters, allocator), + this_param: CloneIn::clone_in(&self.this_param, allocator), + params: CloneIn::clone_in(&self.params, allocator), + return_type: CloneIn::clone_in(&self.return_type, allocator), + body: CloneIn::clone_in(&self.body, allocator), + scope_id: Default::default(), + } + } + fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { Function { span: CloneIn::clone_in(&self.span, allocator), r#type: CloneIn::clone_in(&self.r#type, allocator), @@ -1984,6 +2078,18 @@ impl<'new_alloc> CloneIn<'new_alloc> for FunctionBody<'_> { impl<'new_alloc> CloneIn<'new_alloc> for ArrowFunctionExpression<'_> { type Cloned = ArrowFunctionExpression<'new_alloc>; fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { + ArrowFunctionExpression { + span: CloneIn::clone_in(&self.span, allocator), + expression: CloneIn::clone_in(&self.expression, allocator), + r#async: CloneIn::clone_in(&self.r#async, allocator), + type_parameters: CloneIn::clone_in(&self.type_parameters, allocator), + params: CloneIn::clone_in(&self.params, allocator), + return_type: CloneIn::clone_in(&self.return_type, allocator), + body: CloneIn::clone_in(&self.body, allocator), + scope_id: Default::default(), + } + } + fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { ArrowFunctionExpression { span: CloneIn::clone_in(&self.span, allocator), expression: CloneIn::clone_in(&self.expression, allocator), @@ -2011,6 +2117,22 @@ impl<'new_alloc> CloneIn<'new_alloc> for YieldExpression<'_> { impl<'new_alloc> CloneIn<'new_alloc> for Class<'_> { type Cloned = Class<'new_alloc>; fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { + Class { + span: CloneIn::clone_in(&self.span, allocator), + r#type: CloneIn::clone_in(&self.r#type, allocator), + decorators: CloneIn::clone_in(&self.decorators, allocator), + id: CloneIn::clone_in(&self.id, allocator), + type_parameters: CloneIn::clone_in(&self.type_parameters, allocator), + super_class: CloneIn::clone_in(&self.super_class, allocator), + super_type_parameters: CloneIn::clone_in(&self.super_type_parameters, allocator), + implements: CloneIn::clone_in(&self.implements, allocator), + body: CloneIn::clone_in(&self.body, allocator), + r#abstract: CloneIn::clone_in(&self.r#abstract, allocator), + declare: CloneIn::clone_in(&self.declare, allocator), + scope_id: Default::default(), + } + } + fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { Class { span: CloneIn::clone_in(&self.span, allocator), r#type: CloneIn::clone_in(&self.r#type, allocator), @@ -2157,6 +2279,13 @@ impl<'new_alloc> CloneIn<'new_alloc> for PrivateIdentifier<'_> { impl<'new_alloc> CloneIn<'new_alloc> for StaticBlock<'_> { type Cloned = StaticBlock<'new_alloc>; fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { + StaticBlock { + span: CloneIn::clone_in(&self.span, allocator), + body: CloneIn::clone_in(&self.body, allocator), + scope_id: Default::default(), + } + } + fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { StaticBlock { span: CloneIn::clone_in(&self.span, allocator), body: CloneIn::clone_in(&self.body, allocator), @@ -2591,6 +2720,16 @@ impl<'new_alloc> CloneIn<'new_alloc> for TSEnumDeclaration<'_> { scope_id: Default::default(), } } + fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { + TSEnumDeclaration { + span: CloneIn::clone_in(&self.span, allocator), + id: CloneIn::clone_in(&self.id, allocator), + members: CloneIn::clone_in(&self.members, allocator), + r#const: CloneIn::clone_in(&self.r#const, allocator), + declare: CloneIn::clone_in(&self.declare, allocator), + scope_id: CloneIn::clone_in(&self.scope_id, allocator), + } + } } impl<'new_alloc> CloneIn<'new_alloc> for TSEnumMember<'_> { @@ -2742,6 +2881,16 @@ impl<'new_alloc> CloneIn<'new_alloc> for TSConditionalType<'_> { scope_id: Default::default(), } } + fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { + TSConditionalType { + span: CloneIn::clone_in(&self.span, allocator), + check_type: CloneIn::clone_in(&self.check_type, allocator), + extends_type: CloneIn::clone_in(&self.extends_type, allocator), + true_type: CloneIn::clone_in(&self.true_type, allocator), + false_type: CloneIn::clone_in(&self.false_type, allocator), + scope_id: CloneIn::clone_in(&self.scope_id, allocator), + } + } } impl<'new_alloc> CloneIn<'new_alloc> for TSUnionType<'_> { @@ -3152,6 +3301,16 @@ impl<'new_alloc> CloneIn<'new_alloc> for TSTypeAliasDeclaration<'_> { scope_id: Default::default(), } } + fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { + TSTypeAliasDeclaration { + span: CloneIn::clone_in(&self.span, allocator), + id: CloneIn::clone_in(&self.id, allocator), + type_parameters: CloneIn::clone_in(&self.type_parameters, allocator), + type_annotation: CloneIn::clone_in(&self.type_annotation, allocator), + declare: CloneIn::clone_in(&self.declare, allocator), + scope_id: CloneIn::clone_in(&self.scope_id, allocator), + } + } } impl<'alloc> CloneIn<'alloc> for TSAccessibility { @@ -3189,6 +3348,17 @@ impl<'new_alloc> CloneIn<'new_alloc> for TSInterfaceDeclaration<'_> { scope_id: Default::default(), } } + fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { + TSInterfaceDeclaration { + span: CloneIn::clone_in(&self.span, allocator), + id: CloneIn::clone_in(&self.id, allocator), + extends: CloneIn::clone_in(&self.extends, allocator), + type_parameters: CloneIn::clone_in(&self.type_parameters, allocator), + body: CloneIn::clone_in(&self.body, allocator), + declare: CloneIn::clone_in(&self.declare, allocator), + scope_id: CloneIn::clone_in(&self.scope_id, allocator), + } + } } impl<'new_alloc> CloneIn<'new_alloc> for TSInterfaceBody<'_> { @@ -3291,6 +3461,20 @@ impl<'new_alloc> CloneIn<'new_alloc> for TSMethodSignature<'_> { scope_id: Default::default(), } } + fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { + TSMethodSignature { + span: CloneIn::clone_in(&self.span, allocator), + key: CloneIn::clone_in(&self.key, allocator), + computed: CloneIn::clone_in(&self.computed, allocator), + optional: CloneIn::clone_in(&self.optional, allocator), + kind: CloneIn::clone_in(&self.kind, allocator), + type_parameters: CloneIn::clone_in(&self.type_parameters, allocator), + this_param: CloneIn::clone_in(&self.this_param, allocator), + params: CloneIn::clone_in(&self.params, allocator), + return_type: CloneIn::clone_in(&self.return_type, allocator), + scope_id: CloneIn::clone_in(&self.scope_id, allocator), + } + } } impl<'new_alloc> CloneIn<'new_alloc> for TSConstructSignatureDeclaration<'_> { @@ -3304,6 +3488,15 @@ impl<'new_alloc> CloneIn<'new_alloc> for TSConstructSignatureDeclaration<'_> { scope_id: Default::default(), } } + fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { + TSConstructSignatureDeclaration { + span: CloneIn::clone_in(&self.span, allocator), + type_parameters: CloneIn::clone_in(&self.type_parameters, allocator), + params: CloneIn::clone_in(&self.params, allocator), + return_type: CloneIn::clone_in(&self.return_type, allocator), + scope_id: CloneIn::clone_in(&self.scope_id, allocator), + } + } } impl<'new_alloc> CloneIn<'new_alloc> for TSIndexSignatureName<'_> { @@ -3364,6 +3557,16 @@ impl<'new_alloc> CloneIn<'new_alloc> for TSModuleDeclaration<'_> { scope_id: Default::default(), } } + fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { + TSModuleDeclaration { + span: CloneIn::clone_in(&self.span, allocator), + id: CloneIn::clone_in(&self.id, allocator), + body: CloneIn::clone_in(&self.body, allocator), + kind: CloneIn::clone_in(&self.kind, allocator), + declare: CloneIn::clone_in(&self.declare, allocator), + scope_id: CloneIn::clone_in(&self.scope_id, allocator), + } + } } impl<'alloc> CloneIn<'alloc> for TSModuleDeclarationKind { @@ -3553,6 +3756,17 @@ impl<'new_alloc> CloneIn<'new_alloc> for TSMappedType<'_> { scope_id: Default::default(), } } + fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { + TSMappedType { + span: CloneIn::clone_in(&self.span, allocator), + type_parameter: CloneIn::clone_in(&self.type_parameter, allocator), + name_type: CloneIn::clone_in(&self.name_type, allocator), + type_annotation: CloneIn::clone_in(&self.type_annotation, allocator), + optional: CloneIn::clone_in(&self.optional, allocator), + readonly: CloneIn::clone_in(&self.readonly, allocator), + scope_id: CloneIn::clone_in(&self.scope_id, allocator), + } + } } impl<'alloc> CloneIn<'alloc> for TSMappedTypeModifierOperator { diff --git a/crates/oxc_semantic/src/symbol.rs b/crates/oxc_semantic/src/symbol.rs index 2575e01c6b40f..ce88a2c100d2f 100644 --- a/crates/oxc_semantic/src/symbol.rs +++ b/crates/oxc_semantic/src/symbol.rs @@ -326,9 +326,7 @@ impl SymbolTable { /// use another `Allocator` to avoid memory leak #[must_use] pub fn clone_with_another_arena(&self) -> SymbolTable { - let allocator = self.inner.with_dependent(|alloc, _| { - Allocator::with_capacity(alloc.allocated_bytes_including_metadata()) - }); + let allocator = self.inner.with_dependent(|alloc, _| Allocator::with_capacity(0)); Self { spans: self.spans.clone(), flags: self.flags.clone(), diff --git a/tasks/ast_tools/src/derives/clone_in.rs b/tasks/ast_tools/src/derives/clone_in.rs index 48e6b20669c9b..3faef87d04ed2 100644 --- a/tasks/ast_tools/src/derives/clone_in.rs +++ b/tasks/ast_tools/src/derives/clone_in.rs @@ -1,3 +1,5 @@ +use std::cell::Cell; + use itertools::Itertools; use proc_macro2::TokenStream; use quote::{format_ident, quote}; @@ -60,43 +62,76 @@ fn derive_enum(def: &EnumDef) -> TokenStream { } }; - impl_clone_in(&ty_ident, def.has_lifetime, &alloc_ident, &body) + impl_clone_in(&ty_ident, def.has_lifetime, &alloc_ident, &body, "e!()) } fn derive_struct(def: &StructDef) -> TokenStream { let ty_ident = def.ident(); - - let (alloc_ident, body) = if def.fields.is_empty() { - (format_ident!("_"), quote!(#ty_ident)) + let needs_override_clone_in_with_semantic_ids = Cell::new(false); + let (alloc_ident, clone_in_body, clone_in_with_semantic_ids_body) = if def.fields.is_empty() { + (format_ident!("_"), quote!(#ty_ident), quote!()) } else { - let fields = def.fields.iter().map(|field| { - let ident = field.ident(); - match field.markers.derive_attributes.clone_in { - CloneInAttribute::Default => quote!(#ident: Default::default()), - CloneInAttribute::None => { - quote!(#ident: CloneIn::clone_in(&self.#ident, allocator)) + let alloc_ident = format_ident!("allocator"); + let fields = def + .fields + .iter() + .map(|field| { + let ident = field.ident(); + match field.markers.derive_attributes.clone_in { + CloneInAttribute::Default => { + needs_override_clone_in_with_semantic_ids.set(true); + quote!(#ident: Default::default()) + } + CloneInAttribute::None => { + quote!(#ident: CloneIn::clone_in(&self.#ident, allocator)) + } } - } - }); - (format_ident!("allocator"), quote!(#ty_ident { #(#fields),* })) + }) + .collect::>() + .into_iter(); + let clone_in_with_semantic_ids_token_stream = if needs_override_clone_in_with_semantic_ids + .get() + { + let fields = def.fields.iter().map(|field| { + let ident = field.ident(); + quote!(#ident: CloneIn::clone_in(&self.#ident, allocator)) + }); + quote!( + fn clone_in_with_semantic_ids(&self, #alloc_ident: &'new_alloc Allocator) -> Self::Cloned { + #ty_ident { #(#fields),* } + } + ) + } else { + quote!() + }; + (alloc_ident, quote!(#ty_ident { #(#fields),* }), clone_in_with_semantic_ids_token_stream) }; - impl_clone_in(&ty_ident, def.has_lifetime, &alloc_ident, &body) + impl_clone_in( + &ty_ident, + def.has_lifetime, + &alloc_ident, + &clone_in_body, + &clone_in_with_semantic_ids_body, + ) } fn impl_clone_in( ty_ident: &Ident, has_lifetime: bool, alloc_ident: &Ident, - body: &TokenStream, + clone_in_body: &TokenStream, + clone_in_with_semantic_ids_body: &TokenStream, ) -> TokenStream { if has_lifetime { quote! { impl <'new_alloc> CloneIn<'new_alloc> for #ty_ident<'_> { type Cloned = #ty_ident<'new_alloc>; fn clone_in(&self, #alloc_ident: &'new_alloc Allocator) -> Self::Cloned { - #body + #clone_in_body } + + #clone_in_with_semantic_ids_body } } } else { @@ -104,8 +139,10 @@ fn impl_clone_in( impl <'alloc> CloneIn<'alloc> for #ty_ident { type Cloned = #ty_ident; fn clone_in(&self, #alloc_ident: &'alloc Allocator) -> Self::Cloned { - #body + #clone_in_body } + + #clone_in_with_semantic_ids_body } } }