diff options
author | Aleksey Kladov <[email protected]> | 2020-04-11 16:52:26 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-04-11 16:52:26 +0100 |
commit | 38c67e5c0d4297f45ab2b78a00b59f737796d160 (patch) | |
tree | b96b64b2be660a35b6bb706d0ce8c5ee27f7433a /crates/ra_hir_def/src/body.rs | |
parent | deb40d52aaa1989402fc01d65da389dc92fb66fa (diff) |
Avoid cyclic queries in name resolution when processing enums
Diffstat (limited to 'crates/ra_hir_def/src/body.rs')
-rw-r--r-- | crates/ra_hir_def/src/body.rs | 47 |
1 files changed, 36 insertions, 11 deletions
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 7fe5403c0..7fac6ce66 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs | |||
@@ -25,32 +25,57 @@ use crate::{ | |||
25 | AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId, | 25 | AsMacroCall, DefWithBodyId, HasModule, Lookup, ModuleId, |
26 | }; | 26 | }; |
27 | use ra_cfg::CfgOptions; | 27 | use ra_cfg::CfgOptions; |
28 | use ra_db::CrateId; | ||
29 | |||
30 | /// A subser of Exander that only deals with cfg attributes. We only need it to | ||
31 | /// avoid cyclic queries in crate def map during enum processing. | ||
32 | pub(crate) struct CfgExpander { | ||
33 | cfg_options: CfgOptions, | ||
34 | hygiene: Hygiene, | ||
35 | } | ||
28 | 36 | ||
29 | pub(crate) struct Expander { | 37 | pub(crate) struct Expander { |
38 | cfg_expander: CfgExpander, | ||
30 | crate_def_map: Arc<CrateDefMap>, | 39 | crate_def_map: Arc<CrateDefMap>, |
31 | cfg_options: CfgOptions, | ||
32 | current_file_id: HirFileId, | 40 | current_file_id: HirFileId, |
33 | hygiene: Hygiene, | ||
34 | ast_id_map: Arc<AstIdMap>, | 41 | ast_id_map: Arc<AstIdMap>, |
35 | module: ModuleId, | 42 | module: ModuleId, |
36 | recursive_limit: usize, | 43 | recursive_limit: usize, |
37 | } | 44 | } |
38 | 45 | ||
46 | impl CfgExpander { | ||
47 | pub(crate) fn new( | ||
48 | db: &dyn DefDatabase, | ||
49 | current_file_id: HirFileId, | ||
50 | krate: CrateId, | ||
51 | ) -> CfgExpander { | ||
52 | let hygiene = Hygiene::new(db.upcast(), current_file_id); | ||
53 | let cfg_options = db.crate_graph()[krate].cfg_options.clone(); | ||
54 | CfgExpander { cfg_options, hygiene } | ||
55 | } | ||
56 | |||
57 | pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs { | ||
58 | Attrs::new(owner, &self.hygiene) | ||
59 | } | ||
60 | |||
61 | pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool { | ||
62 | attrs.is_cfg_enabled(&self.cfg_options) | ||
63 | } | ||
64 | } | ||
65 | |||
39 | impl Expander { | 66 | impl Expander { |
40 | pub(crate) fn new( | 67 | pub(crate) fn new( |
41 | db: &dyn DefDatabase, | 68 | db: &dyn DefDatabase, |
42 | current_file_id: HirFileId, | 69 | current_file_id: HirFileId, |
43 | module: ModuleId, | 70 | module: ModuleId, |
44 | ) -> Expander { | 71 | ) -> Expander { |
72 | let cfg_expander = CfgExpander::new(db, current_file_id, module.krate); | ||
45 | let crate_def_map = db.crate_def_map(module.krate); | 73 | let crate_def_map = db.crate_def_map(module.krate); |
46 | let hygiene = Hygiene::new(db.upcast(), current_file_id); | ||
47 | let ast_id_map = db.ast_id_map(current_file_id); | 74 | let ast_id_map = db.ast_id_map(current_file_id); |
48 | let cfg_options = db.crate_graph()[module.krate].cfg_options.clone(); | ||
49 | Expander { | 75 | Expander { |
76 | cfg_expander, | ||
50 | crate_def_map, | 77 | crate_def_map, |
51 | cfg_options, | ||
52 | current_file_id, | 78 | current_file_id, |
53 | hygiene, | ||
54 | ast_id_map, | 79 | ast_id_map, |
55 | module, | 80 | module, |
56 | recursive_limit: 0, | 81 | recursive_limit: 0, |
@@ -87,7 +112,7 @@ impl Expander { | |||
87 | ast_id_map: mem::take(&mut self.ast_id_map), | 112 | ast_id_map: mem::take(&mut self.ast_id_map), |
88 | bomb: DropBomb::new("expansion mark dropped"), | 113 | bomb: DropBomb::new("expansion mark dropped"), |
89 | }; | 114 | }; |
90 | self.hygiene = Hygiene::new(db.upcast(), file_id); | 115 | self.cfg_expander.hygiene = Hygiene::new(db.upcast(), file_id); |
91 | self.current_file_id = file_id; | 116 | self.current_file_id = file_id; |
92 | self.ast_id_map = db.ast_id_map(file_id); | 117 | self.ast_id_map = db.ast_id_map(file_id); |
93 | self.recursive_limit += 1; | 118 | self.recursive_limit += 1; |
@@ -103,7 +128,7 @@ impl Expander { | |||
103 | } | 128 | } |
104 | 129 | ||
105 | pub(crate) fn exit(&mut self, db: &dyn DefDatabase, mut mark: Mark) { | 130 | pub(crate) fn exit(&mut self, db: &dyn DefDatabase, mut mark: Mark) { |
106 | self.hygiene = Hygiene::new(db.upcast(), mark.file_id); | 131 | self.cfg_expander.hygiene = Hygiene::new(db.upcast(), mark.file_id); |
107 | self.current_file_id = mark.file_id; | 132 | self.current_file_id = mark.file_id; |
108 | self.ast_id_map = mem::take(&mut mark.ast_id_map); | 133 | self.ast_id_map = mem::take(&mut mark.ast_id_map); |
109 | self.recursive_limit -= 1; | 134 | self.recursive_limit -= 1; |
@@ -115,15 +140,15 @@ impl Expander { | |||
115 | } | 140 | } |
116 | 141 | ||
117 | pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs { | 142 | pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs { |
118 | Attrs::new(owner, &self.hygiene) | 143 | self.cfg_expander.parse_attrs(owner) |
119 | } | 144 | } |
120 | 145 | ||
121 | pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool { | 146 | pub(crate) fn is_cfg_enabled(&self, attrs: &Attrs) -> bool { |
122 | attrs.is_cfg_enabled(&self.cfg_options) | 147 | self.cfg_expander.is_cfg_enabled(attrs) |
123 | } | 148 | } |
124 | 149 | ||
125 | fn parse_path(&mut self, path: ast::Path) -> Option<Path> { | 150 | fn parse_path(&mut self, path: ast::Path) -> Option<Path> { |
126 | Path::from_src(path, &self.hygiene) | 151 | Path::from_src(path, &self.cfg_expander.hygiene) |
127 | } | 152 | } |
128 | 153 | ||
129 | fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroDefId> { | 154 | fn resolve_path_as_macro(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<MacroDefId> { |