mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-27 04:19:13 +00:00
Merge #7145
7145: Proper handling $crate Take 2 [DO NOT MERGE] r=edwin0cheng a=edwin0cheng Similar to previous PR (#7133) , but improved the following things : 1. Instead of storing the whole `ExpansionInfo`, we store a similar but stripped version `HygieneInfo`. 2. Instread of storing the `SyntaxNode` (because every token we are interested are IDENT), we store the `TextRange` only. 3. Because of 2, we now can put it in Salsa. 4. And most important improvement: Instead of computing the whole frames every single time, we compute it recursively through salsa: (Such that in the best scenario, we only need to compute the first layer of frame) ```rust let def_site = db.hygiene_frame(info.def.file_id); let call_site = db.hygiene_frame(info.arg.file_id); HygieneFrame { expansion: Some(info), local_inner, krate, call_site, def_site } ``` The overall speed compared to previous PR is much faster (65s vs 45s) : ``` [WITH old PR] Database loaded 644.86ms, 284mi Crates in this dir: 36 Total modules found: 576 Total declarations: 11153 Total functions: 8715 Item Collection: 15.78s, 91562mi Total expressions: 240721 Expressions of unknown type: 2635 (1%) Expressions of partially unknown type: 2064 (0%) Type mismatches: 865 Inference: 49.84s, 250747mi Total: 65.62s, 342310mi rust-analyzer -q analysis-stats . 66.72s user 0.57s system 99% cpu 1:07.40 total [WITH this PR] Database loaded 665.83ms, 284mi Crates in this dir: 36 Total modules found: 577 Total declarations: 11188 Total functions: 8743 Item Collection: 15.28s, 84919mi Total expressions: 241229 Expressions of unknown type: 2637 (1%) Expressions of partially unknown type: 2064 (0%) Type mismatches: 868 Inference: 30.15s, 135293mi Total: 45.43s, 220213mi rust-analyzer -q analysis-stats . 46.26s user 0.74s system 99% cpu 47.294 total ``` *HOWEVER*, it is still a perf regression (35s vs 45s): ``` [WITHOUT this PR] Database loaded 657.42ms, 284mi Crates in this dir: 36 Total modules found: 577 Total declarations: 11177 Total functions: 8735 Item Collection: 12.87s, 72407mi Total expressions: 239380 Expressions of unknown type: 2643 (1%) Expressions of partially unknown type: 2064 (0%) Type mismatches: 868 Inference: 22.88s, 97889mi Total: 35.74s, 170297mi rust-analyzer -q analysis-stats . 36.71s user 0.63s system 99% cpu 37.498 total ``` Co-authored-by: Edwin Cheng <edwin0cheng@gmail.com>
This commit is contained in:
commit
1a29934c37
9 changed files with 235 additions and 58 deletions
|
@ -150,7 +150,7 @@ fn match_subtree(
|
|||
res.add_err(err!("leftover tokens"));
|
||||
}
|
||||
}
|
||||
Op::Var { name, kind } => {
|
||||
Op::Var { name, kind, .. } => {
|
||||
let kind = match kind {
|
||||
Some(k) => k,
|
||||
None => {
|
||||
|
|
|
@ -100,8 +100,8 @@ fn expand_subtree(
|
|||
err = err.or(e);
|
||||
arena.push(tt.into());
|
||||
}
|
||||
Op::Var { name, .. } => {
|
||||
let ExpandResult { value: fragment, err: e } = expand_var(ctx, &name);
|
||||
Op::Var { name, id, .. } => {
|
||||
let ExpandResult { value: fragment, err: e } = expand_var(ctx, &name, *id);
|
||||
err = err.or(e);
|
||||
push_fragment(arena, fragment);
|
||||
}
|
||||
|
@ -118,12 +118,10 @@ fn expand_subtree(
|
|||
ExpandResult { value: tt::Subtree { delimiter: template.delimiter, token_trees: tts }, err }
|
||||
}
|
||||
|
||||
fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> {
|
||||
fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr, id: tt::TokenId) -> ExpandResult<Fragment> {
|
||||
if v == "crate" {
|
||||
// We simply produce identifier `$crate` here. And it will be resolved when lowering ast to Path.
|
||||
let tt =
|
||||
tt::Leaf::from(tt::Ident { text: "$crate".into(), id: tt::TokenId::unspecified() })
|
||||
.into();
|
||||
let tt = tt::Leaf::from(tt::Ident { text: "$crate".into(), id }).into();
|
||||
ExpandResult::ok(Fragment::Tokens(tt))
|
||||
} else if !ctx.bindings.contains(v) {
|
||||
// Note that it is possible to have a `$var` inside a macro which is not bound.
|
||||
|
@ -142,14 +140,8 @@ fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> {
|
|||
let tt = tt::Subtree {
|
||||
delimiter: None,
|
||||
token_trees: vec![
|
||||
tt::Leaf::from(tt::Punct {
|
||||
char: '$',
|
||||
spacing: tt::Spacing::Alone,
|
||||
id: tt::TokenId::unspecified(),
|
||||
})
|
||||
.into(),
|
||||
tt::Leaf::from(tt::Ident { text: v.clone(), id: tt::TokenId::unspecified() })
|
||||
.into(),
|
||||
tt::Leaf::from(tt::Punct { char: '$', spacing: tt::Spacing::Alone, id }).into(),
|
||||
tt::Leaf::from(tt::Ident { text: v.clone(), id }).into(),
|
||||
],
|
||||
}
|
||||
.into();
|
||||
|
|
|
@ -8,7 +8,7 @@ use crate::{tt_iter::TtIter, ExpandError, MetaTemplate};
|
|||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub(crate) enum Op {
|
||||
Var { name: SmolStr, kind: Option<SmolStr> },
|
||||
Var { name: SmolStr, kind: Option<SmolStr>, id: tt::TokenId },
|
||||
Repeat { subtree: MetaTemplate, kind: RepeatKind, separator: Option<Separator> },
|
||||
Leaf(tt::Leaf),
|
||||
Subtree(MetaTemplate),
|
||||
|
@ -106,18 +106,21 @@ fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Resul
|
|||
}
|
||||
let name = UNDERSCORE.clone();
|
||||
let kind = eat_fragment_kind(src, mode)?;
|
||||
Op::Var { name, kind }
|
||||
let id = punct.id;
|
||||
Op::Var { name, kind, id }
|
||||
}
|
||||
tt::Leaf::Ident(ident) => {
|
||||
let name = ident.text.clone();
|
||||
let kind = eat_fragment_kind(src, mode)?;
|
||||
Op::Var { name, kind }
|
||||
let id = ident.id;
|
||||
Op::Var { name, kind, id }
|
||||
}
|
||||
tt::Leaf::Literal(lit) => {
|
||||
if is_boolean_literal(&lit) {
|
||||
let name = lit.text.clone();
|
||||
let kind = eat_fragment_kind(src, mode)?;
|
||||
Op::Var { name, kind }
|
||||
let id = lit.id;
|
||||
Op::Var { name, kind, id }
|
||||
} else {
|
||||
bail!("bad var 2");
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue