diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-05-09 15:40:49 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2021-05-09 15:40:49 +0100 |
commit | 0900beeaa2ca4b9e91d51165545935d4e1db7bb6 (patch) | |
tree | db1e1461562c7d8a90d816e5a241636f10468cdc /crates/hir_expand | |
parent | 3f01edebecd5a73fc2abab75a8b29b9d64fd9fa0 (diff) | |
parent | fd5a1d1765801ef3bda447b849951631f61f1d25 (diff) |
Merge #8776
8776: fix: fix unnecessary recomputations due to macros r=jonas-schievink a=jonas-schievink
This computes a macro's fragment kind eagerly (when the calling file is still available in parsed form) and stores it in the `MacroCallLoc`. This means that during expansion we no longer have to reparse the file containing the macro call, avoiding the unnecessary salsa dependencies (https://github.com/rust-analyzer/rust-analyzer/pull/8746#issuecomment-834776349).
Marking as draft until I manage to find a test for this problem, since for some reason `typing_inside_a_function_should_not_invalidate_expansions` does not catch this (which might indicate that I misunderstand the problem).
I've manually confirmed that this fixes the issue described in https://github.com/rust-analyzer/rust-analyzer/pull/8746#issuecomment-834776349:
```
7ms - parse_query @ FileId(179)
12ms - SourceBinder::to_module_def
12ms - crate_def_map:wait
5ms - item_tree_query (1 calls)
7ms - ???
```
Co-authored-by: Jonas Schievink <[email protected]>
Diffstat (limited to 'crates/hir_expand')
-rw-r--r-- | crates/hir_expand/src/builtin_macro.rs | 1 | ||||
-rw-r--r-- | crates/hir_expand/src/db.rs | 71 | ||||
-rw-r--r-- | crates/hir_expand/src/eager.rs | 7 | ||||
-rw-r--r-- | crates/hir_expand/src/lib.rs | 68 |
4 files changed, 84 insertions, 63 deletions
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index 0142a06ed..af9802144 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs | |||
@@ -578,6 +578,7 @@ mod tests { | |||
578 | krate, | 578 | krate, |
579 | kind: MacroCallKind::FnLike { | 579 | kind: MacroCallKind::FnLike { |
580 | ast_id: AstId::new(file_id.into(), ast_id_map.ast_id(¯o_call)), | 580 | ast_id: AstId::new(file_id.into(), ast_id_map.ast_id(¯o_call)), |
581 | fragment: FragmentKind::Expr, | ||
581 | }, | 582 | }, |
582 | }; | 583 | }; |
583 | 584 | ||
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs index d61f4b31a..6647e57e7 100644 --- a/crates/hir_expand/src/db.rs +++ b/crates/hir_expand/src/db.rs | |||
@@ -8,9 +8,7 @@ use parser::FragmentKind; | |||
8 | use syntax::{ | 8 | use syntax::{ |
9 | algo::diff, | 9 | algo::diff, |
10 | ast::{self, NameOwner}, | 10 | ast::{self, NameOwner}, |
11 | AstNode, GreenNode, Parse, | 11 | AstNode, GreenNode, Parse, SyntaxNode, SyntaxToken, |
12 | SyntaxKind::*, | ||
13 | SyntaxNode, SyntaxToken, | ||
14 | }; | 12 | }; |
15 | 13 | ||
16 | use crate::{ | 14 | use crate::{ |
@@ -160,7 +158,7 @@ pub fn expand_hypothetical( | |||
160 | 158 | ||
161 | let hypothetical_expansion = macro_def.expand(db, lazy_id, &tt); | 159 | let hypothetical_expansion = macro_def.expand(db, lazy_id, &tt); |
162 | 160 | ||
163 | let fragment_kind = to_fragment_kind(db, actual_macro_call); | 161 | let fragment_kind = macro_fragment_kind(db, actual_macro_call); |
164 | 162 | ||
165 | let (node, tmap_2) = | 163 | let (node, tmap_2) = |
166 | mbe::token_tree_to_syntax_node(&hypothetical_expansion.value, fragment_kind).ok()?; | 164 | mbe::token_tree_to_syntax_node(&hypothetical_expansion.value, fragment_kind).ok()?; |
@@ -226,7 +224,7 @@ fn parse_macro_expansion( | |||
226 | None => return ExpandResult { value: None, err: result.err }, | 224 | None => return ExpandResult { value: None, err: result.err }, |
227 | }; | 225 | }; |
228 | 226 | ||
229 | let fragment_kind = to_fragment_kind(db, macro_file.macro_call_id); | 227 | let fragment_kind = macro_fragment_kind(db, macro_file.macro_call_id); |
230 | 228 | ||
231 | log::debug!("expanded = {}", tt.as_debug_string()); | 229 | log::debug!("expanded = {}", tt.as_debug_string()); |
232 | log::debug!("kind = {:?}", fragment_kind); | 230 | log::debug!("kind = {:?}", fragment_kind); |
@@ -427,62 +425,15 @@ fn hygiene_frame(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<HygieneFrame> | |||
427 | Arc::new(HygieneFrame::new(db, file_id)) | 425 | Arc::new(HygieneFrame::new(db, file_id)) |
428 | } | 426 | } |
429 | 427 | ||
430 | /// Given a `MacroCallId`, return what `FragmentKind` it belongs to. | 428 | fn macro_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind { |
431 | /// FIXME: Not completed | 429 | match id { |
432 | fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind { | 430 | MacroCallId::LazyMacro(id) => { |
433 | let lazy_id = match id { | 431 | let loc: MacroCallLoc = db.lookup_intern_macro(id); |
434 | MacroCallId::LazyMacro(id) => id, | 432 | loc.kind.fragment_kind() |
435 | MacroCallId::EagerMacro(id) => { | ||
436 | return db.lookup_intern_eager_expansion(id).fragment; | ||
437 | } | ||
438 | }; | ||
439 | let syn = db.lookup_intern_macro(lazy_id).kind.node(db).value; | ||
440 | |||
441 | let parent = match syn.parent() { | ||
442 | Some(it) => it, | ||
443 | None => return FragmentKind::Statements, | ||
444 | }; | ||
445 | |||
446 | match parent.kind() { | ||
447 | MACRO_ITEMS | SOURCE_FILE => FragmentKind::Items, | ||
448 | MACRO_STMTS => FragmentKind::Statements, | ||
449 | MACRO_PAT => FragmentKind::Pattern, | ||
450 | MACRO_TYPE => FragmentKind::Type, | ||
451 | ITEM_LIST => FragmentKind::Items, | ||
452 | LET_STMT => { | ||
453 | // FIXME: Handle LHS Pattern | ||
454 | FragmentKind::Expr | ||
455 | } | 433 | } |
456 | EXPR_STMT => FragmentKind::Statements, | 434 | MacroCallId::EagerMacro(id) => { |
457 | BLOCK_EXPR => FragmentKind::Statements, | 435 | let loc: EagerCallLoc = db.lookup_intern_eager_expansion(id); |
458 | ARG_LIST => FragmentKind::Expr, | 436 | loc.fragment |
459 | TRY_EXPR => FragmentKind::Expr, | ||
460 | TUPLE_EXPR => FragmentKind::Expr, | ||
461 | PAREN_EXPR => FragmentKind::Expr, | ||
462 | ARRAY_EXPR => FragmentKind::Expr, | ||
463 | FOR_EXPR => FragmentKind::Expr, | ||
464 | PATH_EXPR => FragmentKind::Expr, | ||
465 | CLOSURE_EXPR => FragmentKind::Expr, | ||
466 | CONDITION => FragmentKind::Expr, | ||
467 | BREAK_EXPR => FragmentKind::Expr, | ||
468 | RETURN_EXPR => FragmentKind::Expr, | ||
469 | MATCH_EXPR => FragmentKind::Expr, | ||
470 | MATCH_ARM => FragmentKind::Expr, | ||
471 | MATCH_GUARD => FragmentKind::Expr, | ||
472 | RECORD_EXPR_FIELD => FragmentKind::Expr, | ||
473 | CALL_EXPR => FragmentKind::Expr, | ||
474 | INDEX_EXPR => FragmentKind::Expr, | ||
475 | METHOD_CALL_EXPR => FragmentKind::Expr, | ||
476 | FIELD_EXPR => FragmentKind::Expr, | ||
477 | AWAIT_EXPR => FragmentKind::Expr, | ||
478 | CAST_EXPR => FragmentKind::Expr, | ||
479 | REF_EXPR => FragmentKind::Expr, | ||
480 | PREFIX_EXPR => FragmentKind::Expr, | ||
481 | RANGE_EXPR => FragmentKind::Expr, | ||
482 | BIN_EXPR => FragmentKind::Expr, | ||
483 | _ => { | ||
484 | // Unknown , Just guess it is `Items` | ||
485 | FragmentKind::Items | ||
486 | } | 437 | } |
487 | } | 438 | } |
488 | } | 439 | } |
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs index f12132f84..85491fe8b 100644 --- a/crates/hir_expand/src/eager.rs +++ b/crates/hir_expand/src/eager.rs | |||
@@ -175,8 +175,13 @@ fn lazy_expand( | |||
175 | ) -> ExpandResult<Option<InFile<SyntaxNode>>> { | 175 | ) -> ExpandResult<Option<InFile<SyntaxNode>>> { |
176 | let ast_id = db.ast_id_map(macro_call.file_id).ast_id(¯o_call.value); | 176 | let ast_id = db.ast_id_map(macro_call.file_id).ast_id(¯o_call.value); |
177 | 177 | ||
178 | let fragment = crate::to_fragment_kind(¯o_call.value); | ||
178 | let id: MacroCallId = def | 179 | let id: MacroCallId = def |
179 | .as_lazy_macro(db, krate, MacroCallKind::FnLike { ast_id: macro_call.with_value(ast_id) }) | 180 | .as_lazy_macro( |
181 | db, | ||
182 | krate, | ||
183 | MacroCallKind::FnLike { ast_id: macro_call.with_value(ast_id), fragment }, | ||
184 | ) | ||
180 | .into(); | 185 | .into(); |
181 | 186 | ||
182 | let err = db.macro_expand_error(id); | 187 | let err = db.macro_expand_error(id); |
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs index 0402640de..80ab3aeee 100644 --- a/crates/hir_expand/src/lib.rs +++ b/crates/hir_expand/src/lib.rs | |||
@@ -16,7 +16,9 @@ pub mod quote; | |||
16 | pub mod eager; | 16 | pub mod eager; |
17 | 17 | ||
18 | use either::Either; | 18 | use either::Either; |
19 | |||
19 | pub use mbe::{ExpandError, ExpandResult}; | 20 | pub use mbe::{ExpandError, ExpandResult}; |
21 | pub use parser::FragmentKind; | ||
20 | 22 | ||
21 | use std::hash::Hash; | 23 | use std::hash::Hash; |
22 | use std::sync::Arc; | 24 | use std::sync::Arc; |
@@ -290,7 +292,7 @@ pub struct MacroCallLoc { | |||
290 | 292 | ||
291 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 293 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
292 | pub enum MacroCallKind { | 294 | pub enum MacroCallKind { |
293 | FnLike { ast_id: AstId<ast::MacroCall> }, | 295 | FnLike { ast_id: AstId<ast::MacroCall>, fragment: FragmentKind }, |
294 | Derive { ast_id: AstId<ast::Item>, derive_name: String, derive_attr: AttrId }, | 296 | Derive { ast_id: AstId<ast::Item>, derive_name: String, derive_attr: AttrId }, |
295 | } | 297 | } |
296 | 298 | ||
@@ -324,6 +326,13 @@ impl MacroCallKind { | |||
324 | MacroCallKind::Derive { ast_id, .. } => Some(ast_id.to_node(db).syntax().clone()), | 326 | MacroCallKind::Derive { ast_id, .. } => Some(ast_id.to_node(db).syntax().clone()), |
325 | } | 327 | } |
326 | } | 328 | } |
329 | |||
330 | fn fragment_kind(&self) -> FragmentKind { | ||
331 | match self { | ||
332 | MacroCallKind::FnLike { fragment, .. } => *fragment, | ||
333 | MacroCallKind::Derive { .. } => FragmentKind::Items, | ||
334 | } | ||
335 | } | ||
327 | } | 336 | } |
328 | 337 | ||
329 | impl MacroCallId { | 338 | impl MacroCallId { |
@@ -357,7 +366,6 @@ pub struct ExpansionInfo { | |||
357 | } | 366 | } |
358 | 367 | ||
359 | pub use mbe::Origin; | 368 | pub use mbe::Origin; |
360 | use parser::FragmentKind; | ||
361 | 369 | ||
362 | impl ExpansionInfo { | 370 | impl ExpansionInfo { |
363 | pub fn call_node(&self) -> Option<InFile<SyntaxNode>> { | 371 | pub fn call_node(&self) -> Option<InFile<SyntaxNode>> { |
@@ -562,3 +570,59 @@ impl<N: AstNode> InFile<N> { | |||
562 | self.with_value(self.value.syntax()) | 570 | self.with_value(self.value.syntax()) |
563 | } | 571 | } |
564 | } | 572 | } |
573 | |||
574 | /// Given a `MacroCallId`, return what `FragmentKind` it belongs to. | ||
575 | /// FIXME: Not completed | ||
576 | pub fn to_fragment_kind(call: &ast::MacroCall) -> FragmentKind { | ||
577 | use syntax::SyntaxKind::*; | ||
578 | |||
579 | let syn = call.syntax(); | ||
580 | |||
581 | let parent = match syn.parent() { | ||
582 | Some(it) => it, | ||
583 | None => return FragmentKind::Statements, | ||
584 | }; | ||
585 | |||
586 | match parent.kind() { | ||
587 | MACRO_ITEMS | SOURCE_FILE => FragmentKind::Items, | ||
588 | MACRO_STMTS => FragmentKind::Statements, | ||
589 | MACRO_PAT => FragmentKind::Pattern, | ||
590 | MACRO_TYPE => FragmentKind::Type, | ||
591 | ITEM_LIST => FragmentKind::Items, | ||
592 | LET_STMT => { | ||
593 | // FIXME: Handle LHS Pattern | ||
594 | FragmentKind::Expr | ||
595 | } | ||
596 | EXPR_STMT => FragmentKind::Statements, | ||
597 | BLOCK_EXPR => FragmentKind::Statements, | ||
598 | ARG_LIST => FragmentKind::Expr, | ||
599 | TRY_EXPR => FragmentKind::Expr, | ||
600 | TUPLE_EXPR => FragmentKind::Expr, | ||
601 | PAREN_EXPR => FragmentKind::Expr, | ||
602 | ARRAY_EXPR => FragmentKind::Expr, | ||
603 | FOR_EXPR => FragmentKind::Expr, | ||
604 | PATH_EXPR => FragmentKind::Expr, | ||
605 | CLOSURE_EXPR => FragmentKind::Expr, | ||
606 | CONDITION => FragmentKind::Expr, | ||
607 | BREAK_EXPR => FragmentKind::Expr, | ||
608 | RETURN_EXPR => FragmentKind::Expr, | ||
609 | MATCH_EXPR => FragmentKind::Expr, | ||
610 | MATCH_ARM => FragmentKind::Expr, | ||
611 | MATCH_GUARD => FragmentKind::Expr, | ||
612 | RECORD_EXPR_FIELD => FragmentKind::Expr, | ||
613 | CALL_EXPR => FragmentKind::Expr, | ||
614 | INDEX_EXPR => FragmentKind::Expr, | ||
615 | METHOD_CALL_EXPR => FragmentKind::Expr, | ||
616 | FIELD_EXPR => FragmentKind::Expr, | ||
617 | AWAIT_EXPR => FragmentKind::Expr, | ||
618 | CAST_EXPR => FragmentKind::Expr, | ||
619 | REF_EXPR => FragmentKind::Expr, | ||
620 | PREFIX_EXPR => FragmentKind::Expr, | ||
621 | RANGE_EXPR => FragmentKind::Expr, | ||
622 | BIN_EXPR => FragmentKind::Expr, | ||
623 | _ => { | ||
624 | // Unknown , Just guess it is `Items` | ||
625 | FragmentKind::Items | ||
626 | } | ||
627 | } | ||
628 | } | ||