mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 13:33:31 +00:00
Auto merge of #16237 - Veykril:expand-arc-alloc, r=Veykril
internal: Remove unnecessary `Arc` allocations in `macro_expand`
This commit is contained in:
commit
9279c6566b
6 changed files with 40 additions and 19 deletions
|
@ -390,7 +390,13 @@ fn parse_macro_expansion(
|
||||||
let expand_to = loc.expand_to();
|
let expand_to = loc.expand_to();
|
||||||
let mbe::ValueResult { value: tt, err } = macro_expand(db, macro_file.macro_call_id, loc);
|
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 }
|
ExpandResult { value: (parse, Arc::new(rev_token_map)), err }
|
||||||
}
|
}
|
||||||
|
@ -669,15 +675,20 @@ fn macro_expander(db: &dyn ExpandDatabase, id: MacroDefId) -> TokenExpander {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum CowArc<T> {
|
||||||
|
Arc(Arc<T>),
|
||||||
|
Owned(T),
|
||||||
|
}
|
||||||
|
|
||||||
fn macro_expand(
|
fn macro_expand(
|
||||||
db: &dyn ExpandDatabase,
|
db: &dyn ExpandDatabase,
|
||||||
macro_call_id: MacroCallId,
|
macro_call_id: MacroCallId,
|
||||||
loc: MacroCallLoc,
|
loc: MacroCallLoc,
|
||||||
) -> ExpandResult<Arc<tt::Subtree>> {
|
) -> ExpandResult<CowArc<tt::Subtree>> {
|
||||||
let _p = profile::span("macro_expand");
|
let _p = profile::span("macro_expand");
|
||||||
|
|
||||||
let ExpandResult { value: tt, mut err } = match loc.def.kind {
|
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, ..) => {
|
MacroDefKind::BuiltInDerive(expander, ..) => {
|
||||||
let (root, map) = parse_with_map(db, loc.kind.file_id());
|
let (root, map) = parse_with_map(db, loc.kind.file_id());
|
||||||
let root = root.syntax_node();
|
let root = root.syntax_node();
|
||||||
|
@ -692,7 +703,7 @@ fn macro_expand(
|
||||||
let ValueResult { value, err } = db.macro_arg(macro_call_id);
|
let ValueResult { value, err } = db.macro_arg(macro_call_id);
|
||||||
let Some((macro_arg, undo_info)) = value else {
|
let Some((macro_arg, undo_info)) = value else {
|
||||||
return ExpandResult {
|
return ExpandResult {
|
||||||
value: Arc::new(tt::Subtree {
|
value: CowArc::Owned(tt::Subtree {
|
||||||
delimiter: tt::Delimiter::invisible_spanned(loc.call_site),
|
delimiter: tt::Delimiter::invisible_spanned(loc.call_site),
|
||||||
token_trees: Vec::new(),
|
token_trees: Vec::new(),
|
||||||
}),
|
}),
|
||||||
|
@ -718,7 +729,7 @@ fn macro_expand(
|
||||||
// As such we just return the input subtree here.
|
// As such we just return the input subtree here.
|
||||||
MacroDefKind::BuiltInEager(..) if loc.eager.is_none() => {
|
MacroDefKind::BuiltInEager(..) if loc.eager.is_none() => {
|
||||||
return ExpandResult {
|
return ExpandResult {
|
||||||
value: macro_arg.clone(),
|
value: CowArc::Arc(macro_arg.clone()),
|
||||||
err: err.map(|err| {
|
err: err.map(|err| {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
for err in &**err {
|
for err in &**err {
|
||||||
|
@ -752,12 +763,17 @@ fn macro_expand(
|
||||||
// Skip checking token tree limit for include! macro call
|
// Skip checking token tree limit for include! macro call
|
||||||
if !loc.def.is_include() {
|
if !loc.def.is_include() {
|
||||||
// Set a hard limit for the expanded tt
|
// Set a hard limit for the expanded tt
|
||||||
if let Err(value) = check_tt_count(&tt, loc.call_site) {
|
if let Err(value) = check_tt_count(&tt) {
|
||||||
return value;
|
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<Arc<tt::Subtree>> {
|
fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt::Subtree>> {
|
||||||
|
@ -796,8 +812,13 @@ fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<A
|
||||||
);
|
);
|
||||||
|
|
||||||
// Set a hard limit for the expanded tt
|
// Set a hard limit for the expanded tt
|
||||||
if let Err(value) = check_tt_count(&tt, loc.call_site) {
|
if let Err(value) = check_tt_count(&tt) {
|
||||||
return value;
|
return value.map(|()| {
|
||||||
|
Arc::new(tt::Subtree {
|
||||||
|
delimiter: tt::Delimiter::invisible_spanned(loc.call_site),
|
||||||
|
token_trees: vec![],
|
||||||
|
})
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fixup::reverse_fixups(&mut tt, &undo_info);
|
fixup::reverse_fixups(&mut tt, &undo_info);
|
||||||
|
@ -819,14 +840,11 @@ fn token_tree_to_syntax_node(
|
||||||
mbe::token_tree_to_syntax_node(tt, entry_point)
|
mbe::token_tree_to_syntax_node(tt, entry_point)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_tt_count(tt: &tt::Subtree, call_site: Span) -> Result<(), ExpandResult<Arc<tt::Subtree>>> {
|
fn check_tt_count(tt: &tt::Subtree) -> Result<(), ExpandResult<()>> {
|
||||||
let count = tt.count();
|
let count = tt.count();
|
||||||
if TOKEN_LIMIT.check(count).is_err() {
|
if TOKEN_LIMIT.check(count).is_err() {
|
||||||
Err(ExpandResult {
|
Err(ExpandResult {
|
||||||
value: Arc::new(tt::Subtree {
|
value: (),
|
||||||
delimiter: tt::Delimiter::invisible_spanned(call_site),
|
|
||||||
token_trees: vec![],
|
|
||||||
}),
|
|
||||||
err: Some(ExpandError::other(format!(
|
err: Some(ExpandError::other(format!(
|
||||||
"macro invocation exceeds token limit: produced {} tokens, limit is {}",
|
"macro invocation exceeds token limit: produced {} tokens, limit is {}",
|
||||||
count,
|
count,
|
||||||
|
|
|
@ -5,6 +5,7 @@ import * as vscode from "vscode";
|
||||||
import type { Env } from "./client";
|
import type { Env } from "./client";
|
||||||
import { log } from "./util";
|
import { log } from "./util";
|
||||||
import { expectNotUndefined, unwrapUndefinable } from "./undefinable";
|
import { expectNotUndefined, unwrapUndefinable } from "./undefinable";
|
||||||
|
import type { JsonProject } from "./rust_project";
|
||||||
|
|
||||||
export type RunnableEnvCfgItem = {
|
export type RunnableEnvCfgItem = {
|
||||||
mask?: string;
|
mask?: string;
|
||||||
|
|
|
@ -23,6 +23,7 @@ import { execRevealDependency } from "./commands";
|
||||||
import { PersistentState } from "./persistent_state";
|
import { PersistentState } from "./persistent_state";
|
||||||
import { bootstrap } from "./bootstrap";
|
import { bootstrap } from "./bootstrap";
|
||||||
import type { RustAnalyzerExtensionApi } from "./main";
|
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
|
// 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
|
// only those are in use. We use "Empty" to represent these scenarios
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { type CommandFactory, Ctx, fetchWorkspace } from "./ctx";
|
||||||
import * as diagnostics from "./diagnostics";
|
import * as diagnostics from "./diagnostics";
|
||||||
import { activateTaskProvider } from "./tasks";
|
import { activateTaskProvider } from "./tasks";
|
||||||
import { setContextValue } from "./util";
|
import { setContextValue } from "./util";
|
||||||
|
import type { JsonProject } from "./rust_project";
|
||||||
|
|
||||||
const RUST_PROJECT_CONTEXT_NAME = "inRustProject";
|
const RUST_PROJECT_CONTEXT_NAME = "inRustProject";
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
interface JsonProject {
|
export interface JsonProject {
|
||||||
/// Path to the directory with *source code* of
|
/// Path to the directory with *source code* of
|
||||||
/// sysroot crates.
|
/// sysroot crates.
|
||||||
///
|
///
|
||||||
|
@ -21,7 +21,7 @@ interface JsonProject {
|
||||||
crates: Crate[];
|
crates: Crate[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Crate {
|
export interface Crate {
|
||||||
/// Optional crate name used for display purposes,
|
/// Optional crate name used for display purposes,
|
||||||
/// without affecting semantics. See the `deps`
|
/// without affecting semantics. See the `deps`
|
||||||
/// key for semantically-significant crate names.
|
/// key for semantically-significant crate names.
|
||||||
|
@ -82,7 +82,7 @@ interface Crate {
|
||||||
proc_macro_dylib_path?: string;
|
proc_macro_dylib_path?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Dep {
|
export interface Dep {
|
||||||
/// Index of a crate in the `crates` array.
|
/// Index of a crate in the `crates` array.
|
||||||
crate: number;
|
crate: number;
|
||||||
/// Name as should appear in the (implicit)
|
/// Name as should appear in the (implicit)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
"extends": "@tsconfig/strictest/tsconfig.json",
|
"extends": "@tsconfig/strictest/tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"esModuleInterop": false,
|
"esModuleInterop": false,
|
||||||
"module": "CommonJS",
|
"module": "Node16",
|
||||||
"moduleResolution": "Node16",
|
"moduleResolution": "Node16",
|
||||||
"target": "ES2021",
|
"target": "ES2021",
|
||||||
"outDir": "out",
|
"outDir": "out",
|
||||||
|
|
Loading…
Reference in a new issue