From 49aac9ef63bf11827fca48c16b820ee1c3fe327f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 15:38:17 +0100 Subject: [PATCH 01/11] Add item_scope module --- crates/ra_hir_def/src/item_scope.rs | 1 + crates/ra_hir_def/src/lib.rs | 1 + 2 files changed, 2 insertions(+) create mode 100644 crates/ra_hir_def/src/item_scope.rs diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/crates/ra_hir_def/src/item_scope.rs @@ -0,0 +1 @@ + diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 8ed1599ffb..bf8d6d1d46 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -15,6 +15,7 @@ pub mod type_ref; pub mod builtin_type; pub mod diagnostics; pub mod per_ns; +pub mod item_scope; pub mod dyn_map; pub mod keys; From 0f212b379811dcb26cde3eba160e07a11182fc5a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 15:43:45 +0100 Subject: [PATCH 02/11] Move ModuleScope to a new module --- crates/ra_hir_def/src/body.rs | 3 +- crates/ra_hir_def/src/item_scope.rs | 105 ++++++++++++++++++++ crates/ra_hir_def/src/nameres.rs | 108 +-------------------- crates/ra_hir_def/src/nameres/collector.rs | 3 +- crates/ra_hir_def/src/resolver.rs | 3 +- 5 files changed, 114 insertions(+), 108 deletions(-) diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 401fe0b9b5..d9ce6bcff6 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -17,7 +17,8 @@ use rustc_hash::FxHashMap; use crate::{ db::DefDatabase, expr::{Expr, ExprId, Pat, PatId}, - nameres::{BuiltinShadowMode, CrateDefMap}, + item_scope::BuiltinShadowMode, + nameres::CrateDefMap, path::{ModPath, Path}, src::HasSource, DefWithBodyId, HasModule, Lookup, ModuleDefId, ModuleId, diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 8b13789179..62e7a02cb4 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -1 +1,106 @@ +use hir_expand::name::Name; +use once_cell::sync::Lazy; +use rustc_hash::FxHashMap; +use crate::{per_ns::PerNs, BuiltinType, LocalImportId, MacroDefId, ModuleDefId, TraitId}; + +#[derive(Debug, Default, PartialEq, Eq)] +pub struct ModuleScope { + pub(crate) items: FxHashMap, + /// Macros visable in current module in legacy textual scope + /// + /// For macros invoked by an unquatified identifier like `bar!()`, `legacy_macros` will be searched in first. + /// If it yields no result, then it turns to module scoped `macros`. + /// It macros with name quatified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped, + /// and only normal scoped `macros` will be searched in. + /// + /// Note that this automatically inherit macros defined textually before the definition of module itself. + /// + /// Module scoped macros will be inserted into `items` instead of here. + // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will + // be all resolved to the last one defined if shadowing happens. + pub(crate) legacy_macros: FxHashMap, +} + +static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { + BuiltinType::ALL + .iter() + .map(|(name, ty)| { + (name.clone(), Resolution { def: PerNs::types(ty.clone().into()), import: None }) + }) + .collect() +}); + +/// Shadow mode for builtin type which can be shadowed by module. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum BuiltinShadowMode { + // Prefer Module + Module, + // Prefer Other Types + Other, +} + +/// Legacy macros can only be accessed through special methods like `get_legacy_macros`. +/// Other methods will only resolve values, types and module scoped macros only. +impl ModuleScope { + pub fn entries<'a>(&'a self) -> impl Iterator + 'a { + //FIXME: shadowing + self.items.iter().chain(BUILTIN_SCOPE.iter()) + } + + pub fn declarations(&self) -> impl Iterator + '_ { + self.entries() + .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None }) + .flat_map(|per_ns| { + per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter()) + }) + } + + /// Iterate over all module scoped macros + pub fn macros<'a>(&'a self) -> impl Iterator + 'a { + self.items + .iter() + .filter_map(|(name, res)| res.def.take_macros().map(|macro_| (name, macro_))) + } + + /// Iterate over all legacy textual scoped macros visable at the end of the module + pub fn legacy_macros<'a>(&'a self) -> impl Iterator + 'a { + self.legacy_macros.iter().map(|(name, def)| (name, *def)) + } + + /// Get a name from current module scope, legacy macros are not included + pub fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&Resolution> { + match shadow { + BuiltinShadowMode::Module => self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)), + BuiltinShadowMode::Other => { + let item = self.items.get(name); + if let Some(res) = item { + if let Some(ModuleDefId::ModuleId(_)) = res.def.take_types() { + return BUILTIN_SCOPE.get(name).or(item); + } + } + + item.or_else(|| BUILTIN_SCOPE.get(name)) + } + } + } + + pub fn traits<'a>(&'a self) -> impl Iterator + 'a { + self.items.values().filter_map(|r| match r.def.take_types() { + Some(ModuleDefId::TraitId(t)) => Some(t), + _ => None, + }) + } + + pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option { + self.legacy_macros.get(name).copied() + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Default)] +pub struct Resolution { + /// None for unresolved + pub def: PerNs, + /// ident by which this is imported into local scope. + pub import: Option, +} diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index af52fa36ee..0b486ce163 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -57,8 +57,7 @@ mod tests; use std::sync::Arc; -use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile, MacroDefId}; -use once_cell::sync::Lazy; +use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile}; use ra_arena::Arena; use ra_db::{CrateId, Edition, FileId, FilePosition}; use ra_prof::profile; @@ -69,12 +68,12 @@ use ra_syntax::{ use rustc_hash::FxHashMap; use crate::{ - builtin_type::BuiltinType, db::DefDatabase, + item_scope::{BuiltinShadowMode, ModuleScope}, nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, path::ModPath, per_ns::PerNs, - AstId, ImplId, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, TraitId, + AstId, ImplId, LocalModuleId, ModuleDefId, ModuleId, }; /// Contains all top-level defs from a macro-expanded crate @@ -174,107 +173,6 @@ pub struct ModuleData { pub impls: Vec, } -#[derive(Debug, Default, PartialEq, Eq)] -pub struct ModuleScope { - items: FxHashMap, - /// Macros visable in current module in legacy textual scope - /// - /// For macros invoked by an unquatified identifier like `bar!()`, `legacy_macros` will be searched in first. - /// If it yields no result, then it turns to module scoped `macros`. - /// It macros with name quatified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped, - /// and only normal scoped `macros` will be searched in. - /// - /// Note that this automatically inherit macros defined textually before the definition of module itself. - /// - /// Module scoped macros will be inserted into `items` instead of here. - // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will - // be all resolved to the last one defined if shadowing happens. - legacy_macros: FxHashMap, -} - -static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { - BuiltinType::ALL - .iter() - .map(|(name, ty)| { - (name.clone(), Resolution { def: PerNs::types(ty.clone().into()), import: None }) - }) - .collect() -}); - -/// Shadow mode for builtin type which can be shadowed by module. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum BuiltinShadowMode { - // Prefer Module - Module, - // Prefer Other Types - Other, -} - -/// Legacy macros can only be accessed through special methods like `get_legacy_macros`. -/// Other methods will only resolve values, types and module scoped macros only. -impl ModuleScope { - pub fn entries<'a>(&'a self) -> impl Iterator + 'a { - //FIXME: shadowing - self.items.iter().chain(BUILTIN_SCOPE.iter()) - } - - pub fn declarations(&self) -> impl Iterator + '_ { - self.entries() - .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None }) - .flat_map(|per_ns| { - per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter()) - }) - } - - /// Iterate over all module scoped macros - pub fn macros<'a>(&'a self) -> impl Iterator + 'a { - self.items - .iter() - .filter_map(|(name, res)| res.def.take_macros().map(|macro_| (name, macro_))) - } - - /// Iterate over all legacy textual scoped macros visable at the end of the module - pub fn legacy_macros<'a>(&'a self) -> impl Iterator + 'a { - self.legacy_macros.iter().map(|(name, def)| (name, *def)) - } - - /// Get a name from current module scope, legacy macros are not included - pub fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&Resolution> { - match shadow { - BuiltinShadowMode::Module => self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)), - BuiltinShadowMode::Other => { - let item = self.items.get(name); - if let Some(res) = item { - if let Some(ModuleDefId::ModuleId(_)) = res.def.take_types() { - return BUILTIN_SCOPE.get(name).or(item); - } - } - - item.or_else(|| BUILTIN_SCOPE.get(name)) - } - } - } - - pub fn traits<'a>(&'a self) -> impl Iterator + 'a { - self.items.values().filter_map(|r| match r.def.take_types() { - Some(ModuleDefId::TraitId(t)) => Some(t), - _ => None, - }) - } - - fn get_legacy_macro(&self, name: &Name) -> Option { - self.legacy_macros.get(name).copied() - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Default)] -pub struct Resolution { - /// None for unresolved - pub def: PerNs, - /// ident by which this is imported into local scope. - pub import: Option, -} - impl CrateDefMap { pub(crate) fn crate_def_map_query( // Note that this doesn't have `+ AstDatabase`! diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index e68bf48688..ea6ce5f97b 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -18,9 +18,10 @@ use test_utils::tested_by; use crate::{ attr::Attrs, db::DefDatabase, + item_scope::Resolution, nameres::{ diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, - raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, Resolution, ResolveMode, + raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode, }, path::{ModPath, PathKind}, per_ns::PerNs, diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index af9d194f8a..83013fed3d 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs @@ -14,7 +14,8 @@ use crate::{ db::DefDatabase, expr::{ExprId, PatId}, generics::GenericParams, - nameres::{BuiltinShadowMode, CrateDefMap}, + item_scope::BuiltinShadowMode, + nameres::CrateDefMap, path::{ModPath, PathKind}, per_ns::PerNs, AdtId, AssocContainerId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, From 16ac792f483035f9d9bf6a61b0aefccbdf002188 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 15:44:40 +0100 Subject: [PATCH 03/11] Docs --- crates/ra_hir_def/src/item_scope.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 62e7a02cb4..3c042a94e0 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -1,3 +1,6 @@ +//! Describes items defined or visible (ie, imported) in a certain scope. +//! This is shared between modules and blocks. + use hir_expand::name::Name; use once_cell::sync::Lazy; use rustc_hash::FxHashMap; @@ -7,11 +10,11 @@ use crate::{per_ns::PerNs, BuiltinType, LocalImportId, MacroDefId, ModuleDefId, #[derive(Debug, Default, PartialEq, Eq)] pub struct ModuleScope { pub(crate) items: FxHashMap, - /// Macros visable in current module in legacy textual scope + /// Macros visible in current module in legacy textual scope /// - /// For macros invoked by an unquatified identifier like `bar!()`, `legacy_macros` will be searched in first. + /// For macros invoked by an unqualified identifier like `bar!()`, `legacy_macros` will be searched in first. /// If it yields no result, then it turns to module scoped `macros`. - /// It macros with name quatified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped, + /// It macros with name qualified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped, /// and only normal scoped `macros` will be searched in. /// /// Note that this automatically inherit macros defined textually before the definition of module itself. From 2ce1aa32c40e68ea905c83c315bddfcdd1b7ae26 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 15:45:12 +0100 Subject: [PATCH 04/11] Rename ModuleScope -> ItemScope --- crates/ra_hir_def/src/item_scope.rs | 4 ++-- crates/ra_hir_def/src/nameres.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 3c042a94e0..62c878313b 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -8,7 +8,7 @@ use rustc_hash::FxHashMap; use crate::{per_ns::PerNs, BuiltinType, LocalImportId, MacroDefId, ModuleDefId, TraitId}; #[derive(Debug, Default, PartialEq, Eq)] -pub struct ModuleScope { +pub struct ItemScope { pub(crate) items: FxHashMap, /// Macros visible in current module in legacy textual scope /// @@ -45,7 +45,7 @@ pub enum BuiltinShadowMode { /// Legacy macros can only be accessed through special methods like `get_legacy_macros`. /// Other methods will only resolve values, types and module scoped macros only. -impl ModuleScope { +impl ItemScope { pub fn entries<'a>(&'a self) -> impl Iterator + 'a { //FIXME: shadowing self.items.iter().chain(BUILTIN_SCOPE.iter()) diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index 0b486ce163..3b318719ee 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -69,7 +69,7 @@ use rustc_hash::FxHashMap; use crate::{ db::DefDatabase, - item_scope::{BuiltinShadowMode, ModuleScope}, + item_scope::{BuiltinShadowMode, ItemScope}, nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, path::ModPath, per_ns::PerNs, @@ -165,7 +165,7 @@ impl ModuleOrigin { pub struct ModuleData { pub parent: Option, pub children: FxHashMap, - pub scope: ModuleScope, + pub scope: ItemScope, /// Where does this module come from? pub origin: ModuleOrigin, From 030e540ad19046e2037981ec8e15a6800b86bbe9 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 15:51:43 +0100 Subject: [PATCH 05/11] Reduce visibility --- crates/ra_hir_def/src/item_scope.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 62c878313b..996d06db61 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -36,7 +36,7 @@ static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { /// Shadow mode for builtin type which can be shadowed by module. #[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum BuiltinShadowMode { +pub(crate) enum BuiltinShadowMode { // Prefer Module Module, // Prefer Other Types @@ -60,19 +60,19 @@ impl ItemScope { } /// Iterate over all module scoped macros - pub fn macros<'a>(&'a self) -> impl Iterator + 'a { + pub(crate) fn macros<'a>(&'a self) -> impl Iterator + 'a { self.items .iter() .filter_map(|(name, res)| res.def.take_macros().map(|macro_| (name, macro_))) } - /// Iterate over all legacy textual scoped macros visable at the end of the module - pub fn legacy_macros<'a>(&'a self) -> impl Iterator + 'a { + /// Iterate over all legacy textual scoped macros visible at the end of the module + pub(crate) fn legacy_macros<'a>(&'a self) -> impl Iterator + 'a { self.legacy_macros.iter().map(|(name, def)| (name, *def)) } /// Get a name from current module scope, legacy macros are not included - pub fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&Resolution> { + pub(crate) fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&Resolution> { match shadow { BuiltinShadowMode::Module => self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)), BuiltinShadowMode::Other => { @@ -88,7 +88,7 @@ impl ItemScope { } } - pub fn traits<'a>(&'a self) -> impl Iterator + 'a { + pub(crate) fn traits<'a>(&'a self) -> impl Iterator + 'a { self.items.values().filter_map(|r| match r.def.take_types() { Some(ModuleDefId::TraitId(t)) => Some(t), _ => None, From 1b8ce5b37b597679796b3ebc57afd55af49449b0 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 15:58:20 +0100 Subject: [PATCH 06/11] Move impls to ItemScope --- crates/ra_hir/src/code_model.rs | 2 +- crates/ra_hir_def/src/child_by_source.rs | 2 +- crates/ra_hir_def/src/item_scope.rs | 7 ++++++- crates/ra_hir_def/src/lang_item.rs | 2 +- crates/ra_hir_def/src/nameres.rs | 4 +--- crates/ra_hir_def/src/nameres/collector.rs | 2 +- crates/ra_hir_def/src/nameres/tests/macros.rs | 4 ++-- crates/ra_hir_ty/src/method_resolution.rs | 2 +- crates/ra_hir_ty/src/test_db.rs | 2 +- crates/ra_hir_ty/src/tests.rs | 2 +- 10 files changed, 16 insertions(+), 13 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index ecf883272d..fca3a29509 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -221,7 +221,7 @@ impl Module { pub fn impl_blocks(self, db: &impl DefDatabase) -> Vec { let def_map = db.crate_def_map(self.id.krate); - def_map[self.id.local_id].impls.iter().copied().map(ImplBlock::from).collect() + def_map[self.id.local_id].scope.impls().map(ImplBlock::from).collect() } pub(crate) fn with_module_id(self, module_id: LocalModuleId) -> Module { diff --git a/crates/ra_hir_def/src/child_by_source.rs b/crates/ra_hir_def/src/child_by_source.rs index f5a65ad409..403ba8b578 100644 --- a/crates/ra_hir_def/src/child_by_source.rs +++ b/crates/ra_hir_def/src/child_by_source.rs @@ -80,7 +80,7 @@ impl ChildBySource for ModuleId { module_data.scope.declarations().for_each(|item| add_module_def(db, &mut res, item)); - for &impl_ in module_data.impls.iter() { + for &impl_ in module_data.scope.impls.iter() { let src = impl_.lookup(db).source(db); res[keys::IMPL].insert(src, impl_) } diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 996d06db61..93e579bb0c 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -5,11 +5,12 @@ use hir_expand::name::Name; use once_cell::sync::Lazy; use rustc_hash::FxHashMap; -use crate::{per_ns::PerNs, BuiltinType, LocalImportId, MacroDefId, ModuleDefId, TraitId}; +use crate::{per_ns::PerNs, BuiltinType, ImplId, LocalImportId, MacroDefId, ModuleDefId, TraitId}; #[derive(Debug, Default, PartialEq, Eq)] pub struct ItemScope { pub(crate) items: FxHashMap, + pub(crate) impls: Vec, /// Macros visible in current module in legacy textual scope /// /// For macros invoked by an unqualified identifier like `bar!()`, `legacy_macros` will be searched in first. @@ -59,6 +60,10 @@ impl ItemScope { }) } + pub fn impls(&self) -> impl Iterator + ExactSizeIterator + '_ { + self.impls.iter().copied() + } + /// Iterate over all module scoped macros pub(crate) fn macros<'a>(&'a self) -> impl Iterator + 'a { self.items diff --git a/crates/ra_hir_def/src/lang_item.rs b/crates/ra_hir_def/src/lang_item.rs index f4fdbdcfc7..61b2488158 100644 --- a/crates/ra_hir_def/src/lang_item.rs +++ b/crates/ra_hir_def/src/lang_item.rs @@ -81,7 +81,7 @@ impl LangItems { // Look for impl targets let def_map = db.crate_def_map(module.krate); let module_data = &def_map[module.local_id]; - for &impl_block in module_data.impls.iter() { + for &impl_block in module_data.scope.impls.iter() { self.collect_lang_item(db, impl_block, LangItemTarget::ImplBlockId) } diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index 3b318719ee..5d4ca73a39 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -73,7 +73,7 @@ use crate::{ nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, path::ModPath, per_ns::PerNs, - AstId, ImplId, LocalModuleId, ModuleDefId, ModuleId, + AstId, LocalModuleId, ModuleDefId, ModuleId, }; /// Contains all top-level defs from a macro-expanded crate @@ -169,8 +169,6 @@ pub struct ModuleData { /// Where does this module come from? pub origin: ModuleOrigin, - - pub impls: Vec, } impl CrateDefMap { diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index ea6ce5f97b..c4f6bcd95e 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -667,7 +667,7 @@ where let impl_id = ImplLoc { container, ast_id: AstId::new(self.file_id, ast_id) } .intern(self.def_collector.db); - self.def_collector.def_map.modules[self.module_id].impls.push(impl_id) + self.def_collector.def_map.modules[self.module_id].scope.impls.push(impl_id) } } } diff --git a/crates/ra_hir_def/src/nameres/tests/macros.rs b/crates/ra_hir_def/src/nameres/tests/macros.rs index cfa4ecb1af..d104f5993f 100644 --- a/crates/ra_hir_def/src/nameres/tests/macros.rs +++ b/crates/ra_hir_def/src/nameres/tests/macros.rs @@ -610,7 +610,7 @@ fn expand_derive() { struct Foo; ", ); - assert_eq!(map.modules[map.root].impls.len(), 1); + assert_eq!(map.modules[map.root].scope.impls().len(), 1); } #[test] @@ -622,5 +622,5 @@ fn expand_multiple_derive() { struct Foo; ", ); - assert_eq!(map.modules[map.root].impls.len(), 2); + assert_eq!(map.modules[map.root].scope.impls().len(), 2); } diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index 92fb4c0817..888dc31166 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs @@ -58,7 +58,7 @@ impl CrateImplBlocks { let crate_def_map = db.crate_def_map(krate); for (_module_id, module_data) in crate_def_map.modules.iter() { - for &impl_id in module_data.impls.iter() { + for impl_id in module_data.scope.impls() { match db.impl_trait(impl_id) { Some(tr) => { res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id); diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs index 476f6df52a..1a31b587bb 100644 --- a/crates/ra_hir_ty/src/test_db.rs +++ b/crates/ra_hir_ty/src/test_db.rs @@ -98,7 +98,7 @@ impl TestDB { } } - for &impl_id in crate_def_map[module_id].impls.iter() { + for impl_id in crate_def_map[module_id].scope.impls() { let impl_data = self.impl_data(impl_id); for item in impl_data.items.iter() { if let AssocItemId::FunctionId(f) = item { diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index d724ee1223..d447b45718 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs @@ -182,7 +182,7 @@ fn visit_module( _ => (), } } - for &impl_id in crate_def_map[module_id].impls.iter() { + for impl_id in crate_def_map[module_id].scope.impls() { let impl_data = db.impl_data(impl_id); for &item in impl_data.items.iter() { match item { From 4f9e3f3632f3c03d44a23daf0d9ce4966816af86 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 16:19:28 +0100 Subject: [PATCH 07/11] Fix typos --- crates/ra_hir_def/src/nameres/collector.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index c4f6bcd95e..17c7e691e2 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -226,10 +226,10 @@ where /// Define a legacy textual scoped macro in module /// - /// We use a map `legacy_macros` to store all legacy textual scoped macros visable per module. + /// We use a map `legacy_macros` to store all legacy textual scoped macros visible per module. /// It will clone all macros from parent legacy scope, whose definition is prior to /// the definition of current module. - /// And also, `macro_use` on a module will import all legacy macros visable inside to + /// And also, `macro_use` on a module will import all legacy macros visible inside to /// current legacy scope, with possible shadowing. fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, macro_: MacroDefId) { // Always shadowing From e6b1194f2f33722f0cfed32465f778b256162626 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 16:26:49 +0100 Subject: [PATCH 08/11] Move some code to scope --- crates/ra_hir_def/src/item_scope.rs | 35 ++++++++++++++++++++++ crates/ra_hir_def/src/nameres/collector.rs | 28 ++--------------- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 93e579bb0c..f4fb768cd3 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -47,6 +47,41 @@ pub(crate) enum BuiltinShadowMode { /// Legacy macros can only be accessed through special methods like `get_legacy_macros`. /// Other methods will only resolve values, types and module scoped macros only. impl ItemScope { + pub fn push_res( + &mut self, + name: Name, + res: &Resolution, + import: Option, + ) -> bool { + let mut changed = false; + let existing = self.items.entry(name.clone()).or_default(); + + if existing.def.types.is_none() && res.def.types.is_some() { + existing.def.types = res.def.types; + existing.import = import.or(res.import); + changed = true; + } + if existing.def.values.is_none() && res.def.values.is_some() { + existing.def.values = res.def.values; + existing.import = import.or(res.import); + changed = true; + } + if existing.def.macros.is_none() && res.def.macros.is_some() { + existing.def.macros = res.def.macros; + existing.import = import.or(res.import); + changed = true; + } + + if existing.def.is_none() + && res.def.is_none() + && existing.import.is_none() + && res.import.is_some() + { + existing.import = res.import; + } + changed + } + pub fn entries<'a>(&'a self) -> impl Iterator + 'a { //FIXME: shadowing self.items.iter().chain(BUILTIN_SCOPE.iter()) diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 17c7e691e2..95c499ec9f 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -467,34 +467,10 @@ where // prevent stack overflows (but this shouldn't be possible) panic!("infinite recursion in glob imports!"); } - let module_items = &mut self.def_map.modules[module_id].scope; + let scope = &mut self.def_map.modules[module_id].scope; let mut changed = false; for (name, res) in resolutions { - let existing = module_items.items.entry(name.clone()).or_default(); - - if existing.def.types.is_none() && res.def.types.is_some() { - existing.def.types = res.def.types; - existing.import = import.or(res.import); - changed = true; - } - if existing.def.values.is_none() && res.def.values.is_some() { - existing.def.values = res.def.values; - existing.import = import.or(res.import); - changed = true; - } - if existing.def.macros.is_none() && res.def.macros.is_some() { - existing.def.macros = res.def.macros; - existing.import = import.or(res.import); - changed = true; - } - - if existing.def.is_none() - && res.def.is_none() - && existing.import.is_none() - && res.import.is_some() - { - existing.import = res.import; - } + changed |= scope.push_res(name.clone(), res, import); } if !changed { From 7adb53319d963d0a40906a6847124974da1d5183 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 16:47:22 +0100 Subject: [PATCH 09/11] Make items private --- crates/ra_hir_def/src/item_scope.rs | 76 ++++++++++++---------- crates/ra_hir_def/src/nameres/collector.rs | 12 +--- 2 files changed, 42 insertions(+), 46 deletions(-) diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index f4fb768cd3..ac56986cd4 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -9,7 +9,7 @@ use crate::{per_ns::PerNs, BuiltinType, ImplId, LocalImportId, MacroDefId, Modul #[derive(Debug, Default, PartialEq, Eq)] pub struct ItemScope { - pub(crate) items: FxHashMap, + items: FxHashMap, pub(crate) impls: Vec, /// Macros visible in current module in legacy textual scope /// @@ -47,41 +47,6 @@ pub(crate) enum BuiltinShadowMode { /// Legacy macros can only be accessed through special methods like `get_legacy_macros`. /// Other methods will only resolve values, types and module scoped macros only. impl ItemScope { - pub fn push_res( - &mut self, - name: Name, - res: &Resolution, - import: Option, - ) -> bool { - let mut changed = false; - let existing = self.items.entry(name.clone()).or_default(); - - if existing.def.types.is_none() && res.def.types.is_some() { - existing.def.types = res.def.types; - existing.import = import.or(res.import); - changed = true; - } - if existing.def.values.is_none() && res.def.values.is_some() { - existing.def.values = res.def.values; - existing.import = import.or(res.import); - changed = true; - } - if existing.def.macros.is_none() && res.def.macros.is_some() { - existing.def.macros = res.def.macros; - existing.import = import.or(res.import); - changed = true; - } - - if existing.def.is_none() - && res.def.is_none() - && existing.import.is_none() - && res.import.is_some() - { - existing.import = res.import; - } - changed - } - pub fn entries<'a>(&'a self) -> impl Iterator + 'a { //FIXME: shadowing self.items.iter().chain(BUILTIN_SCOPE.iter()) @@ -138,6 +103,45 @@ impl ItemScope { pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option { self.legacy_macros.get(name).copied() } + + pub(crate) fn push_res( + &mut self, + name: Name, + res: &Resolution, + import: Option, + ) -> bool { + let mut changed = false; + let existing = self.items.entry(name.clone()).or_default(); + + if existing.def.types.is_none() && res.def.types.is_some() { + existing.def.types = res.def.types; + existing.import = import.or(res.import); + changed = true; + } + if existing.def.values.is_none() && res.def.values.is_some() { + existing.def.values = res.def.values; + existing.import = import.or(res.import); + changed = true; + } + if existing.def.macros.is_none() && res.def.macros.is_some() { + existing.def.macros = res.def.macros; + existing.import = import.or(res.import); + changed = true; + } + + if existing.def.is_none() + && res.def.is_none() + && existing.import.is_none() + && res.import.is_some() + { + existing.import = res.import; + } + changed + } + + pub(crate) fn collect_resolutions(&self) -> Vec<(Name, Resolution)> { + self.items.iter().map(|(name, res)| (name.clone(), res.clone())).collect() + } } #[derive(Debug, Clone, PartialEq, Eq, Default)] diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 95c499ec9f..d62fae8a64 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -372,11 +372,7 @@ where let scope = &item_map[m.local_id].scope; // Module scoped macros is included - let items = scope - .items - .iter() - .map(|(name, res)| (name.clone(), res.clone())) - .collect::>(); + let items = scope.collect_resolutions(); self.update(module_id, Some(import_id), &items); } else { @@ -386,11 +382,7 @@ where let scope = &self.def_map[m.local_id].scope; // Module scoped macros is included - let items = scope - .items - .iter() - .map(|(name, res)| (name.clone(), res.clone())) - .collect::>(); + let items = scope.collect_resolutions(); self.update(module_id, Some(import_id), &items); // record the glob import in case we add further items From af42cb5981a1f94116b1da8cfeedb6efdd5aeb01 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 16:55:38 +0100 Subject: [PATCH 10/11] Privitize impls --- crates/ra_hir_def/src/child_by_source.rs | 6 +++--- crates/ra_hir_def/src/item_scope.rs | 6 +++++- crates/ra_hir_def/src/lang_item.rs | 2 +- crates/ra_hir_def/src/nameres/collector.rs | 4 +++- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/crates/ra_hir_def/src/child_by_source.rs b/crates/ra_hir_def/src/child_by_source.rs index 403ba8b578..4488e85020 100644 --- a/crates/ra_hir_def/src/child_by_source.rs +++ b/crates/ra_hir_def/src/child_by_source.rs @@ -80,9 +80,9 @@ impl ChildBySource for ModuleId { module_data.scope.declarations().for_each(|item| add_module_def(db, &mut res, item)); - for &impl_ in module_data.scope.impls.iter() { - let src = impl_.lookup(db).source(db); - res[keys::IMPL].insert(src, impl_) + for imp in module_data.scope.impls() { + let src = imp.lookup(db).source(db); + res[keys::IMPL].insert(src, imp) } res diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index ac56986cd4..f51e97ef9d 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -10,7 +10,7 @@ use crate::{per_ns::PerNs, BuiltinType, ImplId, LocalImportId, MacroDefId, Modul #[derive(Debug, Default, PartialEq, Eq)] pub struct ItemScope { items: FxHashMap, - pub(crate) impls: Vec, + impls: Vec, /// Macros visible in current module in legacy textual scope /// /// For macros invoked by an unqualified identifier like `bar!()`, `legacy_macros` will be searched in first. @@ -104,6 +104,10 @@ impl ItemScope { self.legacy_macros.get(name).copied() } + pub(crate) fn define_impl(&mut self, imp: ImplId) { + self.impls.push(imp) + } + pub(crate) fn push_res( &mut self, name: Name, diff --git a/crates/ra_hir_def/src/lang_item.rs b/crates/ra_hir_def/src/lang_item.rs index 61b2488158..cef061837b 100644 --- a/crates/ra_hir_def/src/lang_item.rs +++ b/crates/ra_hir_def/src/lang_item.rs @@ -81,7 +81,7 @@ impl LangItems { // Look for impl targets let def_map = db.crate_def_map(module.krate); let module_data = &def_map[module.local_id]; - for &impl_block in module_data.scope.impls.iter() { + for impl_block in module_data.scope.impls() { self.collect_lang_item(db, impl_block, LangItemTarget::ImplBlockId) } diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index d62fae8a64..b064ccc9c9 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -635,7 +635,9 @@ where let impl_id = ImplLoc { container, ast_id: AstId::new(self.file_id, ast_id) } .intern(self.def_collector.db); - self.def_collector.def_map.modules[self.module_id].scope.impls.push(impl_id) + self.def_collector.def_map.modules[self.module_id] + .scope + .define_impl(impl_id) } } } From 7a862f0d47e8ae018d449a04c918ea3705785552 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 17:09:13 +0100 Subject: [PATCH 11/11] Make legacy macros private --- crates/ra_hir_def/src/item_scope.rs | 10 +++++++++- crates/ra_hir_def/src/nameres/collector.rs | 10 ++++++---- crates/ra_hir_def/src/nameres/tests.rs | 19 +++++++------------ .../src/nameres/tests/incremental.rs | 4 ++-- 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index f51e97ef9d..6b9be8325d 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -23,7 +23,7 @@ pub struct ItemScope { /// Module scoped macros will be inserted into `items` instead of here. // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will // be all resolved to the last one defined if shadowing happens. - pub(crate) legacy_macros: FxHashMap, + legacy_macros: FxHashMap, } static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { @@ -108,6 +108,10 @@ impl ItemScope { self.impls.push(imp) } + pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroDefId) { + self.legacy_macros.insert(name, mac); + } + pub(crate) fn push_res( &mut self, name: Name, @@ -146,6 +150,10 @@ impl ItemScope { pub(crate) fn collect_resolutions(&self) -> Vec<(Name, Resolution)> { self.items.iter().map(|(name, res)| (name.clone(), res.clone())).collect() } + + pub(crate) fn collect_legacy_macros(&self) -> FxHashMap { + self.legacy_macros.clone() + } } #[derive(Debug, Clone, PartialEq, Eq, Default)] diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index b064ccc9c9..8b641d8b56 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -231,9 +231,9 @@ where /// the definition of current module. /// And also, `macro_use` on a module will import all legacy macros visible inside to /// current legacy scope, with possible shadowing. - fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, macro_: MacroDefId) { + fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, mac: MacroDefId) { // Always shadowing - self.def_map.modules[module_id].scope.legacy_macros.insert(name, macro_); + self.def_map.modules[module_id].scope.define_legacy_macro(name, mac); } /// Import macros from `#[macro_use] extern crate`. @@ -711,7 +711,9 @@ where let res = modules.alloc(ModuleData::default()); modules[res].parent = Some(self.module_id); modules[res].origin = ModuleOrigin::not_sure_file(definition, declaration); - modules[res].scope.legacy_macros = modules[self.module_id].scope.legacy_macros.clone(); + for (name, mac) in modules[self.module_id].scope.collect_legacy_macros() { + modules[res].scope.define_legacy_macro(name, mac) + } modules[self.module_id].children.insert(name.clone(), res); let resolution = Resolution { def: PerNs::types( @@ -875,7 +877,7 @@ where } fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) { - let macros = self.def_collector.def_map[module_id].scope.legacy_macros.clone(); + let macros = self.def_collector.def_map[module_id].scope.collect_legacy_macros(); for (name, macro_) in macros { self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_); } diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs index 61cdd768e8..4e968bcc84 100644 --- a/crates/ra_hir_def/src/nameres/tests.rs +++ b/crates/ra_hir_def/src/nameres/tests.rs @@ -32,27 +32,22 @@ fn render_crate_def_map(map: &CrateDefMap) -> String { *buf += path; *buf += "\n"; - let mut entries = map.modules[module] - .scope - .items - .iter() - .map(|(name, res)| (name, res.def)) - .collect::>(); - entries.sort_by_key(|(name, _)| *name); + let mut entries = map.modules[module].scope.collect_resolutions(); + entries.sort_by_key(|(name, _)| name.clone()); for (name, res) in entries { *buf += &format!("{}:", name); - if res.types.is_some() { + if res.def.types.is_some() { *buf += " t"; } - if res.values.is_some() { + if res.def.values.is_some() { *buf += " v"; } - if res.macros.is_some() { + if res.def.macros.is_some() { *buf += " m"; } - if res.is_none() { + if res.def.is_none() { *buf += " _"; } @@ -587,6 +582,6 @@ mod b { ⋮T: v ⋮ ⋮crate::a - ⋮T: t v + ⋮T: t v "###); } diff --git a/crates/ra_hir_def/src/nameres/tests/incremental.rs b/crates/ra_hir_def/src/nameres/tests/incremental.rs index 903a227719..ef2e9435cf 100644 --- a/crates/ra_hir_def/src/nameres/tests/incremental.rs +++ b/crates/ra_hir_def/src/nameres/tests/incremental.rs @@ -116,7 +116,7 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() { let events = db.log_executed(|| { let crate_def_map = db.crate_def_map(krate); let (_, module_data) = crate_def_map.modules.iter().last().unwrap(); - assert_eq!(module_data.scope.items.len(), 1); + assert_eq!(module_data.scope.collect_resolutions().len(), 1); }); assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events) } @@ -126,7 +126,7 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() { let events = db.log_executed(|| { let crate_def_map = db.crate_def_map(krate); let (_, module_data) = crate_def_map.modules.iter().last().unwrap(); - assert_eq!(module_data.scope.items.len(), 1); + assert_eq!(module_data.scope.collect_resolutions().len(), 1); }); assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events) }