mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
Merge #2624
2624: Separate module item from module scope r=matklad a=matklad bors r+ Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
6eab968c60
15 changed files with 210 additions and 178 deletions
|
@ -221,7 +221,7 @@ impl Module {
|
||||||
|
|
||||||
pub fn impl_blocks(self, db: &impl DefDatabase) -> Vec<ImplBlock> {
|
pub fn impl_blocks(self, db: &impl DefDatabase) -> Vec<ImplBlock> {
|
||||||
let def_map = db.crate_def_map(self.id.krate);
|
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 {
|
pub(crate) fn with_module_id(self, module_id: LocalModuleId) -> Module {
|
||||||
|
|
|
@ -17,7 +17,8 @@ use rustc_hash::FxHashMap;
|
||||||
use crate::{
|
use crate::{
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
expr::{Expr, ExprId, Pat, PatId},
|
expr::{Expr, ExprId, Pat, PatId},
|
||||||
nameres::{BuiltinShadowMode, CrateDefMap},
|
item_scope::BuiltinShadowMode,
|
||||||
|
nameres::CrateDefMap,
|
||||||
path::{ModPath, Path},
|
path::{ModPath, Path},
|
||||||
src::HasSource,
|
src::HasSource,
|
||||||
DefWithBodyId, HasModule, Lookup, ModuleDefId, ModuleId,
|
DefWithBodyId, HasModule, Lookup, ModuleDefId, ModuleId,
|
||||||
|
|
|
@ -80,9 +80,9 @@ impl ChildBySource for ModuleId {
|
||||||
|
|
||||||
module_data.scope.declarations().for_each(|item| add_module_def(db, &mut res, item));
|
module_data.scope.declarations().for_each(|item| add_module_def(db, &mut res, item));
|
||||||
|
|
||||||
for &impl_ in module_data.impls.iter() {
|
for imp in module_data.scope.impls() {
|
||||||
let src = impl_.lookup(db).source(db);
|
let src = imp.lookup(db).source(db);
|
||||||
res[keys::IMPL].insert(src, impl_)
|
res[keys::IMPL].insert(src, imp)
|
||||||
}
|
}
|
||||||
|
|
||||||
res
|
res
|
||||||
|
|
165
crates/ra_hir_def/src/item_scope.rs
Normal file
165
crates/ra_hir_def/src/item_scope.rs
Normal file
|
@ -0,0 +1,165 @@
|
||||||
|
//! 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;
|
||||||
|
|
||||||
|
use crate::{per_ns::PerNs, BuiltinType, ImplId, LocalImportId, MacroDefId, ModuleDefId, TraitId};
|
||||||
|
|
||||||
|
#[derive(Debug, Default, PartialEq, Eq)]
|
||||||
|
pub struct ItemScope {
|
||||||
|
items: FxHashMap<Name, Resolution>,
|
||||||
|
impls: Vec<ImplId>,
|
||||||
|
/// 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.
|
||||||
|
/// If it yields no result, then it turns to module scoped `macros`.
|
||||||
|
/// 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.
|
||||||
|
///
|
||||||
|
/// 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<Name, MacroDefId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
static BUILTIN_SCOPE: Lazy<FxHashMap<Name, Resolution>> = 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(crate) 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 ItemScope {
|
||||||
|
pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, &'a Resolution)> + 'a {
|
||||||
|
//FIXME: shadowing
|
||||||
|
self.items.iter().chain(BUILTIN_SCOPE.iter())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
|
||||||
|
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())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn impls(&self) -> impl Iterator<Item = ImplId> + ExactSizeIterator + '_ {
|
||||||
|
self.impls.iter().copied()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Iterate over all module scoped macros
|
||||||
|
pub(crate) fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
|
||||||
|
self.items
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(name, res)| res.def.take_macros().map(|macro_| (name, macro_)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Iterate over all legacy textual scoped macros visible at the end of the module
|
||||||
|
pub(crate) fn legacy_macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
|
||||||
|
self.legacy_macros.iter().map(|(name, def)| (name, *def))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a name from current module scope, legacy macros are not included
|
||||||
|
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 => {
|
||||||
|
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(crate) fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + '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<MacroDefId> {
|
||||||
|
self.legacy_macros.get(name).copied()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn define_impl(&mut self, imp: ImplId) {
|
||||||
|
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,
|
||||||
|
res: &Resolution,
|
||||||
|
import: Option<LocalImportId>,
|
||||||
|
) -> 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()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, MacroDefId> {
|
||||||
|
self.legacy_macros.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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<LocalImportId>,
|
||||||
|
}
|
|
@ -81,7 +81,7 @@ impl LangItems {
|
||||||
// Look for impl targets
|
// Look for impl targets
|
||||||
let def_map = db.crate_def_map(module.krate);
|
let def_map = db.crate_def_map(module.krate);
|
||||||
let module_data = &def_map[module.local_id];
|
let module_data = &def_map[module.local_id];
|
||||||
for &impl_block in module_data.impls.iter() {
|
for impl_block in module_data.scope.impls() {
|
||||||
self.collect_lang_item(db, impl_block, LangItemTarget::ImplBlockId)
|
self.collect_lang_item(db, impl_block, LangItemTarget::ImplBlockId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ pub mod type_ref;
|
||||||
pub mod builtin_type;
|
pub mod builtin_type;
|
||||||
pub mod diagnostics;
|
pub mod diagnostics;
|
||||||
pub mod per_ns;
|
pub mod per_ns;
|
||||||
|
pub mod item_scope;
|
||||||
|
|
||||||
pub mod dyn_map;
|
pub mod dyn_map;
|
||||||
pub mod keys;
|
pub mod keys;
|
||||||
|
|
|
@ -57,8 +57,7 @@ mod tests;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile, MacroDefId};
|
use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile};
|
||||||
use once_cell::sync::Lazy;
|
|
||||||
use ra_arena::Arena;
|
use ra_arena::Arena;
|
||||||
use ra_db::{CrateId, Edition, FileId, FilePosition};
|
use ra_db::{CrateId, Edition, FileId, FilePosition};
|
||||||
use ra_prof::profile;
|
use ra_prof::profile;
|
||||||
|
@ -69,12 +68,12 @@ use ra_syntax::{
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
builtin_type::BuiltinType,
|
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
|
item_scope::{BuiltinShadowMode, ItemScope},
|
||||||
nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
|
nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode},
|
||||||
path::ModPath,
|
path::ModPath,
|
||||||
per_ns::PerNs,
|
per_ns::PerNs,
|
||||||
AstId, ImplId, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, TraitId,
|
AstId, LocalModuleId, ModuleDefId, ModuleId,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Contains all top-level defs from a macro-expanded crate
|
/// Contains all top-level defs from a macro-expanded crate
|
||||||
|
@ -166,113 +165,10 @@ impl ModuleOrigin {
|
||||||
pub struct ModuleData {
|
pub struct ModuleData {
|
||||||
pub parent: Option<LocalModuleId>,
|
pub parent: Option<LocalModuleId>,
|
||||||
pub children: FxHashMap<Name, LocalModuleId>,
|
pub children: FxHashMap<Name, LocalModuleId>,
|
||||||
pub scope: ModuleScope,
|
pub scope: ItemScope,
|
||||||
|
|
||||||
/// Where does this module come from?
|
/// Where does this module come from?
|
||||||
pub origin: ModuleOrigin,
|
pub origin: ModuleOrigin,
|
||||||
|
|
||||||
pub impls: Vec<ImplId>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default, PartialEq, Eq)]
|
|
||||||
pub struct ModuleScope {
|
|
||||||
items: FxHashMap<Name, Resolution>,
|
|
||||||
/// 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<Name, MacroDefId>,
|
|
||||||
}
|
|
||||||
|
|
||||||
static BUILTIN_SCOPE: Lazy<FxHashMap<Name, Resolution>> = 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<Item = (&'a Name, &'a Resolution)> + 'a {
|
|
||||||
//FIXME: shadowing
|
|
||||||
self.items.iter().chain(BUILTIN_SCOPE.iter())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
|
|
||||||
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<Item = (&'a Name, MacroDefId)> + '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<Item = (&'a Name, MacroDefId)> + '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<Item = TraitId> + '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<MacroDefId> {
|
|
||||||
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<LocalImportId>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CrateDefMap {
|
impl CrateDefMap {
|
||||||
|
|
|
@ -18,9 +18,10 @@ use test_utils::tested_by;
|
||||||
use crate::{
|
use crate::{
|
||||||
attr::Attrs,
|
attr::Attrs,
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
|
item_scope::Resolution,
|
||||||
nameres::{
|
nameres::{
|
||||||
diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
|
diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint,
|
||||||
raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, Resolution, ResolveMode,
|
raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode,
|
||||||
},
|
},
|
||||||
path::{ModPath, PathKind},
|
path::{ModPath, PathKind},
|
||||||
per_ns::PerNs,
|
per_ns::PerNs,
|
||||||
|
@ -225,14 +226,14 @@ where
|
||||||
|
|
||||||
/// Define a legacy textual scoped macro in module
|
/// 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
|
/// It will clone all macros from parent legacy scope, whose definition is prior to
|
||||||
/// the definition of current module.
|
/// 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.
|
/// 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
|
// 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`.
|
/// Import macros from `#[macro_use] extern crate`.
|
||||||
|
@ -371,11 +372,7 @@ where
|
||||||
let scope = &item_map[m.local_id].scope;
|
let scope = &item_map[m.local_id].scope;
|
||||||
|
|
||||||
// Module scoped macros is included
|
// Module scoped macros is included
|
||||||
let items = scope
|
let items = scope.collect_resolutions();
|
||||||
.items
|
|
||||||
.iter()
|
|
||||||
.map(|(name, res)| (name.clone(), res.clone()))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
self.update(module_id, Some(import_id), &items);
|
self.update(module_id, Some(import_id), &items);
|
||||||
} else {
|
} else {
|
||||||
|
@ -385,11 +382,7 @@ where
|
||||||
let scope = &self.def_map[m.local_id].scope;
|
let scope = &self.def_map[m.local_id].scope;
|
||||||
|
|
||||||
// Module scoped macros is included
|
// Module scoped macros is included
|
||||||
let items = scope
|
let items = scope.collect_resolutions();
|
||||||
.items
|
|
||||||
.iter()
|
|
||||||
.map(|(name, res)| (name.clone(), res.clone()))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
self.update(module_id, Some(import_id), &items);
|
self.update(module_id, Some(import_id), &items);
|
||||||
// record the glob import in case we add further items
|
// record the glob import in case we add further items
|
||||||
|
@ -466,34 +459,10 @@ where
|
||||||
// prevent stack overflows (but this shouldn't be possible)
|
// prevent stack overflows (but this shouldn't be possible)
|
||||||
panic!("infinite recursion in glob imports!");
|
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;
|
let mut changed = false;
|
||||||
for (name, res) in resolutions {
|
for (name, res) in resolutions {
|
||||||
let existing = module_items.items.entry(name.clone()).or_default();
|
changed |= scope.push_res(name.clone(), res, import);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !changed {
|
if !changed {
|
||||||
|
@ -666,7 +635,9 @@ where
|
||||||
let impl_id =
|
let impl_id =
|
||||||
ImplLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
|
ImplLoc { container, ast_id: AstId::new(self.file_id, ast_id) }
|
||||||
.intern(self.def_collector.db);
|
.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
|
||||||
|
.define_impl(impl_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -740,7 +711,9 @@ where
|
||||||
let res = modules.alloc(ModuleData::default());
|
let res = modules.alloc(ModuleData::default());
|
||||||
modules[res].parent = Some(self.module_id);
|
modules[res].parent = Some(self.module_id);
|
||||||
modules[res].origin = ModuleOrigin::not_sure_file(definition, declaration);
|
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);
|
modules[self.module_id].children.insert(name.clone(), res);
|
||||||
let resolution = Resolution {
|
let resolution = Resolution {
|
||||||
def: PerNs::types(
|
def: PerNs::types(
|
||||||
|
@ -904,7 +877,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) {
|
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 {
|
for (name, macro_) in macros {
|
||||||
self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_);
|
self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,27 +32,22 @@ fn render_crate_def_map(map: &CrateDefMap) -> String {
|
||||||
*buf += path;
|
*buf += path;
|
||||||
*buf += "\n";
|
*buf += "\n";
|
||||||
|
|
||||||
let mut entries = map.modules[module]
|
let mut entries = map.modules[module].scope.collect_resolutions();
|
||||||
.scope
|
entries.sort_by_key(|(name, _)| name.clone());
|
||||||
.items
|
|
||||||
.iter()
|
|
||||||
.map(|(name, res)| (name, res.def))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
entries.sort_by_key(|(name, _)| *name);
|
|
||||||
|
|
||||||
for (name, res) in entries {
|
for (name, res) in entries {
|
||||||
*buf += &format!("{}:", name);
|
*buf += &format!("{}:", name);
|
||||||
|
|
||||||
if res.types.is_some() {
|
if res.def.types.is_some() {
|
||||||
*buf += " t";
|
*buf += " t";
|
||||||
}
|
}
|
||||||
if res.values.is_some() {
|
if res.def.values.is_some() {
|
||||||
*buf += " v";
|
*buf += " v";
|
||||||
}
|
}
|
||||||
if res.macros.is_some() {
|
if res.def.macros.is_some() {
|
||||||
*buf += " m";
|
*buf += " m";
|
||||||
}
|
}
|
||||||
if res.is_none() {
|
if res.def.is_none() {
|
||||||
*buf += " _";
|
*buf += " _";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -587,6 +582,6 @@ mod b {
|
||||||
⋮T: v
|
⋮T: v
|
||||||
⋮
|
⋮
|
||||||
⋮crate::a
|
⋮crate::a
|
||||||
⋮T: t v
|
⋮T: t v
|
||||||
"###);
|
"###);
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,7 +116,7 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() {
|
||||||
let events = db.log_executed(|| {
|
let events = db.log_executed(|| {
|
||||||
let crate_def_map = db.crate_def_map(krate);
|
let crate_def_map = db.crate_def_map(krate);
|
||||||
let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
|
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)
|
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 events = db.log_executed(|| {
|
||||||
let crate_def_map = db.crate_def_map(krate);
|
let crate_def_map = db.crate_def_map(krate);
|
||||||
let (_, module_data) = crate_def_map.modules.iter().last().unwrap();
|
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)
|
assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events)
|
||||||
}
|
}
|
||||||
|
|
|
@ -610,7 +610,7 @@ fn expand_derive() {
|
||||||
struct Foo;
|
struct Foo;
|
||||||
",
|
",
|
||||||
);
|
);
|
||||||
assert_eq!(map.modules[map.root].impls.len(), 1);
|
assert_eq!(map.modules[map.root].scope.impls().len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -622,5 +622,5 @@ fn expand_multiple_derive() {
|
||||||
struct Foo;
|
struct Foo;
|
||||||
",
|
",
|
||||||
);
|
);
|
||||||
assert_eq!(map.modules[map.root].impls.len(), 2);
|
assert_eq!(map.modules[map.root].scope.impls().len(), 2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,8 @@ use crate::{
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
expr::{ExprId, PatId},
|
expr::{ExprId, PatId},
|
||||||
generics::GenericParams,
|
generics::GenericParams,
|
||||||
nameres::{BuiltinShadowMode, CrateDefMap},
|
item_scope::BuiltinShadowMode,
|
||||||
|
nameres::CrateDefMap,
|
||||||
path::{ModPath, PathKind},
|
path::{ModPath, PathKind},
|
||||||
per_ns::PerNs,
|
per_ns::PerNs,
|
||||||
AdtId, AssocContainerId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId,
|
AdtId, AssocContainerId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId,
|
||||||
|
|
|
@ -58,7 +58,7 @@ impl CrateImplBlocks {
|
||||||
|
|
||||||
let crate_def_map = db.crate_def_map(krate);
|
let crate_def_map = db.crate_def_map(krate);
|
||||||
for (_module_id, module_data) in crate_def_map.modules.iter() {
|
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) {
|
match db.impl_trait(impl_id) {
|
||||||
Some(tr) => {
|
Some(tr) => {
|
||||||
res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id);
|
res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id);
|
||||||
|
|
|
@ -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);
|
let impl_data = self.impl_data(impl_id);
|
||||||
for item in impl_data.items.iter() {
|
for item in impl_data.items.iter() {
|
||||||
if let AssocItemId::FunctionId(f) = item {
|
if let AssocItemId::FunctionId(f) = item {
|
||||||
|
|
|
@ -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);
|
let impl_data = db.impl_data(impl_id);
|
||||||
for &item in impl_data.items.iter() {
|
for &item in impl_data.items.iter() {
|
||||||
match item {
|
match item {
|
||||||
|
|
Loading…
Reference in a new issue