aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-04-11 16:52:26 +0100
committerAleksey Kladov <[email protected]>2020-04-11 16:52:26 +0100
commit38c67e5c0d4297f45ab2b78a00b59f737796d160 (patch)
treeb96b64b2be660a35b6bb706d0ce8c5ee27f7433a
parentdeb40d52aaa1989402fc01d65da389dc92fb66fa (diff)
Avoid cyclic queries in name resolution when processing enums
-rw-r--r--crates/ra_hir_def/src/adt.rs8
-rw-r--r--crates/ra_hir_def/src/body.rs47
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs8
3 files changed, 48 insertions, 15 deletions
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index c7c3c0bc7..7c0d93691 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -12,7 +12,7 @@ use ra_prof::profile;
12use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner}; 12use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner};
13 13
14use crate::{ 14use crate::{
15 body::Expander, db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace, 15 body::CfgExpander, db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace,
16 type_ref::TypeRef, visibility::RawVisibility, EnumId, HasModule, LocalEnumVariantId, 16 type_ref::TypeRef, visibility::RawVisibility, EnumId, HasModule, LocalEnumVariantId,
17 LocalStructFieldId, Lookup, ModuleId, StructId, UnionId, VariantId, 17 LocalStructFieldId, Lookup, ModuleId, StructId, UnionId, VariantId,
18}; 18};
@@ -124,7 +124,7 @@ fn lower_enum(
124 124
125impl VariantData { 125impl VariantData {
126 fn new(db: &dyn DefDatabase, flavor: InFile<ast::StructKind>, module_id: ModuleId) -> Self { 126 fn new(db: &dyn DefDatabase, flavor: InFile<ast::StructKind>, module_id: ModuleId) -> Self {
127 let mut expander = Expander::new(db, flavor.file_id, module_id); 127 let mut expander = CfgExpander::new(db, flavor.file_id, module_id.krate);
128 let mut trace = Trace::new_for_arena(); 128 let mut trace = Trace::new_for_arena();
129 match lower_struct(db, &mut expander, &mut trace, &flavor) { 129 match lower_struct(db, &mut expander, &mut trace, &flavor) {
130 StructKind::Tuple => VariantData::Tuple(trace.into_arena()), 130 StructKind::Tuple => VariantData::Tuple(trace.into_arena()),
@@ -178,7 +178,7 @@ impl HasChildSource for VariantId {
178 it.lookup(db).container.module(db), 178 it.lookup(db).container.module(db),
179 ), 179 ),
180 }; 180 };
181 let mut expander = Expander::new(db, src.file_id, module_id); 181 let mut expander = CfgExpander::new(db, src.file_id, module_id.krate);
182 let mut trace = Trace::new_for_map(); 182 let mut trace = Trace::new_for_map();
183 lower_struct(db, &mut expander, &mut trace, &src); 183 lower_struct(db, &mut expander, &mut trace, &src);
184 src.with_value(trace.into_map()) 184 src.with_value(trace.into_map())
@@ -194,7 +194,7 @@ pub enum StructKind {
194 194
195fn lower_struct( 195fn lower_struct(
196 db: &dyn DefDatabase, 196 db: &dyn DefDatabase,
197 expander: &mut Expander, 197 expander: &mut CfgExpander,
198 trace: &mut Trace<StructFieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>, 198 trace: &mut Trace<StructFieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>,
199 ast: &InFile<ast::StructKind>, 199 ast: &InFile<ast::StructKind>,
200) -> StructKind { 200) -> StructKind {
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};
27use ra_cfg::CfgOptions; 27use ra_cfg::CfgOptions;
28use 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.
32pub(crate) struct CfgExpander {
33 cfg_options: CfgOptions,
34 hygiene: Hygiene,
35}
28 36
29pub(crate) struct Expander { 37pub(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
46impl 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
39impl Expander { 66impl 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> {
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 1c33a6520..98c74fe25 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -462,6 +462,14 @@ impl DefCollector<'_> {
462 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => { 462 Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => {
463 tested_by!(glob_enum); 463 tested_by!(glob_enum);
464 // glob import from enum => just import all the variants 464 // glob import from enum => just import all the variants
465
466 // XXX: urgh, so this works by accident! Here, we look at
467 // the enum data, and, in theory, this might require us to
468 // look back at the crate_def_map, creating a cycle. For
469 // example, `enum E { crate::some_macro!(); }`. Luckely, the
470 // only kind of macro that is allowed inside enum is a
471 // `cfg_macro`, and we don't need to run name resolution for
472 // it, but this is sheer luck!
465 let enum_data = self.db.enum_data(e); 473 let enum_data = self.db.enum_data(e);
466 let resolutions = enum_data 474 let resolutions = enum_data
467 .variants 475 .variants