From 6d64798a2300858c74b1cc0a22f6d3df578288b3 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 21 Nov 2019 15:39:09 +0300 Subject: Move resolver to hir_def --- crates/ra_hir/src/code_model.rs | 2 +- crates/ra_hir/src/expr.rs | 3 +- crates/ra_hir/src/impl_block.rs | 5 +- crates/ra_hir/src/lib.rs | 3 - crates/ra_hir/src/resolve.rs | 623 ------------------------------ crates/ra_hir/src/source_binder.rs | 16 +- crates/ra_hir/src/ty/autoderef.rs | 3 +- crates/ra_hir/src/ty/infer.rs | 2 +- crates/ra_hir/src/ty/infer/coerce.rs | 6 +- crates/ra_hir/src/ty/infer/expr.rs | 5 +- crates/ra_hir/src/ty/infer/path.rs | 9 +- crates/ra_hir/src/ty/lower.rs | 2 +- crates/ra_hir/src/ty/method_resolution.rs | 2 +- crates/ra_hir_def/src/lib.rs | 1 + crates/ra_hir_def/src/resolver.rs | 608 +++++++++++++++++++++++++++++ 15 files changed, 638 insertions(+), 652 deletions(-) delete mode 100644 crates/ra_hir/src/resolve.rs create mode 100644 crates/ra_hir_def/src/resolver.rs (limited to 'crates') diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 3c891547e..92860fb59 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -11,6 +11,7 @@ use hir_def::{ body::scope::ExprScopes, builtin_type::BuiltinType, nameres::per_ns::PerNs, + resolver::{HasResolver, TypeNs}, traits::TraitData, type_ref::{Mutability, TypeRef}, ContainerId, CrateModuleId, HasModule, ImplId, LocalEnumVariantId, LocalStructFieldId, Lookup, @@ -31,7 +32,6 @@ use crate::{ AstItemDef, ConstId, EnumId, FunctionId, MacroDefId, StaticId, StructId, TraitId, TypeAliasId, }, - resolve::{HasResolver, TypeNs}, ty::{InferenceResult, Namespace, TraitRef}, Either, HasSource, ImportId, Name, Source, Ty, }; diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 9cdc0c645..6b703d8b4 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -2,7 +2,7 @@ use std::sync::Arc; -use hir_def::path::known; +use hir_def::{path::known, resolver::HasResolver}; use hir_expand::diagnostics::DiagnosticSink; use ra_syntax::ast; use ra_syntax::AstPtr; @@ -11,7 +11,6 @@ use rustc_hash::FxHashSet; use crate::{ db::HirDatabase, diagnostics::{MissingFields, MissingOkInTailExpr}, - resolve::HasResolver, ty::{ApplicationTy, InferenceResult, Ty, TypeCtor}, Adt, Function, Name, Path, }; diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index c84ceee62..774fa1d96 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs @@ -1,11 +1,10 @@ //! FIXME: write short doc here -use hir_def::{type_ref::TypeRef, AstItemDef}; -use ra_syntax::ast::{self}; +use hir_def::{resolver::HasResolver, type_ref::TypeRef, AstItemDef}; +use ra_syntax::ast; use crate::{ db::{AstDatabase, DefDatabase, HirDatabase}, - resolve::HasResolver, ty::Ty, AssocItem, Crate, HasSource, ImplBlock, Module, Source, TraitRef, }; diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 095d4964f..76c96bdcf 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -38,7 +38,6 @@ mod impl_block; mod expr; mod lang_item; pub mod generics; -mod resolve; pub mod diagnostics; mod util; @@ -52,8 +51,6 @@ mod test_db; #[cfg(test)] mod marks; -use crate::resolve::Resolver; - pub use crate::{ code_model::{ attrs::{AttrDef, Attrs}, diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs deleted file mode 100644 index a616f0ea5..000000000 --- a/crates/ra_hir/src/resolve.rs +++ /dev/null @@ -1,623 +0,0 @@ -//! Name resolution. -use std::sync::Arc; - -use hir_def::{ - body::scope::{ExprScopes, ScopeId}, - builtin_type::BuiltinType, - db::DefDatabase2, - expr::{ExprId, PatId}, - generics::GenericParams, - nameres::{per_ns::PerNs, CrateDefMap}, - path::{Path, PathKind}, - AdtId, AstItemDef, ConstId, ContainerId, CrateModuleId, DefWithBodyId, EnumId, EnumVariantId, - FunctionId, GenericDefId, ImplId, Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId, - TypeAliasId, UnionId, -}; -use hir_expand::{ - name::{self, Name}, - MacroDefId, -}; -use ra_db::CrateId; -use rustc_hash::FxHashSet; - -#[derive(Debug, Clone, Default)] -pub(crate) struct Resolver { - scopes: Vec, -} - -// FIXME how to store these best -#[derive(Debug, Clone)] -pub(crate) struct ModuleItemMap { - crate_def_map: Arc, - module_id: CrateModuleId, -} - -#[derive(Debug, Clone)] -pub(crate) struct ExprScope { - owner: DefWithBodyId, - expr_scopes: Arc, - scope_id: ScopeId, -} - -#[derive(Debug, Clone)] -pub(crate) enum Scope { - /// All the items and imported names of a module - ModuleScope(ModuleItemMap), - /// Brings the generic parameters of an item into scope - GenericParams { def: GenericDefId, params: Arc }, - /// Brings `Self` in `impl` block into scope - ImplBlockScope(ImplId), - /// Brings `Self` in enum, struct and union definitions into scope - AdtScope(AdtId), - /// Local bindings - ExprScope(ExprScope), -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub(crate) enum TypeNs { - SelfType(ImplId), - GenericParam(u32), - AdtId(AdtId), - AdtSelfType(AdtId), - EnumVariantId(EnumVariantId), - TypeAliasId(TypeAliasId), - BuiltinType(BuiltinType), - TraitId(TraitId), - // Module belong to type ns, but the resolver is used when all module paths - // are fully resolved. - // ModuleId(ModuleId) -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub(crate) enum ResolveValueResult { - ValueNs(ValueNs), - Partial(TypeNs, usize), -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub(crate) enum ValueNs { - LocalBinding(PatId), - FunctionId(FunctionId), - ConstId(ConstId), - StaticId(StaticId), - StructId(StructId), - EnumVariantId(EnumVariantId), -} - -impl Resolver { - /// Resolve known trait from std, like `std::futures::Future` - pub(crate) fn resolve_known_trait( - &self, - db: &impl DefDatabase2, - path: &Path, - ) -> Option { - let res = self.resolve_module_path(db, path).take_types()?; - match res { - ModuleDefId::TraitId(it) => Some(it), - _ => None, - } - } - - /// Resolve known struct from std, like `std::boxed::Box` - pub(crate) fn resolve_known_struct( - &self, - db: &impl DefDatabase2, - path: &Path, - ) -> Option { - let res = self.resolve_module_path(db, path).take_types()?; - match res { - ModuleDefId::AdtId(AdtId::StructId(it)) => Some(it), - _ => None, - } - } - - /// Resolve known enum from std, like `std::result::Result` - pub(crate) fn resolve_known_enum(&self, db: &impl DefDatabase2, path: &Path) -> Option { - let res = self.resolve_module_path(db, path).take_types()?; - match res { - ModuleDefId::AdtId(AdtId::EnumId(it)) => Some(it), - _ => None, - } - } - - /// pub only for source-binder - pub(crate) fn resolve_module_path(&self, db: &impl DefDatabase2, path: &Path) -> PerNs { - let (item_map, module) = match self.module() { - Some(it) => it, - None => return PerNs::none(), - }; - let (module_res, segment_index) = item_map.resolve_path(db, module, path); - if segment_index.is_some() { - return PerNs::none(); - } - module_res - } - - pub(crate) fn resolve_path_in_type_ns( - &self, - db: &impl DefDatabase2, - path: &Path, - ) -> Option<(TypeNs, Option)> { - if path.is_type_relative() { - return None; - } - let first_name = &path.segments.first()?.name; - let skip_to_mod = path.kind != PathKind::Plain; - for scope in self.scopes.iter().rev() { - match scope { - Scope::ExprScope(_) => continue, - Scope::GenericParams { .. } | Scope::ImplBlockScope(_) if skip_to_mod => continue, - - Scope::GenericParams { params, .. } => { - if let Some(param) = params.find_by_name(first_name) { - let idx = if path.segments.len() == 1 { None } else { Some(1) }; - return Some((TypeNs::GenericParam(param.idx), idx)); - } - } - Scope::ImplBlockScope(impl_) => { - if first_name == &name::SELF_TYPE { - let idx = if path.segments.len() == 1 { None } else { Some(1) }; - return Some((TypeNs::SelfType(*impl_), idx)); - } - } - Scope::AdtScope(adt) => { - if first_name == &name::SELF_TYPE { - let idx = if path.segments.len() == 1 { None } else { Some(1) }; - return Some((TypeNs::AdtSelfType(*adt), idx)); - } - } - Scope::ModuleScope(m) => { - let (module_def, idx) = m.crate_def_map.resolve_path(db, m.module_id, path); - let res = match module_def.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, - }; - return Some((res, idx)); - } - } - } - None - } - - pub(crate) fn resolve_path_in_type_ns_fully( - &self, - db: &impl DefDatabase2, - path: &Path, - ) -> Option { - let (res, unresolved) = self.resolve_path_in_type_ns(db, path)?; - if unresolved.is_some() { - return None; - } - Some(res) - } - - pub(crate) fn resolve_path_in_value_ns<'p>( - &self, - db: &impl DefDatabase2, - path: &'p Path, - ) -> Option { - if path.is_type_relative() { - return None; - } - let n_segments = path.segments.len(); - let tmp = name::SELF_PARAM; - let first_name = if path.is_self() { &tmp } else { &path.segments.first()?.name }; - let skip_to_mod = path.kind != PathKind::Plain && !path.is_self(); - for scope in self.scopes.iter().rev() { - match scope { - Scope::AdtScope(_) - | Scope::ExprScope(_) - | Scope::GenericParams { .. } - | Scope::ImplBlockScope(_) - if skip_to_mod => - { - continue - } - - Scope::ExprScope(scope) if n_segments <= 1 => { - let entry = scope - .expr_scopes - .entries(scope.scope_id) - .iter() - .find(|entry| entry.name() == first_name); - - if let Some(e) = entry { - return Some(ResolveValueResult::ValueNs(ValueNs::LocalBinding(e.pat()))); - } - } - Scope::ExprScope(_) => continue, - - Scope::GenericParams { params, .. } if n_segments > 1 => { - if let Some(param) = params.find_by_name(first_name) { - let ty = TypeNs::GenericParam(param.idx); - return Some(ResolveValueResult::Partial(ty, 1)); - } - } - Scope::GenericParams { .. } => continue, - - Scope::ImplBlockScope(impl_) if n_segments > 1 => { - if first_name == &name::SELF_TYPE { - let ty = TypeNs::SelfType(*impl_); - return Some(ResolveValueResult::Partial(ty, 1)); - } - } - Scope::AdtScope(adt) if n_segments > 1 => { - if first_name == &name::SELF_TYPE { - let ty = TypeNs::AdtSelfType(*adt); - return Some(ResolveValueResult::Partial(ty, 1)); - } - } - Scope::ImplBlockScope(_) | Scope::AdtScope(_) => continue, - - Scope::ModuleScope(m) => { - let (module_def, idx) = m.crate_def_map.resolve_path(db, m.module_id, path); - return match idx { - None => { - let value = match module_def.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(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)) - } - }; - } - } - } - None - } - - pub(crate) fn resolve_path_in_value_ns_fully( - &self, - db: &impl DefDatabase2, - path: &Path, - ) -> Option { - match self.resolve_path_in_value_ns(db, path)? { - ResolveValueResult::ValueNs(it) => Some(it), - ResolveValueResult::Partial(..) => None, - } - } - - pub(crate) fn resolve_path_as_macro( - &self, - db: &impl DefDatabase2, - path: &Path, - ) -> Option { - let (item_map, module) = self.module()?; - item_map.resolve_path(db, module, path).0.get_macros() - } - - pub(crate) fn process_all_names( - &self, - db: &impl DefDatabase2, - f: &mut dyn FnMut(Name, ScopeDef), - ) { - for scope in self.scopes.iter().rev() { - scope.process_names(db, f); - } - } - - pub(crate) fn traits_in_scope(&self, db: &impl DefDatabase2) -> FxHashSet { - let mut traits = FxHashSet::default(); - for scope in &self.scopes { - if let Scope::ModuleScope(m) = scope { - if let Some(prelude) = m.crate_def_map.prelude() { - let prelude_def_map = db.crate_def_map(prelude.krate); - traits.extend(prelude_def_map[prelude.module_id].scope.traits()); - } - traits.extend(m.crate_def_map[m.module_id].scope.traits()); - } - } - traits - } - - fn module(&self) -> Option<(&CrateDefMap, CrateModuleId)> { - self.scopes.iter().rev().find_map(|scope| match scope { - Scope::ModuleScope(m) => Some((&*m.crate_def_map, m.module_id)), - - _ => None, - }) - } - - pub(crate) fn krate(&self) -> Option { - self.module().map(|t| t.0.krate()) - } - - pub(crate) fn where_predicates_in_scope<'a>( - &'a self, - ) -> impl Iterator + 'a { - self.scopes - .iter() - .filter_map(|scope| match scope { - Scope::GenericParams { params, .. } => Some(params), - _ => None, - }) - .flat_map(|params| params.where_predicates.iter()) - } - - pub(crate) fn generic_def(&self) -> Option { - self.scopes.iter().find_map(|scope| match scope { - Scope::GenericParams { def, .. } => Some(*def), - _ => None, - }) - } - - pub(crate) fn body_owner(&self) -> Option { - self.scopes.iter().find_map(|scope| match scope { - Scope::ExprScope(it) => Some(it.owner), - _ => None, - }) - } -} - -impl Resolver { - pub(crate) fn push_scope(mut self, scope: Scope) -> Resolver { - self.scopes.push(scope); - self - } - - pub(crate) fn push_generic_params_scope( - self, - db: &impl DefDatabase2, - def: GenericDefId, - ) -> Resolver { - let params = db.generic_params(def); - if params.params.is_empty() { - self - } else { - self.push_scope(Scope::GenericParams { def, params }) - } - } - - pub(crate) fn push_impl_block_scope(self, impl_block: ImplId) -> Resolver { - self.push_scope(Scope::ImplBlockScope(impl_block)) - } - - pub(crate) fn push_module_scope( - self, - crate_def_map: Arc, - module_id: CrateModuleId, - ) -> Resolver { - self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id })) - } - - pub(crate) fn push_expr_scope( - self, - owner: DefWithBodyId, - expr_scopes: Arc, - scope_id: ScopeId, - ) -> Resolver { - self.push_scope(Scope::ExprScope(ExprScope { owner, expr_scopes, scope_id })) - } -} - -pub(crate) enum ScopeDef { - PerNs(PerNs), - ImplSelfType(ImplId), - AdtSelfType(AdtId), - GenericParam(u32), - Local(PatId), -} - -impl Scope { - fn process_names(&self, db: &impl DefDatabase2, f: &mut dyn FnMut(Name, ScopeDef)) { - match self { - Scope::ModuleScope(m) => { - // FIXME: should we provide `self` here? - // f( - // Name::self_param(), - // PerNs::types(Resolution::Def { - // def: m.module.into(), - // }), - // ); - m.crate_def_map[m.module_id].scope.entries().for_each(|(name, res)| { - f(name.clone(), ScopeDef::PerNs(res.def)); - }); - m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| { - f(name.clone(), ScopeDef::PerNs(PerNs::macros(macro_))); - }); - m.crate_def_map.extern_prelude().iter().for_each(|(name, &def)| { - f(name.clone(), ScopeDef::PerNs(PerNs::types(def.into()))); - }); - if let Some(prelude) = m.crate_def_map.prelude() { - let prelude_def_map = db.crate_def_map(prelude.krate); - prelude_def_map[prelude.module_id].scope.entries().for_each(|(name, res)| { - f(name.clone(), ScopeDef::PerNs(res.def)); - }); - } - } - Scope::GenericParams { params, .. } => { - for param in params.params.iter() { - f(param.name.clone(), ScopeDef::GenericParam(param.idx)) - } - } - Scope::ImplBlockScope(i) => { - f(name::SELF_TYPE, ScopeDef::ImplSelfType((*i).into())); - } - Scope::AdtScope(i) => { - f(name::SELF_TYPE, ScopeDef::AdtSelfType((*i).into())); - } - Scope::ExprScope(scope) => { - scope.expr_scopes.entries(scope.scope_id).iter().for_each(|e| { - f(e.name().clone(), ScopeDef::Local(e.pat())); - }); - } - } - } -} - -// needs arbitrary_self_types to be a method... or maybe move to the def? -pub(crate) fn resolver_for_expr( - db: &impl DefDatabase2, - owner: DefWithBodyId, - expr_id: ExprId, -) -> Resolver { - let scopes = db.expr_scopes(owner); - resolver_for_scope(db, owner, scopes.scope_for(expr_id)) -} - -pub(crate) fn resolver_for_scope( - db: &impl DefDatabase2, - owner: DefWithBodyId, - scope_id: Option, -) -> Resolver { - let mut r = owner.resolver(db); - let scopes = db.expr_scopes(owner); - let scope_chain = scopes.scope_chain(scope_id).collect::>(); - for scope in scope_chain.into_iter().rev() { - r = r.push_expr_scope(owner, Arc::clone(&scopes), scope); - } - r -} - -pub(crate) trait HasResolver { - /// Builds a resolver for type references inside this def. - fn resolver(self, db: &impl DefDatabase2) -> Resolver; -} - -impl HasResolver for ModuleId { - fn resolver(self, db: &impl DefDatabase2) -> Resolver { - let def_map = db.crate_def_map(self.krate); - Resolver::default().push_module_scope(def_map, self.module_id) - } -} - -impl HasResolver for TraitId { - fn resolver(self, db: &impl DefDatabase2) -> Resolver { - self.module(db).resolver(db).push_generic_params_scope(db, self.into()) - } -} - -impl HasResolver for AdtId { - fn resolver(self, db: &impl DefDatabase2) -> Resolver { - let module = match self { - AdtId::StructId(it) => it.0.module(db), - AdtId::UnionId(it) => it.0.module(db), - AdtId::EnumId(it) => it.module(db), - }; - - module - .resolver(db) - .push_generic_params_scope(db, self.into()) - .push_scope(Scope::AdtScope(self.into())) - } -} - -impl HasResolver for StructId { - fn resolver(self, db: &impl DefDatabase2) -> Resolver { - AdtId::from(self).resolver(db) - } -} - -impl HasResolver for UnionId { - fn resolver(self, db: &impl DefDatabase2) -> Resolver { - AdtId::from(self).resolver(db) - } -} - -impl HasResolver for EnumId { - fn resolver(self, db: &impl DefDatabase2) -> Resolver { - AdtId::from(self).resolver(db) - } -} - -impl HasResolver for FunctionId { - fn resolver(self, db: &impl DefDatabase2) -> Resolver { - self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into()) - } -} - -impl HasResolver for DefWithBodyId { - fn resolver(self, db: &impl DefDatabase2) -> Resolver { - match self { - DefWithBodyId::ConstId(c) => c.resolver(db), - DefWithBodyId::FunctionId(f) => f.resolver(db), - DefWithBodyId::StaticId(s) => s.resolver(db), - } - } -} - -impl HasResolver for ConstId { - fn resolver(self, db: &impl DefDatabase2) -> Resolver { - self.lookup(db).container.resolver(db) - } -} - -impl HasResolver for StaticId { - fn resolver(self, db: &impl DefDatabase2) -> Resolver { - self.module(db).resolver(db) - } -} - -impl HasResolver for TypeAliasId { - fn resolver(self, db: &impl DefDatabase2) -> Resolver { - self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into()) - } -} - -impl HasResolver for ContainerId { - fn resolver(self, db: &impl DefDatabase2) -> Resolver { - match self { - ContainerId::TraitId(it) => it.resolver(db), - ContainerId::ImplId(it) => it.resolver(db), - ContainerId::ModuleId(it) => it.resolver(db), - } - } -} - -impl HasResolver for GenericDefId { - fn resolver(self, db: &impl DefDatabase2) -> crate::Resolver { - match self { - GenericDefId::FunctionId(inner) => inner.resolver(db), - GenericDefId::AdtId(adt) => adt.resolver(db), - GenericDefId::TraitId(inner) => inner.resolver(db), - GenericDefId::TypeAliasId(inner) => inner.resolver(db), - GenericDefId::ImplId(inner) => inner.resolver(db), - GenericDefId::EnumVariantId(inner) => inner.parent.resolver(db), - GenericDefId::ConstId(inner) => inner.resolver(db), - } - } -} - -impl HasResolver for ImplId { - fn resolver(self, db: &impl DefDatabase2) -> Resolver { - self.module(db) - .resolver(db) - .push_generic_params_scope(db, self.into()) - .push_impl_block_scope(self) - } -} diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 898b823c0..c42ceabdf 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -10,6 +10,7 @@ use std::sync::Arc; use hir_def::{ expr::{ExprId, PatId}, path::known, + resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs}, DefWithBodyId, }; use hir_expand::{name::AsName, AstId, MacroCallId, MacroCallLoc, MacroFileKind, Source}; @@ -24,11 +25,10 @@ use crate::{ db::HirDatabase, expr::{BodySourceMap, ExprScopes, ScopeId}, ids::LocationCtx, - resolve::{self, resolver_for_scope, HasResolver, TypeNs, ValueNs}, ty::method_resolution::{self, implements_trait}, Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function, - GenericParam, HasBody, HirFileId, Local, MacroDef, Module, Name, Path, Resolver, ScopeDef, - Static, Struct, Trait, Ty, TypeAlias, + GenericParam, HasBody, HirFileId, Local, MacroDef, Module, Name, Path, ScopeDef, Static, + Struct, Trait, Ty, TypeAlias, }; fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option { @@ -317,14 +317,14 @@ impl SourceAnalyzer { pub fn process_all_names(&self, db: &impl HirDatabase, f: &mut dyn FnMut(Name, ScopeDef)) { self.resolver.process_all_names(db, &mut |name, def| { let def = match def { - resolve::ScopeDef::PerNs(it) => it.into(), - resolve::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()), - resolve::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()), - resolve::ScopeDef::GenericParam(idx) => { + resolver::ScopeDef::PerNs(it) => it.into(), + resolver::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()), + resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()), + resolver::ScopeDef::GenericParam(idx) => { let parent = self.resolver.generic_def().unwrap().into(); ScopeDef::GenericParam(GenericParam { parent, idx }) } - resolve::ScopeDef::Local(pat_id) => { + resolver::ScopeDef::Local(pat_id) => { let parent = self.resolver.body_owner().unwrap().into(); ScopeDef::Local(Local { parent, pat_id }) } diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs index f77492170..5d8518041 100644 --- a/crates/ra_hir/src/ty/autoderef.rs +++ b/crates/ra_hir/src/ty/autoderef.rs @@ -5,11 +5,12 @@ use std::iter::successors; +use hir_def::resolver::Resolver; use hir_expand::name; use log::{info, warn}; use super::{traits::Solution, Canonical, Substs, Ty, TypeWalk}; -use crate::{db::HirDatabase, generics::HasGenericParams, Resolver}; +use crate::{db::HirDatabase, generics::HasGenericParams}; const AUTODEREF_RECURSION_LIMIT: usize = 10; diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index c3d65afa6..69b13baef 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -23,6 +23,7 @@ use rustc_hash::FxHashMap; use hir_def::{ path::known, + resolver::{HasResolver, Resolver, TypeNs}, type_ref::{Mutability, TypeRef}, AdtId, DefWithBodyId, }; @@ -41,7 +42,6 @@ use crate::{ code_model::TypeAlias, db::HirDatabase, expr::{BindingAnnotation, Body, ExprId, PatId}, - resolve::{HasResolver, Resolver, TypeNs}, ty::infer::diagnostics::InferenceDiagnostic, Adt, AssocItem, ConstData, DefWithBody, FloatTy, FnData, Function, HasBody, IntTy, Path, StructField, Trait, VariantDef, diff --git a/crates/ra_hir/src/ty/infer/coerce.rs b/crates/ra_hir/src/ty/infer/coerce.rs index 6d297c268..0772b9df5 100644 --- a/crates/ra_hir/src/ty/infer/coerce.rs +++ b/crates/ra_hir/src/ty/infer/coerce.rs @@ -4,19 +4,19 @@ //! //! See: https://doc.rust-lang.org/nomicon/coercions.html +use hir_def::resolver::Resolver; use rustc_hash::FxHashMap; - use test_utils::tested_by; -use super::{InferTy, InferenceContext, TypeVarValue}; use crate::{ db::HirDatabase, lang_item::LangItemTarget, - resolve::Resolver, ty::{autoderef, Substs, Ty, TypeCtor, TypeWalk}, Adt, Mutability, }; +use super::{InferTy, InferenceContext, TypeVarValue}; + impl<'a, D: HirDatabase> InferenceContext<'a, D> { /// Unify two types, but may coerce the first one to the second one /// using "implicit coercion rules" if needed. diff --git a/crates/ra_hir/src/ty/infer/expr.rs b/crates/ra_hir/src/ty/infer/expr.rs index 1ac2709f5..ac570075f 100644 --- a/crates/ra_hir/src/ty/infer/expr.rs +++ b/crates/ra_hir/src/ty/infer/expr.rs @@ -6,15 +6,14 @@ use std::sync::Arc; use hir_def::{ builtin_type::Signedness, path::{GenericArg, GenericArgs}, + resolver::resolver_for_expr, }; use hir_expand::name; -use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; use crate::{ db::HirDatabase, expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, generics::{GenericParams, HasGenericParams}, - resolve::resolver_for_expr, ty::{ autoderef, method_resolution, op, CallableDef, InferTy, IntTy, Mutability, Namespace, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, @@ -23,6 +22,8 @@ use crate::{ Adt, Name, }; +use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; + impl<'a, D: HirDatabase> InferenceContext<'a, D> { pub(super) fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { let ty = self.infer_expr_inner(tgt_expr, expected); diff --git a/crates/ra_hir/src/ty/infer/path.rs b/crates/ra_hir/src/ty/infer/path.rs index 55a5dbec7..70136e514 100644 --- a/crates/ra_hir/src/ty/infer/path.rs +++ b/crates/ra_hir/src/ty/infer/path.rs @@ -1,16 +1,19 @@ //! Path expression resolution. -use hir_def::path::PathSegment; +use hir_def::{ + path::PathSegment, + resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, +}; -use super::{ExprOrPatId, InferenceContext, TraitRef}; use crate::{ db::HirDatabase, generics::HasGenericParams, - resolve::{ResolveValueResult, Resolver, TypeNs, ValueNs}, ty::{method_resolution, Namespace, Substs, Ty, TypableDef, TypeWalk}, AssocItem, Container, Function, Name, Path, }; +use super::{ExprOrPatId, InferenceContext, TraitRef}; + impl<'a, D: HirDatabase> InferenceContext<'a, D> { pub(super) fn infer_path( &mut self, diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index e477b2439..c6ad0811b 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs @@ -11,6 +11,7 @@ use std::sync::Arc; use hir_def::{ builtin_type::{BuiltinFloat, BuiltinInt, BuiltinType}, path::{GenericArg, PathSegment}, + resolver::{HasResolver, Resolver, TypeNs}, type_ref::{TypeBound, TypeRef}, GenericDefId, }; @@ -23,7 +24,6 @@ use crate::{ db::HirDatabase, generics::HasGenericParams, generics::{GenericDef, WherePredicate}, - resolve::{HasResolver, Resolver, TypeNs}, ty::{ primitive::{FloatTy, IntTy, Uncertain}, Adt, diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 5ad72ef9f..64adb814d 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -5,11 +5,11 @@ use std::sync::Arc; use arrayvec::ArrayVec; +use hir_def::resolver::Resolver; use rustc_hash::FxHashMap; use crate::{ db::HirDatabase, - resolve::Resolver, ty::primitive::{FloatBitness, Uncertain}, ty::{Ty, TypeCtor}, AssocItem, Crate, Function, ImplBlock, Module, Mutability, Name, Trait, diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 0af41de87..d579f5c7e 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -19,6 +19,7 @@ pub mod expr; pub mod body; pub mod generics; pub mod traits; +pub mod resolver; #[cfg(test)] mod test_db; diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs new file mode 100644 index 000000000..840785baa --- /dev/null +++ b/crates/ra_hir_def/src/resolver.rs @@ -0,0 +1,608 @@ +//! Name resolution façade. +use std::sync::Arc; + +use hir_expand::{ + name::{self, Name}, + MacroDefId, +}; +use ra_db::CrateId; +use rustc_hash::FxHashSet; + +use crate::{ + body::scope::{ExprScopes, ScopeId}, + builtin_type::BuiltinType, + db::DefDatabase2, + expr::{ExprId, PatId}, + generics::GenericParams, + nameres::{per_ns::PerNs, CrateDefMap}, + path::{Path, PathKind}, + AdtId, AstItemDef, ConstId, ContainerId, CrateModuleId, DefWithBodyId, EnumId, EnumVariantId, + FunctionId, GenericDefId, ImplId, Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId, + TypeAliasId, UnionId, +}; + +#[derive(Debug, Clone, Default)] +pub struct Resolver { + scopes: Vec, +} + +// FIXME how to store these best +#[derive(Debug, Clone)] +pub(crate) struct ModuleItemMap { + crate_def_map: Arc, + module_id: CrateModuleId, +} + +#[derive(Debug, Clone)] +pub(crate) struct ExprScope { + owner: DefWithBodyId, + expr_scopes: Arc, + scope_id: ScopeId, +} + +#[derive(Debug, Clone)] +pub(crate) enum Scope { + /// All the items and imported names of a module + ModuleScope(ModuleItemMap), + /// Brings the generic parameters of an item into scope + GenericParams { def: GenericDefId, params: Arc }, + /// Brings `Self` in `impl` block into scope + ImplBlockScope(ImplId), + /// Brings `Self` in enum, struct and union definitions into scope + AdtScope(AdtId), + /// Local bindings + ExprScope(ExprScope), +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum TypeNs { + SelfType(ImplId), + GenericParam(u32), + AdtId(AdtId), + AdtSelfType(AdtId), + EnumVariantId(EnumVariantId), + TypeAliasId(TypeAliasId), + BuiltinType(BuiltinType), + TraitId(TraitId), + // Module belong to type ns, but the resolver is used when all module paths + // are fully resolved. + // ModuleId(ModuleId) +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum ResolveValueResult { + ValueNs(ValueNs), + Partial(TypeNs, usize), +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum ValueNs { + LocalBinding(PatId), + FunctionId(FunctionId), + ConstId(ConstId), + StaticId(StaticId), + StructId(StructId), + EnumVariantId(EnumVariantId), +} + +impl Resolver { + /// Resolve known trait from std, like `std::futures::Future` + pub fn resolve_known_trait(&self, db: &impl DefDatabase2, path: &Path) -> Option { + let res = self.resolve_module_path(db, path).take_types()?; + match res { + ModuleDefId::TraitId(it) => Some(it), + _ => None, + } + } + + /// Resolve known struct from std, like `std::boxed::Box` + pub fn resolve_known_struct(&self, db: &impl DefDatabase2, path: &Path) -> Option { + let res = self.resolve_module_path(db, path).take_types()?; + match res { + ModuleDefId::AdtId(AdtId::StructId(it)) => Some(it), + _ => None, + } + } + + /// Resolve known enum from std, like `std::result::Result` + pub fn resolve_known_enum(&self, db: &impl DefDatabase2, path: &Path) -> Option { + let res = self.resolve_module_path(db, path).take_types()?; + match res { + ModuleDefId::AdtId(AdtId::EnumId(it)) => Some(it), + _ => None, + } + } + + /// pub only for source-binder + pub fn resolve_module_path(&self, db: &impl DefDatabase2, path: &Path) -> PerNs { + let (item_map, module) = match self.module() { + Some(it) => it, + None => return PerNs::none(), + }; + let (module_res, segment_index) = item_map.resolve_path(db, module, path); + if segment_index.is_some() { + return PerNs::none(); + } + module_res + } + + pub fn resolve_path_in_type_ns( + &self, + db: &impl DefDatabase2, + path: &Path, + ) -> Option<(TypeNs, Option)> { + if path.is_type_relative() { + return None; + } + let first_name = &path.segments.first()?.name; + let skip_to_mod = path.kind != PathKind::Plain; + for scope in self.scopes.iter().rev() { + match scope { + Scope::ExprScope(_) => continue, + Scope::GenericParams { .. } | Scope::ImplBlockScope(_) if skip_to_mod => continue, + + Scope::GenericParams { params, .. } => { + if let Some(param) = params.find_by_name(first_name) { + let idx = if path.segments.len() == 1 { None } else { Some(1) }; + return Some((TypeNs::GenericParam(param.idx), idx)); + } + } + Scope::ImplBlockScope(impl_) => { + if first_name == &name::SELF_TYPE { + let idx = if path.segments.len() == 1 { None } else { Some(1) }; + return Some((TypeNs::SelfType(*impl_), idx)); + } + } + Scope::AdtScope(adt) => { + if first_name == &name::SELF_TYPE { + let idx = if path.segments.len() == 1 { None } else { Some(1) }; + return Some((TypeNs::AdtSelfType(*adt), idx)); + } + } + Scope::ModuleScope(m) => { + let (module_def, idx) = m.crate_def_map.resolve_path(db, m.module_id, path); + let res = match module_def.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, + }; + return Some((res, idx)); + } + } + } + None + } + + pub fn resolve_path_in_type_ns_fully( + &self, + db: &impl DefDatabase2, + path: &Path, + ) -> Option { + let (res, unresolved) = self.resolve_path_in_type_ns(db, path)?; + if unresolved.is_some() { + return None; + } + Some(res) + } + + pub fn resolve_path_in_value_ns<'p>( + &self, + db: &impl DefDatabase2, + path: &'p Path, + ) -> Option { + if path.is_type_relative() { + return None; + } + let n_segments = path.segments.len(); + let tmp = name::SELF_PARAM; + let first_name = if path.is_self() { &tmp } else { &path.segments.first()?.name }; + let skip_to_mod = path.kind != PathKind::Plain && !path.is_self(); + for scope in self.scopes.iter().rev() { + match scope { + Scope::AdtScope(_) + | Scope::ExprScope(_) + | Scope::GenericParams { .. } + | Scope::ImplBlockScope(_) + if skip_to_mod => + { + continue + } + + Scope::ExprScope(scope) if n_segments <= 1 => { + let entry = scope + .expr_scopes + .entries(scope.scope_id) + .iter() + .find(|entry| entry.name() == first_name); + + if let Some(e) = entry { + return Some(ResolveValueResult::ValueNs(ValueNs::LocalBinding(e.pat()))); + } + } + Scope::ExprScope(_) => continue, + + Scope::GenericParams { params, .. } if n_segments > 1 => { + if let Some(param) = params.find_by_name(first_name) { + let ty = TypeNs::GenericParam(param.idx); + return Some(ResolveValueResult::Partial(ty, 1)); + } + } + Scope::GenericParams { .. } => continue, + + Scope::ImplBlockScope(impl_) if n_segments > 1 => { + if first_name == &name::SELF_TYPE { + let ty = TypeNs::SelfType(*impl_); + return Some(ResolveValueResult::Partial(ty, 1)); + } + } + Scope::AdtScope(adt) if n_segments > 1 => { + if first_name == &name::SELF_TYPE { + let ty = TypeNs::AdtSelfType(*adt); + return Some(ResolveValueResult::Partial(ty, 1)); + } + } + Scope::ImplBlockScope(_) | Scope::AdtScope(_) => continue, + + Scope::ModuleScope(m) => { + let (module_def, idx) = m.crate_def_map.resolve_path(db, m.module_id, path); + return match idx { + None => { + let value = match module_def.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(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)) + } + }; + } + } + } + None + } + + pub fn resolve_path_in_value_ns_fully( + &self, + db: &impl DefDatabase2, + path: &Path, + ) -> Option { + match self.resolve_path_in_value_ns(db, path)? { + ResolveValueResult::ValueNs(it) => Some(it), + ResolveValueResult::Partial(..) => None, + } + } + + pub fn resolve_path_as_macro(&self, db: &impl DefDatabase2, path: &Path) -> Option { + let (item_map, module) = self.module()?; + item_map.resolve_path(db, module, path).0.get_macros() + } + + pub fn process_all_names(&self, db: &impl DefDatabase2, f: &mut dyn FnMut(Name, ScopeDef)) { + for scope in self.scopes.iter().rev() { + scope.process_names(db, f); + } + } + + pub fn traits_in_scope(&self, db: &impl DefDatabase2) -> FxHashSet { + let mut traits = FxHashSet::default(); + for scope in &self.scopes { + if let Scope::ModuleScope(m) = scope { + if let Some(prelude) = m.crate_def_map.prelude() { + let prelude_def_map = db.crate_def_map(prelude.krate); + traits.extend(prelude_def_map[prelude.module_id].scope.traits()); + } + traits.extend(m.crate_def_map[m.module_id].scope.traits()); + } + } + traits + } + + fn module(&self) -> Option<(&CrateDefMap, CrateModuleId)> { + self.scopes.iter().rev().find_map(|scope| match scope { + Scope::ModuleScope(m) => Some((&*m.crate_def_map, m.module_id)), + + _ => None, + }) + } + + pub fn krate(&self) -> Option { + self.module().map(|t| t.0.krate()) + } + + pub fn where_predicates_in_scope<'a>( + &'a self, + ) -> impl Iterator + 'a { + self.scopes + .iter() + .filter_map(|scope| match scope { + Scope::GenericParams { params, .. } => Some(params), + _ => None, + }) + .flat_map(|params| params.where_predicates.iter()) + } + + pub fn generic_def(&self) -> Option { + self.scopes.iter().find_map(|scope| match scope { + Scope::GenericParams { def, .. } => Some(*def), + _ => None, + }) + } + + pub fn body_owner(&self) -> Option { + self.scopes.iter().find_map(|scope| match scope { + Scope::ExprScope(it) => Some(it.owner), + _ => None, + }) + } +} + +impl Resolver { + pub(crate) fn push_scope(mut self, scope: Scope) -> Resolver { + self.scopes.push(scope); + self + } + + pub(crate) fn push_generic_params_scope( + self, + db: &impl DefDatabase2, + def: GenericDefId, + ) -> Resolver { + let params = db.generic_params(def); + if params.params.is_empty() { + self + } else { + self.push_scope(Scope::GenericParams { def, params }) + } + } + + pub(crate) fn push_impl_block_scope(self, impl_block: ImplId) -> Resolver { + self.push_scope(Scope::ImplBlockScope(impl_block)) + } + + pub(crate) fn push_module_scope( + self, + crate_def_map: Arc, + module_id: CrateModuleId, + ) -> Resolver { + self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id })) + } + + pub(crate) fn push_expr_scope( + self, + owner: DefWithBodyId, + expr_scopes: Arc, + scope_id: ScopeId, + ) -> Resolver { + self.push_scope(Scope::ExprScope(ExprScope { owner, expr_scopes, scope_id })) + } +} + +pub enum ScopeDef { + PerNs(PerNs), + ImplSelfType(ImplId), + AdtSelfType(AdtId), + GenericParam(u32), + Local(PatId), +} + +impl Scope { + fn process_names(&self, db: &impl DefDatabase2, f: &mut dyn FnMut(Name, ScopeDef)) { + match self { + Scope::ModuleScope(m) => { + // FIXME: should we provide `self` here? + // f( + // Name::self_param(), + // PerNs::types(Resolution::Def { + // def: m.module.into(), + // }), + // ); + m.crate_def_map[m.module_id].scope.entries().for_each(|(name, res)| { + f(name.clone(), ScopeDef::PerNs(res.def)); + }); + m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| { + f(name.clone(), ScopeDef::PerNs(PerNs::macros(macro_))); + }); + m.crate_def_map.extern_prelude().iter().for_each(|(name, &def)| { + f(name.clone(), ScopeDef::PerNs(PerNs::types(def.into()))); + }); + if let Some(prelude) = m.crate_def_map.prelude() { + let prelude_def_map = db.crate_def_map(prelude.krate); + prelude_def_map[prelude.module_id].scope.entries().for_each(|(name, res)| { + f(name.clone(), ScopeDef::PerNs(res.def)); + }); + } + } + Scope::GenericParams { params, .. } => { + for param in params.params.iter() { + f(param.name.clone(), ScopeDef::GenericParam(param.idx)) + } + } + Scope::ImplBlockScope(i) => { + f(name::SELF_TYPE, ScopeDef::ImplSelfType((*i).into())); + } + Scope::AdtScope(i) => { + f(name::SELF_TYPE, ScopeDef::AdtSelfType((*i).into())); + } + Scope::ExprScope(scope) => { + scope.expr_scopes.entries(scope.scope_id).iter().for_each(|e| { + f(e.name().clone(), ScopeDef::Local(e.pat())); + }); + } + } + } +} + +// needs arbitrary_self_types to be a method... or maybe move to the def? +pub fn resolver_for_expr( + db: &impl DefDatabase2, + owner: DefWithBodyId, + expr_id: ExprId, +) -> Resolver { + let scopes = db.expr_scopes(owner); + resolver_for_scope(db, owner, scopes.scope_for(expr_id)) +} + +pub fn resolver_for_scope( + db: &impl DefDatabase2, + owner: DefWithBodyId, + scope_id: Option, +) -> Resolver { + let mut r = owner.resolver(db); + let scopes = db.expr_scopes(owner); + let scope_chain = scopes.scope_chain(scope_id).collect::>(); + for scope in scope_chain.into_iter().rev() { + r = r.push_expr_scope(owner, Arc::clone(&scopes), scope); + } + r +} + +pub trait HasResolver { + /// Builds a resolver for type references inside this def. + fn resolver(self, db: &impl DefDatabase2) -> Resolver; +} + +impl HasResolver for ModuleId { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { + let def_map = db.crate_def_map(self.krate); + Resolver::default().push_module_scope(def_map, self.module_id) + } +} + +impl HasResolver for TraitId { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { + self.module(db).resolver(db).push_generic_params_scope(db, self.into()) + } +} + +impl HasResolver for AdtId { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { + let module = match self { + AdtId::StructId(it) => it.0.module(db), + AdtId::UnionId(it) => it.0.module(db), + AdtId::EnumId(it) => it.module(db), + }; + + module + .resolver(db) + .push_generic_params_scope(db, self.into()) + .push_scope(Scope::AdtScope(self.into())) + } +} + +impl HasResolver for StructId { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { + AdtId::from(self).resolver(db) + } +} + +impl HasResolver for UnionId { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { + AdtId::from(self).resolver(db) + } +} + +impl HasResolver for EnumId { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { + AdtId::from(self).resolver(db) + } +} + +impl HasResolver for FunctionId { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { + self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into()) + } +} + +impl HasResolver for DefWithBodyId { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { + match self { + DefWithBodyId::ConstId(c) => c.resolver(db), + DefWithBodyId::FunctionId(f) => f.resolver(db), + DefWithBodyId::StaticId(s) => s.resolver(db), + } + } +} + +impl HasResolver for ConstId { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { + self.lookup(db).container.resolver(db) + } +} + +impl HasResolver for StaticId { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { + self.module(db).resolver(db) + } +} + +impl HasResolver for TypeAliasId { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { + self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into()) + } +} + +impl HasResolver for ContainerId { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { + match self { + ContainerId::TraitId(it) => it.resolver(db), + ContainerId::ImplId(it) => it.resolver(db), + ContainerId::ModuleId(it) => it.resolver(db), + } + } +} + +impl HasResolver for GenericDefId { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { + match self { + GenericDefId::FunctionId(inner) => inner.resolver(db), + GenericDefId::AdtId(adt) => adt.resolver(db), + GenericDefId::TraitId(inner) => inner.resolver(db), + GenericDefId::TypeAliasId(inner) => inner.resolver(db), + GenericDefId::ImplId(inner) => inner.resolver(db), + GenericDefId::EnumVariantId(inner) => inner.parent.resolver(db), + GenericDefId::ConstId(inner) => inner.resolver(db), + } + } +} + +impl HasResolver for ImplId { + fn resolver(self, db: &impl DefDatabase2) -> Resolver { + self.module(db) + .resolver(db) + .push_generic_params_scope(db, self.into()) + .push_impl_block_scope(self) + } +} -- cgit v1.2.3