aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/nameres.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src/nameres.rs')
-rw-r--r--crates/hir_def/src/nameres.rs107
1 files changed, 62 insertions, 45 deletions
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs
index 0a15fc470..ad2e9bcac 100644
--- a/crates/hir_def/src/nameres.rs
+++ b/crates/hir_def/src/nameres.rs
@@ -73,7 +73,15 @@ use crate::{
73 AstId, BlockId, BlockLoc, LocalModuleId, ModuleDefId, ModuleId, 73 AstId, BlockId, BlockLoc, LocalModuleId, ModuleDefId, ModuleId,
74}; 74};
75 75
76/// Contains all top-level defs from a macro-expanded crate 76/// Contains the results of (early) name resolution.
77///
78/// A `DefMap` stores the module tree and the definitions that are in scope in every module after
79/// item-level macros have been expanded.
80///
81/// Every crate has a primary `DefMap` whose root is the crate's main file (`main.rs`/`lib.rs`),
82/// computed by the `crate_def_map` query. Additionally, every block expression introduces the
83/// opportunity to write arbitrary item and module hierarchies, and thus gets its own `DefMap` that
84/// is computed by the `block_def_map` query.
77#[derive(Debug, PartialEq, Eq)] 85#[derive(Debug, PartialEq, Eq)]
78pub struct DefMap { 86pub struct DefMap {
79 _c: Count<Self>, 87 _c: Count<Self>,
@@ -91,11 +99,13 @@ pub struct DefMap {
91 diagnostics: Vec<DefDiagnostic>, 99 diagnostics: Vec<DefDiagnostic>,
92} 100}
93 101
94#[derive(Debug, PartialEq, Eq)] 102/// For `DefMap`s computed for a block expression, this stores its location in the parent map.
103#[derive(Debug, PartialEq, Eq, Clone, Copy)]
95struct BlockInfo { 104struct BlockInfo {
105 /// The `BlockId` this `DefMap` was created from.
96 block: BlockId, 106 block: BlockId,
97 parent: Arc<DefMap>, 107 /// The containing module.
98 parent_module: LocalModuleId, 108 parent: ModuleId,
99} 109}
100 110
101impl std::ops::Index<LocalModuleId> for DefMap { 111impl std::ops::Index<LocalModuleId> for DefMap {
@@ -197,21 +207,25 @@ impl DefMap {
197 Arc::new(def_map) 207 Arc::new(def_map)
198 } 208 }
199 209
200 pub(crate) fn block_def_map_query(db: &dyn DefDatabase, block_id: BlockId) -> Arc<DefMap> { 210 pub(crate) fn block_def_map_query(
211 db: &dyn DefDatabase,
212 block_id: BlockId,
213 ) -> Option<Arc<DefMap>> {
201 let block: BlockLoc = db.lookup_intern_block(block_id); 214 let block: BlockLoc = db.lookup_intern_block(block_id);
202 let parent = block.module.def_map(db);
203 215
204 // FIXME: It would be good to just return the parent map when the block has no items, but 216 let item_tree = db.item_tree(block.ast_id.file_id);
205 // we rely on `def_map.block` in a few places, which is `Some` for the inner `DefMap`. 217 if item_tree.inner_items_of_block(block.ast_id.value).is_empty() {
218 return None;
219 }
206 220
207 let block_info = 221 let block_info = BlockInfo { block: block_id, parent: block.module };
208 BlockInfo { block: block_id, parent, parent_module: block.module.local_id };
209 222
210 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);
211 def_map.block = Some(block_info); 225 def_map.block = Some(block_info);
212 226
213 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));
214 Arc::new(def_map) 228 Some(Arc::new(def_map))
215 } 229 }
216 230
217 fn empty(krate: CrateId, edition: Edition) -> DefMap { 231 fn empty(krate: CrateId, edition: Edition) -> DefMap {
@@ -275,9 +289,15 @@ impl DefMap {
275 ModuleId { krate: self.krate, local_id, block } 289 ModuleId { krate: self.krate, local_id, block }
276 } 290 }
277 291
278 pub(crate) fn crate_root(&self) -> ModuleId { 292 pub(crate) fn crate_root(&self, db: &dyn DefDatabase) -> ModuleId {
279 let (root_map, _) = self.ancestor_maps(self.root).last().unwrap(); 293 self.with_ancestor_maps(db, self.root, &mut |def_map, _module| {
280 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")
281 } 301 }
282 302
283 pub(crate) fn resolve_path( 303 pub(crate) fn resolve_path(
@@ -292,25 +312,42 @@ impl DefMap {
292 (res.resolved_def, res.segment_index) 312 (res.resolved_def, res.segment_index)
293 } 313 }
294 314
295 /// 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.
296 /// expression. 316 ///
297 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>(
298 &self, 320 &self,
321 db: &dyn DefDatabase,
299 local_mod: LocalModuleId, 322 local_mod: LocalModuleId,
300 ) -> impl Iterator<Item = (&DefMap, LocalModuleId)> { 323 f: &mut dyn FnMut(&DefMap, LocalModuleId) -> Option<T>,
301 std::iter::successors(Some((self, local_mod)), |(map, _)| { 324 ) -> Option<T> {
302 map.block.as_ref().map(|block| (&*block.parent, block.parent_module)) 325 if let Some(it) = f(self, local_mod) {
303 }) 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
304 } 338 }
305 339
306 // 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
307 // even), as this should be a great debugging aid. 341 // even), as this should be a great debugging aid.
308 pub fn dump(&self) -> String { 342 pub fn dump(&self, db: &dyn DefDatabase) -> String {
309 let mut buf = String::new(); 343 let mut buf = String::new();
344 let mut arc;
310 let mut current_map = self; 345 let mut current_map = self;
311 while let Some(block) = &current_map.block { 346 while let Some(block) = &current_map.block {
312 go(&mut buf, current_map, "block scope", current_map.root); 347 go(&mut buf, current_map, "block scope", current_map.root);
313 current_map = &*block.parent; 348 buf.push('\n');
349 arc = block.parent.def_map(db);
350 current_map = &*arc;
314 } 351 }
315 go(&mut buf, current_map, "crate", current_map.root); 352 go(&mut buf, current_map, "crate", current_map.root);
316 return buf; 353 return buf;
@@ -318,27 +355,7 @@ impl DefMap {
318 fn go(buf: &mut String, map: &DefMap, path: &str, module: LocalModuleId) { 355 fn go(buf: &mut String, map: &DefMap, path: &str, module: LocalModuleId) {
319 format_to!(buf, "{}\n", path); 356 format_to!(buf, "{}\n", path);
320 357
321 let mut entries: Vec<_> = map.modules[module].scope.resolutions().collect(); 358 map.modules[module].scope.dump(buf);
322 entries.sort_by_key(|(name, _)| name.clone());
323
324 for (name, def) in entries {
325 format_to!(buf, "{}:", name.map_or("_".to_string(), |name| name.to_string()));
326
327 if def.types.is_some() {
328 buf.push_str(" t");
329 }
330 if def.values.is_some() {
331 buf.push_str(" v");
332 }
333 if def.macros.is_some() {
334 buf.push_str(" m");
335 }
336 if def.is_none() {
337 buf.push_str(" _");
338 }
339
340 buf.push('\n');
341 }
342 359
343 for (name, child) in map.modules[module].children.iter() { 360 for (name, child) in map.modules[module].children.iter() {
344 let path = format!("{}::{}", path, name); 361 let path = format!("{}::{}", path, name);