diff options
-rw-r--r-- | crates/hir_def/src/body/tests.rs | 7 | ||||
-rw-r--r-- | crates/hir_def/src/nameres.rs | 60 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 9 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/path_resolution.rs | 14 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/tests.rs | 13 |
5 files changed, 67 insertions, 36 deletions
diff --git a/crates/hir_def/src/body/tests.rs b/crates/hir_def/src/body/tests.rs index 404603360..a92134ba7 100644 --- a/crates/hir_def/src/body/tests.rs +++ b/crates/hir_def/src/body/tests.rs | |||
@@ -34,7 +34,7 @@ fn check_diagnostics(ra_fixture: &str) { | |||
34 | db.check_diagnostics(); | 34 | db.check_diagnostics(); |
35 | } | 35 | } |
36 | 36 | ||
37 | fn block_def_map_at(ra_fixture: &str) -> Arc<DefMap> { | 37 | fn block_def_map_at(ra_fixture: &str) -> String { |
38 | let (db, position) = crate::test_db::TestDB::with_position(ra_fixture); | 38 | let (db, position) = crate::test_db::TestDB::with_position(ra_fixture); |
39 | 39 | ||
40 | let krate = db.crate_graph().iter().next().unwrap(); | 40 | let krate = db.crate_graph().iter().next().unwrap(); |
@@ -51,7 +51,7 @@ fn block_def_map_at(ra_fixture: &str) -> Arc<DefMap> { | |||
51 | block = new_block; | 51 | block = new_block; |
52 | } | 52 | } |
53 | None => { | 53 | None => { |
54 | return def_map; | 54 | return def_map.dump(&db); |
55 | } | 55 | } |
56 | } | 56 | } |
57 | } | 57 | } |
@@ -138,8 +138,7 @@ fn block_at_pos(db: &dyn DefDatabase, def_map: &DefMap, position: FilePosition) | |||
138 | } | 138 | } |
139 | 139 | ||
140 | fn check_at(ra_fixture: &str, expect: Expect) { | 140 | fn check_at(ra_fixture: &str, expect: Expect) { |
141 | let def_map = block_def_map_at(ra_fixture); | 141 | let actual = block_def_map_at(ra_fixture); |
142 | let actual = def_map.dump(); | ||
143 | expect.assert_eq(&actual); | 142 | expect.assert_eq(&actual); |
144 | } | 143 | } |
145 | 144 | ||
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index 68998c121..ad2e9bcac 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs | |||
@@ -100,11 +100,12 @@ pub struct DefMap { | |||
100 | } | 100 | } |
101 | 101 | ||
102 | /// For `DefMap`s computed for a block expression, this stores its location in the parent map. | 102 | /// For `DefMap`s computed for a block expression, this stores its location in the parent map. |
103 | #[derive(Debug, PartialEq, Eq)] | 103 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] |
104 | struct BlockInfo { | 104 | struct BlockInfo { |
105 | /// The `BlockId` this `DefMap` was created from. | ||
105 | block: BlockId, | 106 | block: BlockId, |
106 | parent: Arc<DefMap>, | 107 | /// The containing module. |
107 | parent_module: LocalModuleId, | 108 | parent: ModuleId, |
108 | } | 109 | } |
109 | 110 | ||
110 | impl std::ops::Index<LocalModuleId> for DefMap { | 111 | impl std::ops::Index<LocalModuleId> for DefMap { |
@@ -211,17 +212,16 @@ impl DefMap { | |||
211 | block_id: BlockId, | 212 | block_id: BlockId, |
212 | ) -> Option<Arc<DefMap>> { | 213 | ) -> Option<Arc<DefMap>> { |
213 | let block: BlockLoc = db.lookup_intern_block(block_id); | 214 | let block: BlockLoc = db.lookup_intern_block(block_id); |
214 | let parent = block.module.def_map(db); | ||
215 | 215 | ||
216 | let item_tree = db.item_tree(block.ast_id.file_id); | 216 | let item_tree = db.item_tree(block.ast_id.file_id); |
217 | if item_tree.inner_items_of_block(block.ast_id.value).is_empty() { | 217 | if item_tree.inner_items_of_block(block.ast_id.value).is_empty() { |
218 | return None; | 218 | return None; |
219 | } | 219 | } |
220 | 220 | ||
221 | let block_info = | 221 | let block_info = BlockInfo { block: block_id, parent: block.module }; |
222 | BlockInfo { block: block_id, parent, parent_module: block.module.local_id }; | ||
223 | 222 | ||
224 | let mut def_map = DefMap::empty(block.module.krate, block_info.parent.edition); | 223 | let parent_map = block.module.def_map(db); |
224 | let mut def_map = DefMap::empty(block.module.krate, parent_map.edition); | ||
225 | def_map.block = Some(block_info); | 225 | def_map.block = Some(block_info); |
226 | 226 | ||
227 | let def_map = collector::collect_defs(db, def_map, Some(block.ast_id)); | 227 | let def_map = collector::collect_defs(db, def_map, Some(block.ast_id)); |
@@ -289,9 +289,15 @@ impl DefMap { | |||
289 | ModuleId { krate: self.krate, local_id, block } | 289 | ModuleId { krate: self.krate, local_id, block } |
290 | } | 290 | } |
291 | 291 | ||
292 | pub(crate) fn crate_root(&self) -> ModuleId { | 292 | pub(crate) fn crate_root(&self, db: &dyn DefDatabase) -> ModuleId { |
293 | let (root_map, _) = self.ancestor_maps(self.root).last().unwrap(); | 293 | self.with_ancestor_maps(db, self.root, &mut |def_map, _module| { |
294 | root_map.module_id(root_map.root) | 294 | if def_map.block.is_none() { |
295 | Some(def_map.module_id(def_map.root)) | ||
296 | } else { | ||
297 | None | ||
298 | } | ||
299 | }) | ||
300 | .expect("DefMap chain without root") | ||
295 | } | 301 | } |
296 | 302 | ||
297 | pub(crate) fn resolve_path( | 303 | pub(crate) fn resolve_path( |
@@ -306,26 +312,42 @@ impl DefMap { | |||
306 | (res.resolved_def, res.segment_index) | 312 | (res.resolved_def, res.segment_index) |
307 | } | 313 | } |
308 | 314 | ||
309 | /// Iterates over the containing `DefMap`s, if `self` is a `DefMap` corresponding to a block | 315 | /// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module. |
310 | /// expression. | 316 | /// |
311 | fn ancestor_maps( | 317 | /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns |
318 | /// `None`, iteration continues. | ||
319 | fn with_ancestor_maps<T>( | ||
312 | &self, | 320 | &self, |
321 | db: &dyn DefDatabase, | ||
313 | local_mod: LocalModuleId, | 322 | local_mod: LocalModuleId, |
314 | ) -> impl Iterator<Item = (&DefMap, LocalModuleId)> { | 323 | f: &mut dyn FnMut(&DefMap, LocalModuleId) -> Option<T>, |
315 | std::iter::successors(Some((self, local_mod)), |(map, _)| { | 324 | ) -> Option<T> { |
316 | map.block.as_ref().map(|block| (&*block.parent, block.parent_module)) | 325 | if let Some(it) = f(self, local_mod) { |
317 | }) | 326 | return Some(it); |
327 | } | ||
328 | let mut block = self.block; | ||
329 | while let Some(block_info) = block { | ||
330 | let parent = block_info.parent.def_map(db); | ||
331 | if let Some(it) = f(&parent, block_info.parent.local_id) { | ||
332 | return Some(it); | ||
333 | } | ||
334 | block = parent.block; | ||
335 | } | ||
336 | |||
337 | None | ||
318 | } | 338 | } |
319 | 339 | ||
320 | // FIXME: this can use some more human-readable format (ideally, an IR | 340 | // FIXME: this can use some more human-readable format (ideally, an IR |
321 | // even), as this should be a great debugging aid. | 341 | // even), as this should be a great debugging aid. |
322 | pub fn dump(&self) -> String { | 342 | pub fn dump(&self, db: &dyn DefDatabase) -> String { |
323 | let mut buf = String::new(); | 343 | let mut buf = String::new(); |
344 | let mut arc; | ||
324 | let mut current_map = self; | 345 | let mut current_map = self; |
325 | while let Some(block) = ¤t_map.block { | 346 | while let Some(block) = ¤t_map.block { |
326 | go(&mut buf, current_map, "block scope", current_map.root); | 347 | go(&mut buf, current_map, "block scope", current_map.root); |
327 | buf.push('\n'); | 348 | buf.push('\n'); |
328 | current_map = &*block.parent; | 349 | arc = block.parent.def_map(db); |
350 | current_map = &*arc; | ||
329 | } | 351 | } |
330 | go(&mut buf, current_map, "crate", current_map.root); | 352 | go(&mut buf, current_map, "crate", current_map.root); |
331 | return buf; | 353 | return buf; |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 6e86cc4a7..f904a97de 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -1449,10 +1449,11 @@ impl ModCollector<'_, '_> { | |||
1449 | if let Some(macro_call_id) = | 1449 | if let Some(macro_call_id) = |
1450 | ast_id.as_call_id(self.def_collector.db, self.def_collector.def_map.krate, |path| { | 1450 | ast_id.as_call_id(self.def_collector.db, self.def_collector.def_map.krate, |path| { |
1451 | path.as_ident().and_then(|name| { | 1451 | path.as_ident().and_then(|name| { |
1452 | self.def_collector | 1452 | self.def_collector.def_map.with_ancestor_maps( |
1453 | .def_map | 1453 | self.def_collector.db, |
1454 | .ancestor_maps(self.module_id) | 1454 | self.module_id, |
1455 | .find_map(|(map, module)| map[module].scope.get_legacy_macro(&name)) | 1455 | &mut |map, module| map[module].scope.get_legacy_macro(&name), |
1456 | ) | ||
1456 | }) | 1457 | }) |
1457 | }) | 1458 | }) |
1458 | { | 1459 | { |
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs index ecf75c777..2a3ac5d7b 100644 --- a/crates/hir_def/src/nameres/path_resolution.rs +++ b/crates/hir_def/src/nameres/path_resolution.rs | |||
@@ -110,6 +110,7 @@ impl DefMap { | |||
110 | let mut result = ResolvePathResult::empty(ReachedFixedPoint::No); | 110 | let mut result = ResolvePathResult::empty(ReachedFixedPoint::No); |
111 | result.segment_index = Some(usize::max_value()); | 111 | result.segment_index = Some(usize::max_value()); |
112 | 112 | ||
113 | let mut arc; | ||
113 | let mut current_map = self; | 114 | let mut current_map = self; |
114 | loop { | 115 | loop { |
115 | let new = current_map.resolve_path_fp_with_macro_single( | 116 | let new = current_map.resolve_path_fp_with_macro_single( |
@@ -131,8 +132,9 @@ impl DefMap { | |||
131 | 132 | ||
132 | match ¤t_map.block { | 133 | match ¤t_map.block { |
133 | Some(block) => { | 134 | Some(block) => { |
134 | current_map = &block.parent; | 135 | original_module = block.parent.local_id; |
135 | original_module = block.parent_module; | 136 | arc = block.parent.def_map(db); |
137 | current_map = &*arc; | ||
136 | } | 138 | } |
137 | None => return result, | 139 | None => return result, |
138 | } | 140 | } |
@@ -152,7 +154,7 @@ impl DefMap { | |||
152 | PathKind::DollarCrate(krate) => { | 154 | PathKind::DollarCrate(krate) => { |
153 | if krate == self.krate { | 155 | if krate == self.krate { |
154 | mark::hit!(macro_dollar_crate_self); | 156 | mark::hit!(macro_dollar_crate_self); |
155 | PerNs::types(self.crate_root().into(), Visibility::Public) | 157 | PerNs::types(self.crate_root(db).into(), Visibility::Public) |
156 | } else { | 158 | } else { |
157 | let def_map = db.crate_def_map(krate); | 159 | let def_map = db.crate_def_map(krate); |
158 | let module = def_map.module_id(def_map.root); | 160 | let module = def_map.module_id(def_map.root); |
@@ -160,7 +162,7 @@ impl DefMap { | |||
160 | PerNs::types(module.into(), Visibility::Public) | 162 | PerNs::types(module.into(), Visibility::Public) |
161 | } | 163 | } |
162 | } | 164 | } |
163 | PathKind::Crate => PerNs::types(self.crate_root().into(), Visibility::Public), | 165 | PathKind::Crate => PerNs::types(self.crate_root(db).into(), Visibility::Public), |
164 | // plain import or absolute path in 2015: crate-relative with | 166 | // plain import or absolute path in 2015: crate-relative with |
165 | // fallback to extern prelude (with the simplification in | 167 | // fallback to extern prelude (with the simplification in |
166 | // rust-lang/rust#57745) | 168 | // rust-lang/rust#57745) |
@@ -206,10 +208,10 @@ impl DefMap { | |||
206 | segments: path.segments.clone(), | 208 | segments: path.segments.clone(), |
207 | }; | 209 | }; |
208 | log::debug!("`super` path: {} -> {} in parent map", path, new_path); | 210 | log::debug!("`super` path: {} -> {} in parent map", path, new_path); |
209 | return block.parent.resolve_path_fp_with_macro( | 211 | return block.parent.def_map(db).resolve_path_fp_with_macro( |
210 | db, | 212 | db, |
211 | mode, | 213 | mode, |
212 | block.parent_module, | 214 | block.parent.local_id, |
213 | &new_path, | 215 | &new_path, |
214 | shadow, | 216 | shadow, |
215 | ); | 217 | ); |
diff --git a/crates/hir_def/src/nameres/tests.rs b/crates/hir_def/src/nameres/tests.rs index 723481c36..bd3e2701b 100644 --- a/crates/hir_def/src/nameres/tests.rs +++ b/crates/hir_def/src/nameres/tests.rs | |||
@@ -11,7 +11,9 @@ use base_db::{fixture::WithFixture, SourceDatabase}; | |||
11 | use expect_test::{expect, Expect}; | 11 | use expect_test::{expect, Expect}; |
12 | use test_utils::mark; | 12 | use test_utils::mark; |
13 | 13 | ||
14 | use crate::{db::DefDatabase, nameres::*, test_db::TestDB}; | 14 | use crate::{db::DefDatabase, test_db::TestDB}; |
15 | |||
16 | use super::DefMap; | ||
15 | 17 | ||
16 | fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> { | 18 | fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> { |
17 | let db = TestDB::with_files(ra_fixture); | 19 | let db = TestDB::with_files(ra_fixture); |
@@ -19,9 +21,14 @@ fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> { | |||
19 | db.crate_def_map(krate) | 21 | db.crate_def_map(krate) |
20 | } | 22 | } |
21 | 23 | ||
24 | fn render_crate_def_map(ra_fixture: &str) -> String { | ||
25 | let db = TestDB::with_files(ra_fixture); | ||
26 | let krate = db.crate_graph().iter().next().unwrap(); | ||
27 | db.crate_def_map(krate).dump(&db) | ||
28 | } | ||
29 | |||
22 | fn check(ra_fixture: &str, expect: Expect) { | 30 | fn check(ra_fixture: &str, expect: Expect) { |
23 | let def_map = compute_crate_def_map(ra_fixture); | 31 | let actual = render_crate_def_map(ra_fixture); |
24 | let actual = def_map.dump(); | ||
25 | expect.assert_eq(&actual); | 32 | expect.assert_eq(&actual); |
26 | } | 33 | } |
27 | 34 | ||