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_def | |
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_def')
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 3 | ||||
-rw-r--r-- | crates/hir_def/src/item_tree/lower.rs | 3 | ||||
-rw-r--r-- | crates/hir_def/src/lib.rs | 12 | ||||
-rw-r--r-- | crates/hir_def/src/nameres.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 20 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests/incremental.rs | 6 |
6 files changed, 35 insertions, 11 deletions
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 8d13c7e04..cad8a7479 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -18,7 +18,7 @@ use hir_expand::{ | |||
18 | ast_id_map::FileAstId, | 18 | ast_id_map::FileAstId, |
19 | hygiene::Hygiene, | 19 | hygiene::Hygiene, |
20 | name::{name, AsName, Name}, | 20 | name::{name, AsName, Name}, |
21 | HirFileId, InFile, | 21 | FragmentKind, HirFileId, InFile, |
22 | }; | 22 | }; |
23 | use la_arena::{Arena, Idx, RawIdx}; | 23 | use la_arena::{Arena, Idx, RawIdx}; |
24 | use profile::Count; | 24 | use profile::Count; |
@@ -656,6 +656,7 @@ pub struct MacroCall { | |||
656 | /// Path to the called macro. | 656 | /// Path to the called macro. |
657 | pub path: Interned<ModPath>, | 657 | pub path: Interned<ModPath>, |
658 | pub ast_id: FileAstId<ast::MacroCall>, | 658 | pub ast_id: FileAstId<ast::MacroCall>, |
659 | pub fragment: FragmentKind, | ||
659 | } | 660 | } |
660 | 661 | ||
661 | #[derive(Debug, Clone, Eq, PartialEq)] | 662 | #[derive(Debug, Clone, Eq, PartialEq)] |
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 5743b3386..fe348091d 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -624,7 +624,8 @@ impl<'a> Ctx<'a> { | |||
624 | fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> { | 624 | fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> { |
625 | let path = Interned::new(ModPath::from_src(self.db, m.path()?, &self.hygiene)?); | 625 | let path = Interned::new(ModPath::from_src(self.db, m.path()?, &self.hygiene)?); |
626 | let ast_id = self.source_ast_id_map.ast_id(m); | 626 | let ast_id = self.source_ast_id_map.ast_id(m); |
627 | let res = MacroCall { path, ast_id }; | 627 | let fragment = hir_expand::to_fragment_kind(m); |
628 | let res = MacroCall { path, ast_id, fragment }; | ||
628 | Some(id(self.data().macro_calls.alloc(res))) | 629 | Some(id(self.data().macro_calls.alloc(res))) |
629 | } | 630 | } |
630 | 631 | ||
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index da46f16f7..e96ca953f 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -62,7 +62,8 @@ use hir_expand::{ | |||
62 | ast_id_map::FileAstId, | 62 | ast_id_map::FileAstId, |
63 | eager::{expand_eager_macro, ErrorEmitted, ErrorSink}, | 63 | eager::{expand_eager_macro, ErrorEmitted, ErrorSink}, |
64 | hygiene::Hygiene, | 64 | hygiene::Hygiene, |
65 | AstId, AttrId, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, | 65 | AstId, AttrId, FragmentKind, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, |
66 | MacroDefKind, | ||
66 | }; | 67 | }; |
67 | use la_arena::Idx; | 68 | use la_arena::Idx; |
68 | use nameres::DefMap; | 69 | use nameres::DefMap; |
@@ -652,6 +653,7 @@ impl AsMacroCall for InFile<&ast::MacroCall> { | |||
652 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | 653 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, |
653 | mut error_sink: &mut dyn FnMut(mbe::ExpandError), | 654 | mut error_sink: &mut dyn FnMut(mbe::ExpandError), |
654 | ) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> { | 655 | ) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> { |
656 | let fragment = hir_expand::to_fragment_kind(self.value); | ||
655 | let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value)); | 657 | let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value)); |
656 | let h = Hygiene::new(db.upcast(), self.file_id); | 658 | let h = Hygiene::new(db.upcast(), self.file_id); |
657 | let path = self.value.path().and_then(|path| path::ModPath::from_src(db, path, &h)); | 659 | let path = self.value.path().and_then(|path| path::ModPath::from_src(db, path, &h)); |
@@ -667,6 +669,7 @@ impl AsMacroCall for InFile<&ast::MacroCall> { | |||
667 | 669 | ||
668 | macro_call_as_call_id( | 670 | macro_call_as_call_id( |
669 | &AstIdWithPath::new(ast_id.file_id, ast_id.value, path), | 671 | &AstIdWithPath::new(ast_id.file_id, ast_id.value, path), |
672 | fragment, | ||
670 | db, | 673 | db, |
671 | krate, | 674 | krate, |
672 | resolver, | 675 | resolver, |
@@ -695,6 +698,7 @@ pub struct UnresolvedMacro { | |||
695 | 698 | ||
696 | fn macro_call_as_call_id( | 699 | fn macro_call_as_call_id( |
697 | call: &AstIdWithPath<ast::MacroCall>, | 700 | call: &AstIdWithPath<ast::MacroCall>, |
701 | fragment: FragmentKind, | ||
698 | db: &dyn db::DefDatabase, | 702 | db: &dyn db::DefDatabase, |
699 | krate: CrateId, | 703 | krate: CrateId, |
700 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | 704 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, |
@@ -718,7 +722,11 @@ fn macro_call_as_call_id( | |||
718 | .map(MacroCallId::from) | 722 | .map(MacroCallId::from) |
719 | } else { | 723 | } else { |
720 | Ok(def | 724 | Ok(def |
721 | .as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike { ast_id: call.ast_id }) | 725 | .as_lazy_macro( |
726 | db.upcast(), | ||
727 | krate, | ||
728 | MacroCallKind::FnLike { ast_id: call.ast_id, fragment }, | ||
729 | ) | ||
722 | .into()) | 730 | .into()) |
723 | }; | 731 | }; |
724 | Ok(res) | 732 | Ok(res) |
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index 1bc72ec1f..249af6fc8 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs | |||
@@ -629,7 +629,7 @@ mod diagnostics { | |||
629 | DiagnosticKind::UnresolvedProcMacro { ast } => { | 629 | DiagnosticKind::UnresolvedProcMacro { ast } => { |
630 | let mut precise_location = None; | 630 | let mut precise_location = None; |
631 | let (file, ast, name) = match ast { | 631 | let (file, ast, name) = match ast { |
632 | MacroCallKind::FnLike { ast_id } => { | 632 | MacroCallKind::FnLike { ast_id, .. } => { |
633 | let node = ast_id.to_node(db.upcast()); | 633 | let node = ast_id.to_node(db.upcast()); |
634 | (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)), None) | 634 | (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)), None) |
635 | } | 635 | } |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 05ceb1efb..e89136ed1 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -13,7 +13,7 @@ use hir_expand::{ | |||
13 | builtin_macro::find_builtin_macro, | 13 | builtin_macro::find_builtin_macro, |
14 | name::{AsName, Name}, | 14 | name::{AsName, Name}, |
15 | proc_macro::ProcMacroExpander, | 15 | proc_macro::ProcMacroExpander, |
16 | AttrId, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, | 16 | AttrId, FragmentKind, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, |
17 | }; | 17 | }; |
18 | use hir_expand::{InFile, MacroCallLoc}; | 18 | use hir_expand::{InFile, MacroCallLoc}; |
19 | use rustc_hash::{FxHashMap, FxHashSet}; | 19 | use rustc_hash::{FxHashMap, FxHashSet}; |
@@ -215,7 +215,7 @@ struct MacroDirective { | |||
215 | 215 | ||
216 | #[derive(Clone, Debug, Eq, PartialEq)] | 216 | #[derive(Clone, Debug, Eq, PartialEq)] |
217 | enum MacroDirectiveKind { | 217 | enum MacroDirectiveKind { |
218 | FnLike { ast_id: AstIdWithPath<ast::MacroCall> }, | 218 | FnLike { ast_id: AstIdWithPath<ast::MacroCall>, fragment: FragmentKind }, |
219 | Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId }, | 219 | Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId }, |
220 | } | 220 | } |
221 | 221 | ||
@@ -807,9 +807,10 @@ impl DefCollector<'_> { | |||
807 | let mut res = ReachedFixedPoint::Yes; | 807 | let mut res = ReachedFixedPoint::Yes; |
808 | macros.retain(|directive| { | 808 | macros.retain(|directive| { |
809 | match &directive.kind { | 809 | match &directive.kind { |
810 | MacroDirectiveKind::FnLike { ast_id } => { | 810 | MacroDirectiveKind::FnLike { ast_id, fragment } => { |
811 | match macro_call_as_call_id( | 811 | match macro_call_as_call_id( |
812 | ast_id, | 812 | ast_id, |
813 | *fragment, | ||
813 | self.db, | 814 | self.db, |
814 | self.def_map.krate, | 815 | self.def_map.krate, |
815 | |path| { | 816 | |path| { |
@@ -926,8 +927,9 @@ impl DefCollector<'_> { | |||
926 | 927 | ||
927 | for directive in &self.unexpanded_macros { | 928 | for directive in &self.unexpanded_macros { |
928 | match &directive.kind { | 929 | match &directive.kind { |
929 | MacroDirectiveKind::FnLike { ast_id, .. } => match macro_call_as_call_id( | 930 | MacroDirectiveKind::FnLike { ast_id, fragment } => match macro_call_as_call_id( |
930 | ast_id, | 931 | ast_id, |
932 | *fragment, | ||
931 | self.db, | 933 | self.db, |
932 | self.def_map.krate, | 934 | self.def_map.krate, |
933 | |path| { | 935 | |path| { |
@@ -1496,6 +1498,7 @@ impl ModCollector<'_, '_> { | |||
1496 | let mut error = None; | 1498 | let mut error = None; |
1497 | match macro_call_as_call_id( | 1499 | match macro_call_as_call_id( |
1498 | &ast_id, | 1500 | &ast_id, |
1501 | mac.fragment, | ||
1499 | self.def_collector.db, | 1502 | self.def_collector.db, |
1500 | self.def_collector.def_map.krate, | 1503 | self.def_collector.def_map.krate, |
1501 | |path| { | 1504 | |path| { |
@@ -1524,9 +1527,14 @@ impl ModCollector<'_, '_> { | |||
1524 | } | 1527 | } |
1525 | Ok(Err(_)) => { | 1528 | Ok(Err(_)) => { |
1526 | // Built-in macro failed eager expansion. | 1529 | // Built-in macro failed eager expansion. |
1530 | |||
1531 | // FIXME: don't parse the file here | ||
1532 | let fragment = hir_expand::to_fragment_kind( | ||
1533 | &ast_id.ast_id.to_node(self.def_collector.db.upcast()), | ||
1534 | ); | ||
1527 | self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error( | 1535 | self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error( |
1528 | self.module_id, | 1536 | self.module_id, |
1529 | MacroCallKind::FnLike { ast_id: ast_id.ast_id }, | 1537 | MacroCallKind::FnLike { ast_id: ast_id.ast_id, fragment }, |
1530 | error.unwrap().to_string(), | 1538 | error.unwrap().to_string(), |
1531 | )); | 1539 | )); |
1532 | return; | 1540 | return; |
@@ -1543,7 +1551,7 @@ impl ModCollector<'_, '_> { | |||
1543 | self.def_collector.unexpanded_macros.push(MacroDirective { | 1551 | self.def_collector.unexpanded_macros.push(MacroDirective { |
1544 | module_id: self.module_id, | 1552 | module_id: self.module_id, |
1545 | depth: self.macro_depth + 1, | 1553 | depth: self.macro_depth + 1, |
1546 | kind: MacroDirectiveKind::FnLike { ast_id }, | 1554 | kind: MacroDirectiveKind::FnLike { ast_id, fragment: mac.fragment }, |
1547 | }); | 1555 | }); |
1548 | } | 1556 | } |
1549 | 1557 | ||
diff --git a/crates/hir_def/src/nameres/tests/incremental.rs b/crates/hir_def/src/nameres/tests/incremental.rs index 227ecd162..d884a6eb4 100644 --- a/crates/hir_def/src/nameres/tests/incremental.rs +++ b/crates/hir_def/src/nameres/tests/incremental.rs | |||
@@ -137,6 +137,9 @@ m!(Z); | |||
137 | }); | 137 | }); |
138 | let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count(); | 138 | let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count(); |
139 | assert_eq!(n_recalculated_item_trees, 6); | 139 | assert_eq!(n_recalculated_item_trees, 6); |
140 | let n_reparsed_macros = | ||
141 | events.iter().filter(|it| it.contains("parse_macro_expansion")).count(); | ||
142 | assert_eq!(n_reparsed_macros, 3); | ||
140 | } | 143 | } |
141 | 144 | ||
142 | let new_text = r#" | 145 | let new_text = r#" |
@@ -155,5 +158,8 @@ m!(Z); | |||
155 | }); | 158 | }); |
156 | let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count(); | 159 | let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count(); |
157 | assert_eq!(n_recalculated_item_trees, 1); | 160 | assert_eq!(n_recalculated_item_trees, 1); |
161 | let n_reparsed_macros = | ||
162 | events.iter().filter(|it| it.contains("parse_macro_expansion")).count(); | ||
163 | assert_eq!(n_reparsed_macros, 0); | ||
158 | } | 164 | } |
159 | } | 165 | } |