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.rs334
1 files changed, 169 insertions, 165 deletions
diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs
index 270468ad0a..764617eafb 100644
--- a/crates/hir-def/src/nameres.rs
+++ b/crates/hir-def/src/nameres.rs
@@ -65,7 +65,6 @@ use hir_expand::{
};
use itertools::Itertools;
use la_arena::Arena;
-use profile::Count;
use rustc_hash::{FxHashMap, FxHashSet};
use span::FileAstId;
use stdx::format_to;
@@ -95,7 +94,6 @@ use crate::{
/// is computed by the `block_def_map` query.
#[derive(Debug, PartialEq, Eq)]
pub struct DefMap {
- _c: Count<Self>,
/// 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>,
@@ -154,6 +152,23 @@ struct DefMapCrateData {
}
impl DefMapCrateData {
+ fn new(edition: Edition) -> Self {
+ Self {
+ extern_prelude: FxHashMap::default(),
+ exported_derives: FxHashMap::default(),
+ fn_proc_macro_mapping: FxHashMap::default(),
+ proc_macro_loading_error: None,
+ registered_attrs: Vec::new(),
+ registered_tools: Vec::new(),
+ unstable_features: FxHashSet::default(),
+ rustc_coherence_is_core: false,
+ no_core: false,
+ no_std: false,
+ edition,
+ recursion_limit: None,
+ }
+ }
+
fn shrink_to_fit(&mut self) {
let Self {
extern_prelude,
@@ -305,67 +320,67 @@ 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(crate) fn crate_def_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<DefMap> {
+ pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, crate_id: CrateId) -> Arc<DefMap> {
let crate_graph = db.crate_graph();
- let krate_name = crate_graph[krate].display_name.as_deref().unwrap_or_default();
-
- let _p = tracing::span!(tracing::Level::INFO, "crate_def_map_query", ?krate_name).entered();
+ let krate = &crate_graph[crate_id];
+ let name = krate.display_name.as_deref().unwrap_or_default();
+ let _p = tracing::span!(tracing::Level::INFO, "crate_def_map_query", ?name).entered();
- let crate_graph = db.crate_graph();
+ let module_data = ModuleData::new(
+ ModuleOrigin::CrateRoot { definition: krate.root_file_id },
+ Visibility::Public,
+ );
- let edition = crate_graph[krate].edition;
- let origin = ModuleOrigin::CrateRoot { definition: crate_graph[krate].root_file_id };
- let def_map = DefMap::empty(krate, edition, ModuleData::new(origin, Visibility::Public));
- let def_map = collector::collect_defs(
- db,
- def_map,
- TreeId::new(crate_graph[krate].root_file_id.into(), None),
+ let def_map = DefMap::empty(
+ crate_id,
+ Arc::new(DefMapCrateData::new(krate.edition)),
+ module_data,
+ None,
);
+ let def_map =
+ collector::collect_defs(db, def_map, TreeId::new(krate.root_file_id.into(), None));
Arc::new(def_map)
}
pub(crate) fn block_def_map_query(db: &dyn DefDatabase, block_id: BlockId) -> Arc<DefMap> {
- let block: BlockLoc = block_id.lookup(db);
-
- let parent_map = block.module.def_map(db);
- let krate = block.module.krate;
- let local_id = LocalModuleId::from_raw(la_arena::RawIdx::from(0));
- // NB: we use `None` as block here, which would be wrong for implicit
- // modules declared by blocks with items. At the moment, we don't use
- // this visibility for anything outside IDE, so that's probably OK.
+ let BlockLoc { ast_id, module } = block_id.lookup(db);
+
let visibility = Visibility::Module(
- ModuleId { krate, local_id, block: None },
+ ModuleId { krate: module.krate, local_id: Self::ROOT, block: module.block },
VisibilityExplicitness::Implicit,
);
- let module_data = ModuleData::new(
- ModuleOrigin::BlockExpr { block: block.ast_id, id: block_id },
- visibility,
+ let module_data =
+ ModuleData::new(ModuleOrigin::BlockExpr { block: ast_id, id: block_id }, visibility);
+
+ let parent_map = module.def_map(db);
+ let def_map = DefMap::empty(
+ module.krate,
+ parent_map.data.clone(),
+ module_data,
+ Some(BlockInfo {
+ block: block_id,
+ parent: BlockRelativeModuleId { block: module.block, local_id: module.local_id },
+ }),
);
- let mut def_map = DefMap::empty(krate, parent_map.data.edition, module_data);
- def_map.data = parent_map.data.clone();
- def_map.block = Some(BlockInfo {
- block: block_id,
- parent: BlockRelativeModuleId {
- block: block.module.block,
- local_id: block.module.local_id,
- },
- });
-
let def_map =
- collector::collect_defs(db, def_map, TreeId::new(block.ast_id.file_id, Some(block_id)));
+ collector::collect_defs(db, def_map, TreeId::new(ast_id.file_id, Some(block_id)));
Arc::new(def_map)
}
- fn empty(krate: CrateId, edition: Edition, module_data: ModuleData) -> DefMap {
+ fn empty(
+ krate: CrateId,
+ 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);
DefMap {
- _c: Count::new(),
- block: None,
+ block,
modules,
krate,
prelude: None,
@@ -373,23 +388,36 @@ impl DefMap {
derive_helpers_in_scope: FxHashMap::default(),
diagnostics: Vec::new(),
enum_definitions: FxHashMap::default(),
- data: Arc::new(DefMapCrateData {
- extern_prelude: FxHashMap::default(),
- exported_derives: FxHashMap::default(),
- fn_proc_macro_mapping: FxHashMap::default(),
- proc_macro_loading_error: None,
- registered_attrs: Vec::new(),
- registered_tools: Vec::new(),
- unstable_features: FxHashSet::default(),
- rustc_coherence_is_core: false,
- no_core: false,
- no_std: false,
- edition,
- recursion_limit: None,
- }),
+ data: crate_data,
+ }
+ }
+ fn shrink_to_fit(&mut self) {
+ // Exhaustive match to require handling new fields.
+ let Self {
+ macro_use_prelude,
+ diagnostics,
+ modules,
+ derive_helpers_in_scope,
+ block: _,
+ krate: _,
+ prelude: _,
+ data: _,
+ enum_definitions,
+ } = self;
+
+ macro_use_prelude.shrink_to_fit();
+ diagnostics.shrink_to_fit();
+ modules.shrink_to_fit();
+ derive_helpers_in_scope.shrink_to_fit();
+ enum_definitions.shrink_to_fit();
+ for (_, module) in modules.iter_mut() {
+ module.children.shrink_to_fit();
+ module.scope.shrink_to_fit();
}
}
+}
+impl DefMap {
pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ {
self.modules
.iter()
@@ -440,26 +468,6 @@ impl DefMap {
self.krate
}
- pub(crate) fn block_id(&self) -> Option<BlockId> {
- self.block.map(|block| block.block)
- }
-
- pub(crate) fn prelude(&self) -> Option<(ModuleId, Option<UseId>)> {
- self.prelude
- }
-
- pub(crate) fn extern_prelude(
- &self,
- ) -> impl Iterator<Item = (&Name, (CrateRootModuleId, Option<ExternCrateId>))> + '_ {
- self.data.extern_prelude.iter().map(|(name, &def)| (name, def))
- }
-
- pub(crate) fn macro_use_prelude(
- &self,
- ) -> impl Iterator<Item = (&Name, (MacroId, Option<ExternCrateId>))> + '_ {
- self.macro_use_prelude.iter().map(|(name, &def)| (name, def))
- }
-
pub fn module_id(&self, local_id: LocalModuleId) -> ModuleId {
let block = self.block.map(|b| b.block);
ModuleId { krate: self.krate, local_id, block }
@@ -475,68 +483,6 @@ impl DefMap {
self.module_id(Self::ROOT)
}
- pub(crate) fn resolve_path(
- &self,
- db: &dyn DefDatabase,
- original_module: LocalModuleId,
- path: &ModPath,
- shadow: BuiltinShadowMode,
- expected_macro_subns: Option<MacroSubNs>,
- ) -> (PerNs, Option<usize>) {
- let res = self.resolve_path_fp_with_macro(
- db,
- ResolveMode::Other,
- original_module,
- path,
- shadow,
- expected_macro_subns,
- );
- (res.resolved_def, res.segment_index)
- }
-
- pub(crate) fn resolve_path_locally(
- &self,
- db: &dyn DefDatabase,
- original_module: LocalModuleId,
- path: &ModPath,
- shadow: BuiltinShadowMode,
- ) -> (PerNs, Option<usize>) {
- let res = self.resolve_path_fp_with_macro_single(
- db,
- ResolveMode::Other,
- original_module,
- path,
- shadow,
- None, // Currently this function isn't used for macro resolution.
- );
- (res.resolved_def, res.segment_index)
- }
-
- /// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module.
- ///
- /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns
- /// `None`, iteration continues.
- pub(crate) fn with_ancestor_maps<T>(
- &self,
- db: &dyn DefDatabase,
- local_mod: LocalModuleId,
- f: &mut dyn FnMut(&DefMap, LocalModuleId) -> 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) {
- return Some(it);
- }
- block = parent.block;
- }
-
- None
- }
-
/// 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> {
@@ -559,6 +505,16 @@ impl DefMap {
}
}
+ /// Get a reference to the def map's diagnostics.
+ pub fn diagnostics(&self) -> &[DefDiagnostic] {
+ self.diagnostics.as_slice()
+ }
+
+ pub fn recursion_limit(&self) -> u32 {
+ // 128 is the default in rustc
+ self.data.recursion_limit.unwrap_or(128)
+ }
+
// FIXME: this can use some more human-readable format (ideally, an IR
// even), as this should be a great debugging aid.
pub fn dump(&self, db: &dyn DefDatabase) -> String {
@@ -608,41 +564,89 @@ impl DefMap {
format_to!(buf, "crate scope\n");
buf
}
+}
- fn shrink_to_fit(&mut self) {
- // Exhaustive match to require handling new fields.
- let Self {
- _c: _,
- macro_use_prelude,
- diagnostics,
- modules,
- derive_helpers_in_scope,
- block: _,
- krate: _,
- prelude: _,
- data: _,
- enum_definitions,
- } = self;
+impl DefMap {
+ pub(crate) fn block_id(&self) -> Option<BlockId> {
+ self.block.map(|block| block.block)
+ }
- macro_use_prelude.shrink_to_fit();
- diagnostics.shrink_to_fit();
- modules.shrink_to_fit();
- derive_helpers_in_scope.shrink_to_fit();
- enum_definitions.shrink_to_fit();
- for (_, module) in modules.iter_mut() {
- module.children.shrink_to_fit();
- module.scope.shrink_to_fit();
- }
+ pub(crate) fn prelude(&self) -> Option<(ModuleId, Option<UseId>)> {
+ self.prelude
}
- /// Get a reference to the def map's diagnostics.
- pub fn diagnostics(&self) -> &[DefDiagnostic] {
- self.diagnostics.as_slice()
+ pub(crate) fn extern_prelude(
+ &self,
+ ) -> impl Iterator<Item = (&Name, (CrateRootModuleId, Option<ExternCrateId>))> + '_ {
+ self.data.extern_prelude.iter().map(|(name, &def)| (name, def))
}
- pub fn recursion_limit(&self) -> u32 {
- // 128 is the default in rustc
- self.data.recursion_limit.unwrap_or(128)
+ pub(crate) fn macro_use_prelude(
+ &self,
+ ) -> impl Iterator<Item = (&Name, (MacroId, Option<ExternCrateId>))> + '_ {
+ self.macro_use_prelude.iter().map(|(name, &def)| (name, def))
+ }
+
+ pub(crate) fn resolve_path(
+ &self,
+ db: &dyn DefDatabase,
+ original_module: LocalModuleId,
+ path: &ModPath,
+ shadow: BuiltinShadowMode,
+ expected_macro_subns: Option<MacroSubNs>,
+ ) -> (PerNs, Option<usize>) {
+ let res = self.resolve_path_fp_with_macro(
+ db,
+ ResolveMode::Other,
+ original_module,
+ path,
+ shadow,
+ expected_macro_subns,
+ );
+ (res.resolved_def, res.segment_index)
+ }
+
+ pub(crate) fn resolve_path_locally(
+ &self,
+ db: &dyn DefDatabase,
+ original_module: LocalModuleId,
+ path: &ModPath,
+ shadow: BuiltinShadowMode,
+ ) -> (PerNs, Option<usize>) {
+ let res = self.resolve_path_fp_with_macro_single(
+ db,
+ ResolveMode::Other,
+ original_module,
+ path,
+ shadow,
+ None, // Currently this function isn't used for macro resolution.
+ );
+ (res.resolved_def, res.segment_index)
+ }
+
+ /// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module.
+ ///
+ /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns
+ /// `None`, iteration continues.
+ pub(crate) fn with_ancestor_maps<T>(
+ &self,
+ db: &dyn DefDatabase,
+ local_mod: LocalModuleId,
+ f: &mut dyn FnMut(&DefMap, LocalModuleId) -> 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) {
+ return Some(it);
+ }
+ block = parent.block;
+ }
+
+ None
}
}