Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/nameres.rs')
-rw-r--r--crates/hir-def/src/nameres.rs237
1 files changed, 126 insertions, 111 deletions
diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs
index 5f45e188e0..3f29619bcb 100644
--- a/crates/hir-def/src/nameres.rs
+++ b/crates/hir-def/src/nameres.rs
@@ -58,7 +58,7 @@ pub mod proc_macro;
#[cfg(test)]
mod tests;
-use std::ops::Deref;
+use std::ops::{Deref, DerefMut, Index, IndexMut};
use base_db::Crate;
use hir_expand::{
@@ -67,7 +67,6 @@ use hir_expand::{
};
use intern::Symbol;
use itertools::Itertools;
-use la_arena::Arena;
use rustc_hash::{FxHashMap, FxHashSet};
use span::{Edition, FileAstId, FileId, ROOT_ERASED_FILE_AST_ID};
use stdx::format_to;
@@ -76,8 +75,8 @@ use triomphe::Arc;
use tt::TextRange;
use crate::{
- AstId, BlockId, BlockLoc, CrateRootModuleId, ExternCrateId, FunctionId, FxIndexMap,
- LocalModuleId, Lookup, MacroCallStyles, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId,
+ AstId, BlockId, BlockLoc, ExternCrateId, FunctionId, FxIndexMap, Lookup, MacroCallStyles,
+ MacroExpander, MacroId, ModuleId, ModuleIdLt, ProcMacroId, UseId,
db::DefDatabase,
item_scope::{BuiltinShadowMode, ItemScope},
item_tree::TreeId,
@@ -109,7 +108,7 @@ pub struct LocalDefMap {
// FIXME: There are probably some other things that could be here, but this is less severe and you
// need to be careful with things that block def maps also have.
/// The extern prelude which contains all root modules of external crates that are in scope.
- extern_prelude: FxIndexMap<Name, (CrateRootModuleId, Option<ExternCrateId>)>,
+ extern_prelude: FxIndexMap<Name, (ModuleId, Option<ExternCrateId>)>,
}
impl std::hash::Hash for LocalDefMap {
@@ -135,8 +134,7 @@ impl LocalDefMap {
pub(crate) fn extern_prelude(
&self,
- ) -> impl DoubleEndedIterator<Item = (&Name, (CrateRootModuleId, Option<ExternCrateId>))> + '_
- {
+ ) -> impl DoubleEndedIterator<Item = (&Name, (ModuleId, Option<ExternCrateId>))> + '_ {
self.extern_prelude.iter().map(|(name, &def)| (name, def))
}
}
@@ -157,8 +155,9 @@ pub struct DefMap {
/// When this is a block def map, this will hold the block id of the block and module that
/// contains this block.
block: Option<BlockInfo>,
+ pub root: ModuleId,
/// The modules and their data declared in this crate.
- pub modules: Arena<ModuleData>,
+ pub modules: ModulesMap,
/// The prelude module for this crate. This either comes from an import
/// marked with the `prelude_import` attribute, or (in the normal case) from
/// a dependency (`std` or `core`).
@@ -245,33 +244,22 @@ struct BlockInfo {
/// The `BlockId` this `DefMap` was created from.
block: BlockId,
/// The containing module.
- parent: BlockRelativeModuleId,
+ parent: ModuleId,
}
-#[derive(Debug, PartialEq, Eq, Clone, Copy)]
-struct BlockRelativeModuleId {
- block: Option<BlockId>,
- local_id: LocalModuleId,
-}
-
-impl BlockRelativeModuleId {
- fn def_map(self, db: &dyn DefDatabase, krate: Crate) -> &DefMap {
- self.into_module(krate).def_map(db)
- }
-
- fn into_module(self, krate: Crate) -> ModuleId {
- ModuleId { krate, block: self.block, local_id: self.local_id }
- }
+impl std::ops::Index<ModuleId> for DefMap {
+ type Output = ModuleData;
- fn is_block_module(self) -> bool {
- self.block.is_some() && self.local_id == DefMap::ROOT
+ fn index(&self, id: ModuleId) -> &ModuleData {
+ self.modules
+ .get(&id)
+ .unwrap_or_else(|| panic!("ModuleId not found in ModulesMap {:#?}: {id:#?}", self.root))
}
}
-impl std::ops::Index<LocalModuleId> for DefMap {
- type Output = ModuleData;
- fn index(&self, id: LocalModuleId) -> &ModuleData {
- &self.modules[id]
+impl std::ops::IndexMut<ModuleId> for DefMap {
+ fn index_mut(&mut self, id: ModuleId) -> &mut ModuleData {
+ &mut self.modules[id]
}
}
@@ -358,8 +346,8 @@ pub struct ModuleData {
/// Parent module in the same `DefMap`.
///
/// [`None`] for block modules because they are always its `DefMap`'s root.
- pub parent: Option<LocalModuleId>,
- pub children: FxIndexMap<Name, LocalModuleId>,
+ pub parent: Option<ModuleId>,
+ pub children: FxIndexMap<Name, ModuleId>,
pub scope: ItemScope,
}
@@ -392,11 +380,19 @@ pub(crate) fn crate_local_def_map(db: &dyn DefDatabase, crate_id: Crate) -> DefM
.entered();
let root_file_id = crate_id.root_file_id(db);
- let module_data =
- ModuleData::new(ModuleOrigin::CrateRoot { definition: root_file_id }, Visibility::Public);
+ let module_data = ModuleData::new(
+ ModuleOrigin::CrateRoot { definition: root_file_id },
+ Visibility::Public,
+ None,
+ );
- let def_map =
- DefMap::empty(crate_id, Arc::new(DefMapCrateData::new(krate.edition)), module_data, None);
+ let def_map = DefMap::empty(
+ db,
+ crate_id,
+ Arc::new(DefMapCrateData::new(krate.edition)),
+ module_data,
+ None,
+ );
let (def_map, local_def_map) =
collector::collect_defs(db, def_map, TreeId::new(root_file_id.into(), None), None);
@@ -407,22 +403,18 @@ pub(crate) fn crate_local_def_map(db: &dyn DefDatabase, crate_id: Crate) -> DefM
pub fn block_def_map(db: &dyn DefDatabase, block_id: BlockId) -> DefMap {
let BlockLoc { ast_id, module } = block_id.lookup(db);
- let visibility = Visibility::Module(
- ModuleId { krate: module.krate, local_id: DefMap::ROOT, block: module.block },
- VisibilityExplicitness::Implicit,
- );
+ let visibility = Visibility::Module(module, VisibilityExplicitness::Implicit);
let module_data =
- ModuleData::new(ModuleOrigin::BlockExpr { block: ast_id, id: block_id }, visibility);
+ ModuleData::new(ModuleOrigin::BlockExpr { block: ast_id, id: block_id }, visibility, None);
- let local_def_map = crate_local_def_map(db, module.krate);
+ let krate = module.krate(db);
+ let local_def_map = crate_local_def_map(db, krate);
let def_map = DefMap::empty(
- module.krate,
+ db,
+ krate,
local_def_map.def_map(db).data.clone(),
module_data,
- Some(BlockInfo {
- block: block_id,
- parent: BlockRelativeModuleId { block: module.block, local_id: module.local_id },
- }),
+ Some(BlockInfo { block: block_id, parent: module }),
);
let (def_map, _) = collector::collect_defs(
@@ -435,25 +427,24 @@ pub fn block_def_map(db: &dyn DefDatabase, block_id: BlockId) -> DefMap {
}
impl DefMap {
- /// The module id of a crate or block root.
- pub const ROOT: LocalModuleId = LocalModuleId::from_raw(la_arena::RawIdx::from_u32(0));
-
pub fn edition(&self) -> Edition {
self.data.edition
}
fn empty(
+ db: &dyn DefDatabase,
krate: Crate,
crate_data: Arc<DefMapCrateData>,
module_data: ModuleData,
block: Option<BlockInfo>,
) -> DefMap {
- let mut modules: Arena<ModuleData> = Arena::default();
- let root = modules.alloc(module_data);
- assert_eq!(root, Self::ROOT);
+ let mut modules = ModulesMap::new();
+ let root = unsafe { ModuleIdLt::new(db, krate, block.map(|it| it.block)).to_static() };
+ modules.insert(root, module_data);
DefMap {
block,
+ root,
modules,
krate,
prelude: None,
@@ -471,6 +462,7 @@ impl DefMap {
diagnostics,
modules,
derive_helpers_in_scope,
+ root: _,
block: _,
krate: _,
prelude: _,
@@ -495,7 +487,7 @@ impl DefMap {
&'a self,
db: &'a dyn DefDatabase,
file_id: FileId,
- ) -> impl Iterator<Item = LocalModuleId> + 'a {
+ ) -> impl Iterator<Item = ModuleId> + 'a {
self.modules
.iter()
.filter(move |(_id, data)| {
@@ -504,7 +496,7 @@ impl DefMap {
.map(|(id, _data)| id)
}
- pub fn modules(&self) -> impl Iterator<Item = (LocalModuleId, &ModuleData)> + '_ {
+ pub fn modules(&self) -> impl Iterator<Item = (ModuleId, &ModuleData)> + '_ {
self.modules.iter()
}
@@ -543,40 +535,32 @@ impl DefMap {
self.krate
}
- pub fn module_id(&self, local_id: LocalModuleId) -> ModuleId {
- let block = self.block.map(|b| b.block);
- ModuleId { krate: self.krate, local_id, block }
- }
-
- pub fn crate_root(&self) -> CrateRootModuleId {
- CrateRootModuleId { krate: self.krate }
+ #[inline]
+ pub fn crate_root(&self, db: &dyn DefDatabase) -> ModuleId {
+ match self.block {
+ Some(_) => crate_def_map(db, self.krate()).root,
+ None => self.root,
+ }
}
/// This is the same as [`Self::crate_root`] for crate def maps, but for block def maps, it
/// returns the root block module.
pub fn root_module_id(&self) -> ModuleId {
- self.module_id(Self::ROOT)
+ self.root
}
/// If this `DefMap` is for a block expression, returns the module containing the block (which
/// might again be a block, or a module inside a block).
pub fn parent(&self) -> Option<ModuleId> {
- let BlockRelativeModuleId { block, local_id } = self.block?.parent;
- Some(ModuleId { krate: self.krate, block, local_id })
+ Some(self.block?.parent)
}
/// Returns the module containing `local_mod`, either the parent `mod`, or the module (or block) containing
/// the block, if `self` corresponds to a block expression.
- pub fn containing_module(&self, local_mod: LocalModuleId) -> Option<ModuleId> {
+ pub fn containing_module(&self, local_mod: ModuleId) -> Option<ModuleId> {
match self[local_mod].parent {
- Some(parent) => Some(self.module_id(parent)),
- None => {
- self.block.map(
- |BlockInfo { parent: BlockRelativeModuleId { block, local_id }, .. }| {
- ModuleId { krate: self.krate, block, local_id }
- },
- )
- }
+ Some(parent) => Some(parent),
+ None => self.block.map(|BlockInfo { parent, .. }| parent),
}
}
@@ -594,30 +578,21 @@ impl DefMap {
// even), as this should be a great debugging aid.
pub fn dump(&self, db: &dyn DefDatabase) -> String {
let mut buf = String::new();
- let mut arc;
let mut current_map = self;
while let Some(block) = current_map.block {
- go(&mut buf, db, current_map, "(block scope)", Self::ROOT);
+ go(&mut buf, db, current_map, "(block scope)", current_map.root);
buf.push('\n');
- arc = block.parent.def_map(db, self.krate);
- current_map = arc;
+ current_map = block.parent.def_map(db);
}
- go(&mut buf, db, current_map, "crate", Self::ROOT);
+ go(&mut buf, db, current_map, "crate", current_map.root);
return buf;
- fn go(
- buf: &mut String,
- db: &dyn DefDatabase,
- map: &DefMap,
- path: &str,
- module: LocalModuleId,
- ) {
+ fn go(buf: &mut String, db: &dyn DefDatabase, map: &DefMap, path: &str, module: ModuleId) {
format_to!(buf, "{}\n", path);
- map.modules[module].scope.dump(db, buf);
+ map[module].scope.dump(db, buf);
- for (name, child) in
- map.modules[module].children.iter().sorted_by(|a, b| Ord::cmp(&a.0, &b.0))
+ for (name, child) in map[module].children.iter().sorted_by(|a, b| Ord::cmp(&a.0, &b.0))
{
let path = format!("{path}::{}", name.display(db, Edition::LATEST));
buf.push('\n');
@@ -625,20 +600,6 @@ impl DefMap {
}
}
}
-
- pub fn dump_block_scopes(&self, db: &dyn DefDatabase) -> String {
- let mut buf = String::new();
- let mut arc;
- let mut current_map = self;
- while let Some(block) = current_map.block {
- format_to!(buf, "{:?} in {:?}\n", block.block, block.parent);
- arc = block.parent.def_map(db, self.krate);
- current_map = arc;
- }
-
- format_to!(buf, "crate scope\n");
- buf
- }
}
impl DefMap {
@@ -658,7 +619,7 @@ impl DefMap {
&self,
local_def_map: &LocalDefMap,
db: &dyn DefDatabase,
- original_module: LocalModuleId,
+ original_module: ModuleId,
path: &ModPath,
shadow: BuiltinShadowMode,
expected_macro_subns: Option<MacroSubNs>,
@@ -681,7 +642,7 @@ impl DefMap {
&self,
local_def_map: &LocalDefMap,
db: &dyn DefDatabase,
- original_module: LocalModuleId,
+ original_module: ModuleId,
path: &ModPath,
shadow: BuiltinShadowMode,
) -> (PerNs, Option<usize>, ResolvePathResultPrefixInfo) {
@@ -704,16 +665,16 @@ impl DefMap {
pub(crate) fn with_ancestor_maps<T>(
&self,
db: &dyn DefDatabase,
- local_mod: LocalModuleId,
- f: &mut dyn FnMut(&DefMap, LocalModuleId) -> Option<T>,
+ local_mod: ModuleId,
+ f: &mut dyn FnMut(&DefMap, ModuleId) -> Option<T>,
) -> Option<T> {
if let Some(it) = f(self, local_mod) {
return Some(it);
}
let mut block = self.block;
while let Some(block_info) = block {
- let parent = block_info.parent.def_map(db, self.krate);
- if let Some(it) = f(parent, block_info.parent.local_id) {
+ let parent = block_info.parent.def_map(db);
+ if let Some(it) = f(parent, block_info.parent) {
return Some(it);
}
block = parent.block;
@@ -724,11 +685,15 @@ impl DefMap {
}
impl ModuleData {
- pub(crate) fn new(origin: ModuleOrigin, visibility: Visibility) -> Self {
+ pub(crate) fn new(
+ origin: ModuleOrigin,
+ visibility: Visibility,
+ parent: Option<ModuleId>,
+ ) -> Self {
ModuleData {
origin,
visibility,
- parent: None,
+ parent,
children: Default::default(),
scope: ItemScope::default(),
}
@@ -739,7 +704,7 @@ impl ModuleData {
self.origin.definition_source(db)
}
- /// Same as [`definition_source`] but only returns the file id to prevent parsing the ASt.
+ /// Same as [`ModuleData::definition_source`] but only returns the file id to prevent parsing the ASt.
pub fn definition_source_file_id(&self) -> HirFileId {
match self.origin {
ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => {
@@ -852,3 +817,53 @@ fn sub_namespace_match(
None => true,
}
}
+
+/// A newtype wrapper around `FxHashMap<ModuleId, ModuleData>` that implements `IndexMut`.
+#[derive(Debug, PartialEq, Eq)]
+pub struct ModulesMap {
+ inner: FxIndexMap<ModuleId, ModuleData>,
+}
+
+impl ModulesMap {
+ fn new() -> Self {
+ Self { inner: FxIndexMap::default() }
+ }
+
+ fn iter(&self) -> impl Iterator<Item = (ModuleId, &ModuleData)> + '_ {
+ self.inner.iter().map(|(&k, v)| (k, v))
+ }
+
+ fn iter_mut(&mut self) -> impl Iterator<Item = (ModuleId, &mut ModuleData)> + '_ {
+ self.inner.iter_mut().map(|(&k, v)| (k, v))
+ }
+}
+
+impl Deref for ModulesMap {
+ type Target = FxIndexMap<ModuleId, ModuleData>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.inner
+ }
+}
+
+impl DerefMut for ModulesMap {
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ &mut self.inner
+ }
+}
+
+impl Index<ModuleId> for ModulesMap {
+ type Output = ModuleData;
+
+ fn index(&self, id: ModuleId) -> &ModuleData {
+ self.inner.get(&id).unwrap_or_else(|| panic!("ModuleId not found in ModulesMap: {id:#?}"))
+ }
+}
+
+impl IndexMut<ModuleId> for ModulesMap {
+ fn index_mut(&mut self, id: ModuleId) -> &mut ModuleData {
+ self.inner
+ .get_mut(&id)
+ .unwrap_or_else(|| panic!("ModuleId not found in ModulesMap: {id:#?}"))
+ }
+}