From 3fc043ce9b6bd5b802af95c3dc50816a581293bc Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 3 Jan 2024 14:55:39 +0100 Subject: [PATCH] internal: Remove unnecessary Arc allocations in `macro_expand` --- crates/hir-expand/src/db.rs | 48 ++++++++++++++++++++++---------- editors/code/src/config.ts | 1 + editors/code/src/ctx.ts | 1 + editors/code/src/main.ts | 1 + editors/code/src/rust_project.ts | 6 ++-- editors/code/tsconfig.json | 2 +- 6 files changed, 40 insertions(+), 19 deletions(-) diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs index f7a26e436dee..ed04582cb0ab 100644 --- a/crates/hir-expand/src/db.rs +++ b/crates/hir-expand/src/db.rs @@ -390,7 +390,13 @@ fn parse_macro_expansion( let expand_to = loc.expand_to(); let mbe::ValueResult { value: tt, err } = macro_expand(db, macro_file.macro_call_id, loc); - let (parse, rev_token_map) = token_tree_to_syntax_node(&tt, expand_to); + let (parse, rev_token_map) = token_tree_to_syntax_node( + match &tt { + CowArc::Arc(it) => it, + CowArc::Owned(it) => it, + }, + expand_to, + ); ExpandResult { value: (parse, Arc::new(rev_token_map)), err } } @@ -669,15 +675,20 @@ fn macro_expander(db: &dyn ExpandDatabase, id: MacroDefId) -> TokenExpander { } } +enum CowArc { + Arc(Arc), + Owned(T), +} + fn macro_expand( db: &dyn ExpandDatabase, macro_call_id: MacroCallId, loc: MacroCallLoc, -) -> ExpandResult> { +) -> ExpandResult> { let _p = profile::span("macro_expand"); let ExpandResult { value: tt, mut err } = match loc.def.kind { - MacroDefKind::ProcMacro(..) => return db.expand_proc_macro(macro_call_id), + MacroDefKind::ProcMacro(..) => return db.expand_proc_macro(macro_call_id).map(CowArc::Arc), MacroDefKind::BuiltInDerive(expander, ..) => { let (root, map) = parse_with_map(db, loc.kind.file_id()); let root = root.syntax_node(); @@ -692,7 +703,7 @@ fn macro_expand( let ValueResult { value, err } = db.macro_arg(macro_call_id); let Some((macro_arg, undo_info)) = value else { return ExpandResult { - value: Arc::new(tt::Subtree { + value: CowArc::Owned(tt::Subtree { delimiter: tt::Delimiter::invisible_spanned(loc.call_site), token_trees: Vec::new(), }), @@ -718,7 +729,7 @@ fn macro_expand( // As such we just return the input subtree here. MacroDefKind::BuiltInEager(..) if loc.eager.is_none() => { return ExpandResult { - value: macro_arg.clone(), + value: CowArc::Arc(macro_arg.clone()), err: err.map(|err| { let mut buf = String::new(); for err in &**err { @@ -752,12 +763,17 @@ fn macro_expand( // Skip checking token tree limit for include! macro call if !loc.def.is_include() { // Set a hard limit for the expanded tt - if let Err(value) = check_tt_count(&tt, loc.call_site) { - return value; + if let Err(value) = check_tt_count(&tt) { + return value.map(|()| { + CowArc::Owned(tt::Subtree { + delimiter: tt::Delimiter::invisible_spanned(loc.call_site), + token_trees: vec![], + }) + }); } } - ExpandResult { value: Arc::new(tt), err } + ExpandResult { value: CowArc::Owned(tt), err } } fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult> { @@ -796,8 +812,13 @@ fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult Result<(), ExpandResult>> { +fn check_tt_count(tt: &tt::Subtree) -> Result<(), ExpandResult<()>> { let count = tt.count(); if TOKEN_LIMIT.check(count).is_err() { Err(ExpandResult { - value: Arc::new(tt::Subtree { - delimiter: tt::Delimiter::invisible_spanned(call_site), - token_trees: vec![], - }), + value: (), err: Some(ExpandError::other(format!( "macro invocation exceeds token limit: produced {} tokens, limit is {}", count, diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 987d936943a1..51a0aece820e 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -5,6 +5,7 @@ import * as vscode from "vscode"; import type { Env } from "./client"; import { log } from "./util"; import { expectNotUndefined, unwrapUndefinable } from "./undefinable"; +import type { JsonProject } from "./rust_project"; export type RunnableEnvCfgItem = { mask?: string; diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index 63ae386c8ad1..55163241c2ac 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -23,6 +23,7 @@ import { execRevealDependency } from "./commands"; import { PersistentState } from "./persistent_state"; import { bootstrap } from "./bootstrap"; import type { RustAnalyzerExtensionApi } from "./main"; +import type { JsonProject } from "./rust_project"; // We only support local folders, not eg. Live Share (`vlsl:` scheme), so don't activate if // only those are in use. We use "Empty" to represent these scenarios diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 3073353674ce..599cfb4ff77a 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts @@ -6,6 +6,7 @@ import { type CommandFactory, Ctx, fetchWorkspace } from "./ctx"; import * as diagnostics from "./diagnostics"; import { activateTaskProvider } from "./tasks"; import { setContextValue } from "./util"; +import type { JsonProject } from "./rust_project"; const RUST_PROJECT_CONTEXT_NAME = "inRustProject"; diff --git a/editors/code/src/rust_project.ts b/editors/code/src/rust_project.ts index 187a1a96c10c..bf65ad43ba59 100644 --- a/editors/code/src/rust_project.ts +++ b/editors/code/src/rust_project.ts @@ -1,4 +1,4 @@ -interface JsonProject { +export interface JsonProject { /// Path to the directory with *source code* of /// sysroot crates. /// @@ -21,7 +21,7 @@ interface JsonProject { crates: Crate[]; } -interface Crate { +export interface Crate { /// Optional crate name used for display purposes, /// without affecting semantics. See the `deps` /// key for semantically-significant crate names. @@ -82,7 +82,7 @@ interface Crate { proc_macro_dylib_path?: string; } -interface Dep { +export interface Dep { /// Index of a crate in the `crates` array. crate: number; /// Name as should appear in the (implicit) diff --git a/editors/code/tsconfig.json b/editors/code/tsconfig.json index c74284a00d96..87cfd1b2ee11 100644 --- a/editors/code/tsconfig.json +++ b/editors/code/tsconfig.json @@ -2,7 +2,7 @@ "extends": "@tsconfig/strictest/tsconfig.json", "compilerOptions": { "esModuleInterop": false, - "module": "CommonJS", + "module": "Node16", "moduleResolution": "Node16", "target": "ES2021", "outDir": "out",