Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/resolver.rs')
-rw-r--r--crates/hir-def/src/resolver.rs29
1 files changed, 19 insertions, 10 deletions
diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs
index db47d743c5..226d6f513f 100644
--- a/crates/hir-def/src/resolver.rs
+++ b/crates/hir-def/src/resolver.rs
@@ -1,5 +1,5 @@
//! Name resolution façade.
-use std::{fmt, hash::BuildHasherDefault};
+use std::{fmt, hash::BuildHasherDefault, mem};
use base_db::CrateId;
use hir_expand::{
@@ -809,7 +809,7 @@ fn resolver_for_scope_(
for scope in scope_chain.into_iter().rev() {
if let Some(block) = scopes.block(scope) {
let def_map = db.block_def_map(block);
- r = r.push_block_scope(def_map, DefMap::ROOT);
+ r = r.push_block_scope(def_map);
// FIXME: This adds as many module scopes as there are blocks, but resolving in each
// already traverses all parents, so this is O(n²). I think we could only store the
// innermost module scope instead?
@@ -835,8 +835,9 @@ impl Resolver {
self.push_scope(Scope::ImplDefScope(impl_def))
}
- fn push_block_scope(self, def_map: Arc<DefMap>, module_id: LocalModuleId) -> Resolver {
- self.push_scope(Scope::BlockScope(ModuleItemMap { def_map, module_id }))
+ fn push_block_scope(self, def_map: Arc<DefMap>) -> Resolver {
+ debug_assert!(def_map.block_id().is_some());
+ self.push_scope(Scope::BlockScope(ModuleItemMap { def_map, module_id: DefMap::ROOT }))
}
fn push_expr_scope(
@@ -986,19 +987,27 @@ pub trait HasResolver: Copy {
impl HasResolver for ModuleId {
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
let mut def_map = self.def_map(db);
- let mut modules: SmallVec<[_; 1]> = smallvec![];
let mut module_id = self.local_id;
+ let mut modules: SmallVec<[_; 1]> = smallvec![];
+
+ if !self.is_block_module() {
+ return Resolver { scopes: vec![], module_scope: ModuleItemMap { def_map, module_id } };
+ }
+
while let Some(parent) = def_map.parent() {
- modules.push((def_map, module_id));
- def_map = parent.def_map(db);
- module_id = parent.local_id;
+ let block_def_map = mem::replace(&mut def_map, parent.def_map(db));
+ modules.push(block_def_map);
+ if !parent.is_block_module() {
+ module_id = parent.local_id;
+ break;
+ }
}
let mut resolver = Resolver {
scopes: Vec::with_capacity(modules.len()),
module_scope: ModuleItemMap { def_map, module_id },
};
- for (def_map, module) in modules.into_iter().rev() {
- resolver = resolver.push_block_scope(def_map, module);
+ for def_map in modules.into_iter().rev() {
+ resolver = resolver.push_block_scope(def_map);
}
resolver
}