From e16d9dc5bd78dc0d2139367f25b403926f682df9 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Tue, 9 Feb 2021 17:27:04 +0100 Subject: Use `block_def_map` in `Resolver` This required a few changes to not bail out immediately if a `ModuleScope` doesn't resolve a path. The `LocalItemsScope` hack is now removed. --- crates/hir_def/src/resolver.rs | 215 +++++++++++++++++++---------------------- 1 file changed, 97 insertions(+), 118 deletions(-) diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index f9ad50301..e293aa425 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs @@ -10,7 +10,6 @@ use rustc_hash::FxHashSet; use crate::{ body::scope::{ExprScopes, ScopeId}, - body::Body, builtin_type::BuiltinType, db::DefDatabase, expr::{ExprId, PatId}, @@ -58,8 +57,6 @@ enum Scope { AdtScope(AdtId), /// Local bindings ExprScope(ExprScope), - /// Temporary hack to support local items. - LocalItemsScope(Arc), } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -169,13 +166,7 @@ impl Resolver { for scope in self.scopes.iter().rev() { match scope { Scope::ExprScope(_) => continue, - Scope::GenericParams { .. } - | Scope::ImplDefScope(_) - | Scope::LocalItemsScope(_) - if skip_to_mod => - { - continue - } + Scope::GenericParams { .. } | Scope::ImplDefScope(_) if skip_to_mod => continue, Scope::GenericParams { params, def } => { if let Some(local_id) = params.find_type_by_name(first_name) { @@ -199,41 +190,13 @@ impl Resolver { } } Scope::ModuleScope(m) => { - let (module_def, idx) = m.crate_def_map.resolve_path( - db, - m.module_id, - &path, - BuiltinShadowMode::Other, - ); - let res = to_type_ns(module_def)?; - return Some((res, idx)); - } - Scope::LocalItemsScope(body) => { - let def = body.item_scope.get(first_name); - if let Some(res) = to_type_ns(def) { - return Some((res, None)); + if let Some(res) = m.resolve_path_in_type_ns(db, path) { + return Some(res); } } } } - return None; - fn to_type_ns(per_ns: PerNs) -> Option { - let res = match per_ns.take_types()? { - ModuleDefId::AdtId(it) => TypeNs::AdtId(it), - ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it), - - ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it), - ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it), - - ModuleDefId::TraitId(it) => TypeNs::TraitId(it), - - ModuleDefId::FunctionId(_) - | ModuleDefId::ConstId(_) - | ModuleDefId::StaticId(_) - | ModuleDefId::ModuleId(_) => return None, - }; - Some(res) - } + None } pub fn resolve_path_in_type_ns_fully( @@ -280,7 +243,6 @@ impl Resolver { | Scope::ExprScope(_) | Scope::GenericParams { .. } | Scope::ImplDefScope(_) - | Scope::LocalItemsScope(_) if skip_to_mod => { continue @@ -335,63 +297,14 @@ impl Resolver { } Scope::ModuleScope(m) => { - let (module_def, idx) = m.crate_def_map.resolve_path( - db, - m.module_id, - &path, - BuiltinShadowMode::Other, - ); - return match idx { - None => { - let value = to_value_ns(module_def)?; - Some(ResolveValueResult::ValueNs(value)) - } - Some(idx) => { - let ty = match module_def.take_types()? { - ModuleDefId::AdtId(it) => TypeNs::AdtId(it), - ModuleDefId::TraitId(it) => TypeNs::TraitId(it), - ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it), - ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it), - - ModuleDefId::ModuleId(_) - | ModuleDefId::FunctionId(_) - | ModuleDefId::EnumVariantId(_) - | ModuleDefId::ConstId(_) - | ModuleDefId::StaticId(_) => return None, - }; - Some(ResolveValueResult::Partial(ty, idx)) - } - }; - } - Scope::LocalItemsScope(body) => { - // we don't bother looking in the builtin scope here because there are no builtin values - let def = to_value_ns(body.item_scope.get(first_name)); - - if let Some(res) = def { - return Some(ResolveValueResult::ValueNs(res)); + if let Some(def) = m.resolve_path_in_value_ns(db, path) { + return Some(def); } } } } - return None; - - fn to_value_ns(per_ns: PerNs) -> Option { - let res = match per_ns.take_values()? { - ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it), - ModuleDefId::AdtId(AdtId::StructId(it)) => ValueNs::StructId(it), - ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariantId(it), - ModuleDefId::ConstId(it) => ValueNs::ConstId(it), - ModuleDefId::StaticId(it) => ValueNs::StaticId(it), - - ModuleDefId::AdtId(AdtId::EnumId(_)) - | ModuleDefId::AdtId(AdtId::UnionId(_)) - | ModuleDefId::TraitId(_) - | ModuleDefId::TypeAliasId(_) - | ModuleDefId::BuiltinType(_) - | ModuleDefId::ModuleId(_) => return None, - }; - Some(res) - } + + None } pub fn resolve_path_in_value_ns_fully( @@ -410,11 +323,6 @@ impl Resolver { db: &dyn DefDatabase, path: &ModPath, ) -> Option { - // Search item scope legacy macro first - if let Some(def) = self.resolve_local_macro_def(path) { - return Some(def); - } - let (item_map, module) = self.module_scope()?; item_map.resolve_path(db, module, &path, BuiltinShadowMode::Other).0.take_macros() } @@ -447,16 +355,6 @@ impl Resolver { }) } - fn resolve_local_macro_def(&self, path: &ModPath) -> Option { - let name = path.as_ident()?; - self.scopes.iter().rev().find_map(|scope| { - if let Scope::LocalItemsScope(body) = scope { - return body.item_scope.get_legacy_macro(name); - } - None - }) - } - pub fn module(&self) -> Option { let (def_map, local_id) = self.module_scope()?; Some(def_map.module_id(local_id)) @@ -538,9 +436,6 @@ impl Scope { }); } } - Scope::LocalItemsScope(body) => body.item_scope.entries().for_each(|(name, def)| { - f(name.clone(), ScopeDef::PerNs(def)); - }), &Scope::GenericParams { ref params, def: parent } => { for (local_id, param) in params.types.iter() { if let Some(ref name) = param.name { @@ -584,10 +479,19 @@ pub fn resolver_for_scope( scope_id: Option, ) -> Resolver { let mut r = owner.resolver(db); - r = r.push_local_items_scope(db.body(owner)); let scopes = db.expr_scopes(owner); let scope_chain = scopes.scope_chain(scope_id).collect::>(); for scope in scope_chain.into_iter().rev() { + if let Some(block) = scopes.block(scope) { + if let Some(def_map) = db.block_def_map(block) { + let root = def_map.root(); + r = r.push_module_scope(def_map, root); + // 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? + } + } + r = r.push_expr_scope(owner, Arc::clone(&scopes), scope); } r @@ -612,10 +516,6 @@ impl Resolver { self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id })) } - fn push_local_items_scope(self, body: Arc) -> Resolver { - self.push_scope(Scope::LocalItemsScope(body)) - } - fn push_expr_scope( self, owner: DefWithBodyId, @@ -626,6 +526,85 @@ impl Resolver { } } +impl ModuleItemMap { + pub fn resolve_path_in_value_ns( + &self, + db: &dyn DefDatabase, + path: &ModPath, + ) -> Option { + let (module_def, idx) = + self.crate_def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other); + return match idx { + None => { + let value = to_value_ns(module_def)?; + Some(ResolveValueResult::ValueNs(value)) + } + Some(idx) => { + let ty = match module_def.take_types()? { + ModuleDefId::AdtId(it) => TypeNs::AdtId(it), + ModuleDefId::TraitId(it) => TypeNs::TraitId(it), + ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it), + ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it), + + ModuleDefId::ModuleId(_) + | ModuleDefId::FunctionId(_) + | ModuleDefId::EnumVariantId(_) + | ModuleDefId::ConstId(_) + | ModuleDefId::StaticId(_) => return None, + }; + Some(ResolveValueResult::Partial(ty, idx)) + } + }; + } + + pub fn resolve_path_in_type_ns( + &self, + db: &dyn DefDatabase, + path: &ModPath, + ) -> Option<(TypeNs, Option)> { + let (module_def, idx) = + self.crate_def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other); + let res = to_type_ns(module_def)?; + Some((res, idx)) + } +} + +fn to_value_ns(per_ns: PerNs) -> Option { + let res = match per_ns.take_values()? { + ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it), + ModuleDefId::AdtId(AdtId::StructId(it)) => ValueNs::StructId(it), + ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariantId(it), + ModuleDefId::ConstId(it) => ValueNs::ConstId(it), + ModuleDefId::StaticId(it) => ValueNs::StaticId(it), + + ModuleDefId::AdtId(AdtId::EnumId(_)) + | ModuleDefId::AdtId(AdtId::UnionId(_)) + | ModuleDefId::TraitId(_) + | ModuleDefId::TypeAliasId(_) + | ModuleDefId::BuiltinType(_) + | ModuleDefId::ModuleId(_) => return None, + }; + Some(res) +} + +fn to_type_ns(per_ns: PerNs) -> Option { + let res = match per_ns.take_types()? { + ModuleDefId::AdtId(it) => TypeNs::AdtId(it), + ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it), + + ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it), + ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it), + + ModuleDefId::TraitId(it) => TypeNs::TraitId(it), + + ModuleDefId::FunctionId(_) + | ModuleDefId::ConstId(_) + | ModuleDefId::StaticId(_) + | ModuleDefId::ModuleId(_) => return None, + }; + Some(res) +} + pub trait HasResolver: Copy { /// Builds a resolver for type references inside this def. fn resolver(self, db: &dyn DefDatabase) -> Resolver; -- cgit v1.2.3