From dc7c6d43c77c2edb549f574188da8aff4ac0fba4 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 1 Jun 2023 14:46:36 +0200 Subject: [PATCH 1/6] Slightly shrink `DefMap` --- crates/hir-def/src/body/lower.rs | 2 +- crates/hir-def/src/child_by_source.rs | 3 +- crates/hir-def/src/db.rs | 11 +++- crates/hir-def/src/import_map.rs | 6 +- .../hir-def/src/macro_expansion_tests/mod.rs | 4 +- crates/hir-def/src/nameres.rs | 57 +++++++++++++------ crates/hir-def/src/nameres/collector.rs | 35 +++++------- crates/hir-def/src/nameres/path_resolution.rs | 29 +++++----- crates/hir-def/src/nameres/tests/macros.rs | 10 ++-- crates/hir-def/src/resolver.rs | 8 +-- crates/hir-def/src/test_db.rs | 4 +- crates/hir-ty/src/display.rs | 3 +- crates/hir/src/display.rs | 2 +- crates/hir/src/lib.rs | 11 ++-- crates/ide-completion/src/completions.rs | 2 +- crates/ide-db/src/helpers.rs | 2 +- crates/ide-db/src/rename.rs | 2 +- crates/ide-db/src/search.rs | 6 +- .../src/handlers/unlinked_file.rs | 4 +- crates/ide/src/status.rs | 3 +- .../ide/src/syntax_highlighting/highlight.rs | 2 +- lib/la-arena/src/lib.rs | 16 +++++- 22 files changed, 130 insertions(+), 92 deletions(-) diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs index ebe05afca6..7055e3ca9e 100644 --- a/crates/hir-def/src/body/lower.rs +++ b/crates/hir-def/src/body/lower.rs @@ -1073,7 +1073,7 @@ impl ExprCollector<'_> { match block_id.map(|block_id| (self.db.block_def_map(block_id), block_id)) { Some((def_map, block_id)) => { self.body.block_scopes.push(block_id); - (def_map.module_id(def_map.root()), def_map) + (def_map.module_id(DefMap::ROOT), def_map) } None => (self.expander.module, self.def_map.clone()), }; diff --git a/crates/hir-def/src/child_by_source.rs b/crates/hir-def/src/child_by_source.rs index 21180fcbda..bb79e28f26 100644 --- a/crates/hir-def/src/child_by_source.rs +++ b/crates/hir-def/src/child_by_source.rs @@ -12,6 +12,7 @@ use crate::{ db::DefDatabase, dyn_map::{keys, DynMap}, item_scope::ItemScope, + nameres::DefMap, src::{HasChildSource, HasSource}, AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, FieldId, ImplId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId, VariantId, @@ -205,7 +206,7 @@ impl ChildBySource for DefWithBodyId { for (_, def_map) in body.blocks(db) { // All block expressions are merged into the same map, because they logically all add // inner items to the containing `DefWithBodyId`. - def_map[def_map.root()].scope.child_by_source_to(db, res, file_id); + def_map[DefMap::ROOT].scope.child_by_source_to(db, res, file_id); } } } diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs index c3721a94f6..6d18e3f56c 100644 --- a/crates/hir-def/src/db.rs +++ b/crates/hir-def/src/db.rs @@ -198,15 +198,14 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast Arc; - #[salsa::invoke(LangItems::lang_item_query)] fn lang_item(&self, start_crate: CrateId, item: LangItem) -> Option; #[salsa::invoke(ImportMap::import_map_query)] fn import_map(&self, krate: CrateId) -> Arc; + // region:visibilities + #[salsa::invoke(visibility::field_visibilities_query)] fn field_visibilities(&self, var: VariantId) -> Arc>; @@ -217,8 +216,14 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast Visibility; + // endregion:visibilities + + #[salsa::invoke(LangItems::crate_lang_items_query)] + fn crate_lang_items(&self, krate: CrateId) -> Arc; + #[salsa::transparent] fn crate_limits(&self, crate_id: CrateId) -> CrateLimits; + #[salsa::transparent] fn recursion_limit(&self, crate_id: CrateId) -> u32; diff --git a/crates/hir-def/src/import_map.rs b/crates/hir-def/src/import_map.rs index 6ef2949ef5..ec150dc068 100644 --- a/crates/hir-def/src/import_map.rs +++ b/crates/hir-def/src/import_map.rs @@ -11,8 +11,8 @@ use rustc_hash::{FxHashSet, FxHasher}; use triomphe::Arc; use crate::{ - db::DefDatabase, item_scope::ItemInNs, visibility::Visibility, AssocItemId, ModuleDefId, - ModuleId, TraitId, + db::DefDatabase, item_scope::ItemInNs, nameres::DefMap, visibility::Visibility, AssocItemId, + ModuleDefId, ModuleId, TraitId, }; type FxIndexMap = IndexMap>; @@ -183,7 +183,7 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMap { // We look only into modules that are public(ly reexported), starting with the crate root. let empty = ImportPath { segments: vec![] }; - let root = def_map.module_id(def_map.root()); + let root = def_map.module_id(DefMap::ROOT); let mut worklist = vec![(root, empty)]; while let Some((module, mod_path)) = worklist.pop() { let ext_def_map; diff --git a/crates/hir-def/src/macro_expansion_tests/mod.rs b/crates/hir-def/src/macro_expansion_tests/mod.rs index 40849d4a66..4a62696df0 100644 --- a/crates/hir-def/src/macro_expansion_tests/mod.rs +++ b/crates/hir-def/src/macro_expansion_tests/mod.rs @@ -35,7 +35,7 @@ use tt::token_id::{Subtree, TokenId}; use crate::{ db::DefDatabase, macro_id_to_def_id, - nameres::{MacroSubNs, ModuleSource}, + nameres::{DefMap, MacroSubNs, ModuleSource}, resolver::HasResolver, src::HasSource, test_db::TestDB, @@ -61,7 +61,7 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream let db = TestDB::with_files_extra_proc_macros(ra_fixture, extra_proc_macros); let krate = db.crate_graph().iter().next().unwrap(); let def_map = db.crate_def_map(krate); - let local_id = def_map.root(); + let local_id = DefMap::ROOT; let module = def_map.module_id(local_id); let resolver = module.resolver(&db); let source = def_map[local_id].definition_source(&db); diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index ccb9bed5c5..053ab5890e 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -94,7 +94,6 @@ use crate::{ pub struct DefMap { _c: Count, block: Option, - root: LocalModuleId, modules: Arena, krate: CrateId, /// The prelude module for this crate. This either comes from an import @@ -141,7 +140,19 @@ struct BlockInfo { /// The `BlockId` this `DefMap` was created from. block: BlockId, /// The containing module. - parent: ModuleId, + parent: BlockRelativeModuleId, +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +struct BlockRelativeModuleId { + block: Option, + local_id: LocalModuleId, +} + +impl BlockRelativeModuleId { + fn def_map(self, db: &dyn DefDatabase, krate: CrateId) -> Arc { + ModuleId { krate, block: self.block, local_id: self.local_id }.def_map(db) + } } impl std::ops::Index for DefMap { @@ -231,6 +242,8 @@ pub struct ModuleData { } impl DefMap { + 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 { let _p = profile::span("crate_def_map_query").detail(|| { db.crate_graph()[krate].display_name.as_deref().unwrap_or_default().to_string() @@ -266,7 +279,13 @@ impl DefMap { ModuleData::new(ModuleOrigin::BlockExpr { block: block.ast_id }, visibility); let mut def_map = DefMap::empty(krate, parent_map.edition, module_data); - def_map.block = Some(BlockInfo { block: block_id, parent: block.module }); + 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, tree_id); Arc::new(def_map) @@ -275,6 +294,7 @@ impl DefMap { fn empty(krate: CrateId, edition: Edition, module_data: ModuleData) -> DefMap { let mut modules: Arena = Arena::default(); let root = modules.alloc(module_data); + assert_eq!(root, Self::ROOT); DefMap { _c: Count::new(), @@ -289,7 +309,6 @@ impl DefMap { proc_macro_loading_error: None, derive_helpers_in_scope: FxHashMap::default(), prelude: None, - root, modules, registered_attrs: Vec::new(), registered_tools: Vec::new(), @@ -339,10 +358,6 @@ impl DefMap { self.no_std || self.no_core } - pub fn root(&self) -> LocalModuleId { - self.root - } - pub fn fn_as_proc_macro(&self, id: FunctionId) -> Option { self.fn_proc_macro_mapping.get(&id).copied() } @@ -377,9 +392,9 @@ impl DefMap { } pub(crate) fn crate_root(&self, db: &dyn DefDatabase) -> ModuleId { - self.with_ancestor_maps(db, self.root, &mut |def_map, _module| { + self.with_ancestor_maps(db, Self::ROOT, &mut |def_map, _module| { if def_map.block.is_none() { - Some(def_map.module_id(def_map.root)) + Some(def_map.module_id(Self::ROOT)) } else { None } @@ -439,7 +454,7 @@ impl DefMap { } let mut block = self.block; while let Some(block_info) = block { - let parent = block_info.parent.def_map(db); + let parent = block_info.parent.def_map(db, self.krate); if let Some(it) = f(&parent, block_info.parent.local_id) { return Some(it); } @@ -452,7 +467,8 @@ impl DefMap { /// 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 { - Some(self.block?.parent) + let BlockRelativeModuleId { block, local_id } = self.block?.parent; + Some(ModuleId { krate: self.krate, block, local_id }) } /// Returns the module containing `local_mod`, either the parent `mod`, or the module (or block) containing @@ -460,7 +476,13 @@ impl DefMap { pub fn containing_module(&self, local_mod: LocalModuleId) -> Option { match self[local_mod].parent { Some(parent) => Some(self.module_id(parent)), - None => self.block.map(|block| block.parent), + None => { + self.block.map( + |BlockInfo { parent: BlockRelativeModuleId { block, local_id }, .. }| { + ModuleId { krate: self.krate, block, local_id } + }, + ) + } } } @@ -471,12 +493,12 @@ impl DefMap { let mut arc; let mut current_map = self; while let Some(block) = current_map.block { - go(&mut buf, db, current_map, "block scope", current_map.root); + go(&mut buf, db, current_map, "block scope", Self::ROOT); buf.push('\n'); - arc = block.parent.def_map(db); + arc = block.parent.def_map(db, self.krate); current_map = &arc; } - go(&mut buf, db, current_map, "crate", current_map.root); + go(&mut buf, db, current_map, "crate", Self::ROOT); return buf; fn go( @@ -506,7 +528,7 @@ impl DefMap { 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); + arc = block.parent.def_map(db, self.krate); current_map = &arc; } @@ -534,7 +556,6 @@ impl DefMap { recursion_limit: _, krate: _, prelude: _, - root: _, rustc_coherence_is_core: _, no_core: _, no_std: _, diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 64caf26299..b431b6f647 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -71,7 +71,7 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: DefMap, tree_id: T for dep in &krate.dependencies { tracing::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id); let dep_def_map = db.crate_def_map(dep.crate_id); - let dep_root = dep_def_map.module_id(dep_def_map.root); + let dep_root = dep_def_map.module_id(DefMap::ROOT); deps.insert(dep.as_name(), dep_root); @@ -287,7 +287,7 @@ impl DefCollector<'_> { let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id; let item_tree = self.db.file_item_tree(file_id.into()); - let module_id = self.def_map.root; + let module_id = DefMap::ROOT; let attrs = item_tree.top_level_attrs(self.db, self.def_map.krate); @@ -382,7 +382,7 @@ impl DefCollector<'_> { fn seed_with_inner(&mut self, tree_id: TreeId) { let item_tree = tree_id.item_tree(self.db); - let module_id = self.def_map.root; + let module_id = DefMap::ROOT; let is_cfg_enabled = item_tree .top_level_attrs(self.db, self.def_map.krate) @@ -464,7 +464,7 @@ impl DefCollector<'_> { // Additionally, while the proc macro entry points must be `pub`, they are not publicly // exported in type/value namespace. This function reduces the visibility of all items // in the crate root that aren't proc macros. - let root = self.def_map.root; + let root = DefMap::ROOT; let module_id = self.def_map.module_id(root); let root = &mut self.def_map.modules[root]; root.scope.censor_non_proc_macros(module_id); @@ -560,13 +560,8 @@ impl DefCollector<'_> { }; let path = ModPath::from_segments(path_kind, [krate, name![prelude], edition]); - let (per_ns, _) = self.def_map.resolve_path( - self.db, - self.def_map.root, - &path, - BuiltinShadowMode::Other, - None, - ); + let (per_ns, _) = + self.def_map.resolve_path(self.db, DefMap::ROOT, &path, BuiltinShadowMode::Other, None); match per_ns.types { Some((ModuleDefId::ModuleId(m), _)) => { @@ -661,7 +656,7 @@ impl DefCollector<'_> { // In Rust, `#[macro_export]` macros are unconditionally visible at the // crate root, even if the parent modules is **not** visible. if export { - let module_id = self.def_map.root; + let module_id = DefMap::ROOT; self.def_map.modules[module_id].scope.declare(macro_.into()); self.update( module_id, @@ -712,7 +707,7 @@ impl DefCollector<'_> { /// A proc macro is similar to normal macro scope, but it would not visible in legacy textual scoped. /// And unconditionally exported. fn define_proc_macro(&mut self, name: Name, macro_: ProcMacroId) { - let module_id = self.def_map.root; + let module_id = DefMap::ROOT; self.def_map.modules[module_id].scope.declare(macro_.into()); self.update( module_id, @@ -732,7 +727,7 @@ impl DefCollector<'_> { let def_map = self.db.crate_def_map(krate); // `#[macro_use]` brings macros into macro_use prelude. Yes, even non-`macro_rules!` // macros. - let root_scope = &def_map[def_map.root].scope; + let root_scope = &def_map[DefMap::ROOT].scope; if let Some(names) = names { for name in names { // FIXME: Report diagnostic on 404. @@ -834,9 +829,9 @@ impl DefCollector<'_> { let root = match self.def_map.block { Some(_) => { let def_map = self.def_map.crate_root(self.db).def_map(self.db); - def_map.module_id(def_map.root()) + def_map.module_id(DefMap::ROOT) } - None => self.def_map.module_id(self.def_map.root()), + None => self.def_map.module_id(DefMap::ROOT), }; Some(root) } else { @@ -879,7 +874,7 @@ impl DefCollector<'_> { // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 if import.is_extern_crate && self.def_map.block.is_none() - && module_id == self.def_map.root + && module_id == DefMap::ROOT { if let (Some(ModuleDefId::ModuleId(def)), Some(name)) = (def.take_types(), name) { @@ -1525,7 +1520,7 @@ impl ModCollector<'_, '_> { fn collect(&mut self, items: &[ModItem], container: ItemContainerId) { let krate = self.def_collector.def_map.krate; - let is_crate_root = self.module_id == self.def_collector.def_map.root; + let is_crate_root = self.module_id == DefMap::ROOT; // Note: don't assert that inserted value is fresh: it's simply not true // for macros. @@ -1641,9 +1636,9 @@ impl ModCollector<'_, '_> { FunctionLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db); let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); - if self.def_collector.is_proc_macro && self.module_id == def_map.root { + if self.def_collector.is_proc_macro && self.module_id == DefMap::ROOT { if let Some(proc_macro) = attrs.parse_proc_macro_decl(&it.name) { - let crate_root = def_map.module_id(def_map.root); + let crate_root = def_map.module_id(DefMap::ROOT); self.def_collector.export_proc_macro( proc_macro, ItemTreeId::new(self.tree_id, id), diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs index 24dc4e243b..751536db38 100644 --- a/crates/hir-def/src/nameres/path_resolution.rs +++ b/crates/hir-def/src/nameres/path_resolution.rs @@ -121,7 +121,7 @@ impl DefMap { // ...unless we're resolving visibility for an associated item in an impl. if self.block_id() != m.block && !within_impl { cov_mark::hit!(adjust_vis_in_block_def_map); - vis = Visibility::Module(self.module_id(self.root())); + vis = Visibility::Module(self.module_id(Self::ROOT)); tracing::debug!("visibility {:?} points outside DefMap, adjusting to {:?}", m, vis); } } @@ -173,7 +173,7 @@ impl DefMap { match ¤t_map.block { Some(block) => { original_module = block.parent.local_id; - arc = block.parent.def_map(db); + arc = block.parent.def_map(db, current_map.krate); current_map = &*arc; } None => return result, @@ -207,7 +207,7 @@ impl DefMap { PerNs::types(self.crate_root(db).into(), Visibility::Public) } else { let def_map = db.crate_def_map(krate); - let module = def_map.module_id(def_map.root); + let module = def_map.module_id(Self::ROOT); cov_mark::hit!(macro_dollar_crate_other); PerNs::types(module.into(), Visibility::Public) } @@ -268,14 +268,17 @@ impl DefMap { path.display(db.upcast()), new_path.display(db.upcast()) ); - return block.parent.def_map(db).resolve_path_fp_with_macro( - db, - mode, - block.parent.local_id, - &new_path, - shadow, - expected_macro_subns, - ); + return block + .parent + .def_map(db, self.krate) + .resolve_path_fp_with_macro( + db, + mode, + block.parent.local_id, + &new_path, + shadow, + expected_macro_subns, + ); } None => { tracing::debug!("super path in root module"); @@ -476,9 +479,9 @@ impl DefMap { let from_crate_root = match self.block { Some(_) => { let def_map = self.crate_root(db).def_map(db); - def_map[def_map.root].scope.get(name) + def_map[Self::ROOT].scope.get(name) } - None => self[self.root].scope.get(name), + None => self[Self::ROOT].scope.get(name), }; let from_extern_prelude = || { self.resolve_name_in_extern_prelude(db, name) diff --git a/crates/hir-def/src/nameres/tests/macros.rs b/crates/hir-def/src/nameres/tests/macros.rs index 57f0233607..ae509de056 100644 --- a/crates/hir-def/src/nameres/tests/macros.rs +++ b/crates/hir-def/src/nameres/tests/macros.rs @@ -750,7 +750,7 @@ macro_rules! foo { pub use core::clone::Clone; "#, ); - assert_eq!(map.modules[map.root].scope.impls().len(), 1); + assert_eq!(map.modules[DefMap::ROOT].scope.impls().len(), 1); } #[test] @@ -772,7 +772,7 @@ pub macro Copy {} pub macro Clone {} "#, ); - assert_eq!(map.modules[map.root].scope.impls().len(), 2); + assert_eq!(map.modules[DefMap::ROOT].scope.impls().len(), 2); } #[test] @@ -815,7 +815,7 @@ pub macro derive($item:item) {} pub macro Clone {} "#, ); - assert_eq!(map.modules[map.root].scope.impls().len(), 1); + assert_eq!(map.modules[DefMap::ROOT].scope.impls().len(), 1); } #[test] @@ -1286,7 +1286,7 @@ fn proc_attr(a: TokenStream, b: TokenStream) -> TokenStream { a } let krate = db.crate_graph().iter().next().unwrap(); let def_map = db.crate_def_map(krate); - let root_module = &def_map[def_map.root()].scope; + let root_module = &def_map[DefMap::ROOT].scope; assert!( root_module.legacy_macros().count() == 0, "`#[macro_use]` shouldn't bring macros into textual macro scope", @@ -1392,7 +1392,7 @@ macro_rules! derive { () => {} } struct S; "#, ); - assert_eq!(map.modules[map.root].scope.impls().len(), 1); + assert_eq!(map.modules[DefMap::ROOT].scope.impls().len(), 1); } #[test] diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs index 3eaff61b15..06f5b2526a 100644 --- a/crates/hir-def/src/resolver.rs +++ b/crates/hir-def/src/resolver.rs @@ -586,8 +586,9 @@ impl Resolver { })); if let Some(block) = expr_scopes.block(scope_id) { let def_map = db.block_def_map(block); - let root = def_map.root(); - resolver.scopes.push(Scope::BlockScope(ModuleItemMap { def_map, module_id: root })); + resolver + .scopes + .push(Scope::BlockScope(ModuleItemMap { def_map, module_id: DefMap::ROOT })); // FIXME: This adds as many module scopes as there are blocks, but resolving in each // already traverses all parents, so this is O(n²). I think we could only store the // innermost module scope instead? @@ -753,8 +754,7 @@ fn resolver_for_scope_( for scope in scope_chain.into_iter().rev() { if let Some(block) = scopes.block(scope) { let def_map = db.block_def_map(block); - let root = def_map.root(); - r = r.push_block_scope(def_map, root); + r = r.push_block_scope(def_map, DefMap::ROOT); // FIXME: This adds as many module scopes as there are blocks, but resolving in each // already traverses all parents, so this is O(n²). I think we could only store the // innermost module scope instead? diff --git a/crates/hir-def/src/test_db.rs b/crates/hir-def/src/test_db.rs index d4b4031364..a6befc8a81 100644 --- a/crates/hir-def/src/test_db.rs +++ b/crates/hir-def/src/test_db.rs @@ -110,7 +110,7 @@ impl TestDB { } _ => { // FIXME: handle `mod` inside block expression - return def_map.module_id(def_map.root()); + return def_map.module_id(DefMap::ROOT); } } } @@ -119,7 +119,7 @@ impl TestDB { /// Finds the smallest/innermost module in `def_map` containing `position`. fn mod_at_position(&self, def_map: &DefMap, position: FilePosition) -> LocalModuleId { let mut size = None; - let mut res = def_map.root(); + let mut res = DefMap::ROOT; for (module, data) in def_map.modules() { let src = data.definition_source(self); if src.file_id != position.file_id.into() { diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs index 058d5059b1..32f50cb051 100644 --- a/crates/hir-ty/src/display.rs +++ b/crates/hir-ty/src/display.rs @@ -13,6 +13,7 @@ use hir_def::{ generics::{TypeOrConstParamData, TypeParamProvenance}, item_scope::ItemInNs, lang_item::{LangItem, LangItemTarget}, + nameres::DefMap, path::{Path, PathKind}, type_ref::{TraitBoundModifier, TypeBound, TypeRef}, visibility::Visibility, @@ -1488,7 +1489,7 @@ pub fn write_visibility( Visibility::Public => write!(f, "pub "), Visibility::Module(vis_id) => { let def_map = module_id.def_map(f.db.upcast()); - let root_module_id = def_map.module_id(def_map.root()); + let root_module_id = def_map.module_id(DefMap::ROOT); if vis_id == module_id { // pub(self) or omitted Ok(()) diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 0c8793c6df..9a2090ab79 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -548,7 +548,7 @@ impl HirDisplay for Module { // FIXME: Module doesn't have visibility saved in data. match self.name(f.db) { Some(name) => write!(f, "mod {}", name.display(f.db.upcast())), - None if self.is_crate_root(f.db) => match self.krate(f.db).display_name(f.db) { + None if self.is_crate_root() => match self.krate(f.db).display_name(f.db) { Some(name) => write!(f, "extern crate {name}"), None => f.write_str("extern crate {unknown}"), }, diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 7c432197a6..19709bb44a 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -118,7 +118,7 @@ pub use { find_path::PrefixKind, import_map, lang_item::LangItem, - nameres::ModuleSource, + nameres::{DefMap, ModuleSource}, path::{ModPath, PathKind}, type_ref::{Mutability, TypeRef}, visibility::Visibility, @@ -202,7 +202,7 @@ impl Crate { pub fn root_module(self, db: &dyn HirDatabase) -> Module { let def_map = db.crate_def_map(self.id); - Module { id: def_map.module_id(def_map.root()) } + Module { id: def_map.module_id(DefMap::ROOT) } } pub fn modules(self, db: &dyn HirDatabase) -> Vec { @@ -475,12 +475,11 @@ impl Module { /// in the module tree of any target in `Cargo.toml`. pub fn crate_root(self, db: &dyn HirDatabase) -> Module { let def_map = db.crate_def_map(self.id.krate()); - Module { id: def_map.module_id(def_map.root()) } + Module { id: def_map.module_id(DefMap::ROOT) } } - pub fn is_crate_root(self, db: &dyn HirDatabase) -> bool { - let def_map = db.crate_def_map(self.id.krate()); - def_map.root() == self.id.local_id + pub fn is_crate_root(self) -> bool { + DefMap::ROOT == self.id.local_id } /// Iterates over all child modules. diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs index d53e9e2fa9..480cb77b4f 100644 --- a/crates/ide-completion/src/completions.rs +++ b/crates/ide-completion/src/completions.rs @@ -158,7 +158,7 @@ impl Completions { path_ctx: &PathCompletionCtx, ) { ctx.process_all_names(&mut |name, res, doc_aliases| match res { - ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) if m.is_crate_root(ctx.db) => { + ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) if m.is_crate_root() => { self.add_module(ctx, path_ctx, m, name, doc_aliases); } _ => (), diff --git a/crates/ide-db/src/helpers.rs b/crates/ide-db/src/helpers.rs index 8e3b1eef15..eba9d8afc4 100644 --- a/crates/ide-db/src/helpers.rs +++ b/crates/ide-db/src/helpers.rs @@ -77,7 +77,7 @@ pub fn visit_file_defs( } module.impl_defs(db).into_iter().for_each(|impl_| cb(impl_.into())); - let is_root = module.is_crate_root(db); + let is_root = module.is_crate_root(); module .legacy_macros(db) .into_iter() diff --git a/crates/ide-db/src/rename.rs b/crates/ide-db/src/rename.rs index 5b2558ea8f..52a23b4b8f 100644 --- a/crates/ide-db/src/rename.rs +++ b/crates/ide-db/src/rename.rs @@ -178,7 +178,7 @@ fn rename_mod( let mut source_change = SourceChange::default(); - if module.is_crate_root(sema.db) { + if module.is_crate_root() { return Ok(source_change); } diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs index 9d00c71709..73cd5dcaf2 100644 --- a/crates/ide-db/src/search.rs +++ b/crates/ide-db/src/search.rs @@ -225,7 +225,7 @@ impl Definition { // def is crate root // FIXME: We don't do searches for crates currently, as a crate does not actually have a single name if let &Definition::Module(module) = self { - if module.is_crate_root(db) { + if module.is_crate_root() { return SearchScope::reverse_dependencies(db, module.krate()); } } @@ -392,7 +392,7 @@ impl<'a> FindUsages<'a> { let name = match self.def { // special case crate modules as these do not have a proper name - Definition::Module(module) if module.is_crate_root(self.sema.db) => { + Definition::Module(module) if module.is_crate_root() => { // FIXME: This assumes the crate name is always equal to its display name when it really isn't module .krate() @@ -500,7 +500,7 @@ impl<'a> FindUsages<'a> { let scope = search_scope.intersection(&SearchScope::module_and_children(self.sema.db, module)); - let is_crate_root = module.is_crate_root(self.sema.db).then(|| Finder::new("crate")); + let is_crate_root = module.is_crate_root().then(|| Finder::new("crate")); let finder = &Finder::new("super"); for (text, file_id, search_range) in scope_files(sema, &scope) { diff --git a/crates/ide-diagnostics/src/handlers/unlinked_file.rs b/crates/ide-diagnostics/src/handlers/unlinked_file.rs index b9c5384ea1..271e7ce73b 100644 --- a/crates/ide-diagnostics/src/handlers/unlinked_file.rs +++ b/crates/ide-diagnostics/src/handlers/unlinked_file.rs @@ -2,7 +2,7 @@ use std::iter; -use hir::{db::DefDatabase, InFile, ModuleSource}; +use hir::{db::DefDatabase, DefMap, InFile, ModuleSource}; use ide_db::{ base_db::{FileId, FileLoader, SourceDatabase, SourceDatabaseExt}, source_change::SourceChange, @@ -74,7 +74,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, file_id: FileId) -> Option> { 'crates: for &krate in &*ctx.sema.db.relevant_crates(file_id) { let crate_def_map = ctx.sema.db.crate_def_map(krate); - let root_module = &crate_def_map[crate_def_map.root()]; + let root_module = &crate_def_map[DefMap::ROOT]; let Some(root_file_id) = root_module.origin.file_id() else { continue }; let Some(crate_root_path) = source_root.path_for_file(&root_file_id) else { continue }; let Some(rel) = parent.strip_prefix(&crate_root_path.parent()?) else { continue }; diff --git a/crates/ide/src/status.rs b/crates/ide/src/status.rs index 70bff41121..d2c77e2dc7 100644 --- a/crates/ide/src/status.rs +++ b/crates/ide/src/status.rs @@ -1,7 +1,7 @@ use std::{fmt, marker::PhantomData}; use hir::{ - db::{AstIdMapQuery, AttrsQuery, ParseMacroExpansionQuery}, + db::{AstIdMapQuery, AttrsQuery, BlockDefMapQuery, ParseMacroExpansionQuery}, Attr, Attrs, ExpandResult, MacroFile, Module, }; use ide_db::{ @@ -51,6 +51,7 @@ pub(crate) fn status(db: &RootDatabase, file_id: Option) -> String { format_to!(buf, "\nDebug info:\n"); format_to!(buf, "{}\n", collect_query(AttrsQuery.in_db(db))); format_to!(buf, "{} ast id maps\n", collect_query_count(AstIdMapQuery.in_db(db))); + format_to!(buf, "{} block def maps\n", collect_query_count(BlockDefMapQuery.in_db(db))); if let Some(file_id) = file_id { format_to!(buf, "\nFile info:\n"); diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs index 925057ffaa..3c40246a69 100644 --- a/crates/ide/src/syntax_highlighting/highlight.rs +++ b/crates/ide/src/syntax_highlighting/highlight.rs @@ -340,7 +340,7 @@ fn highlight_def( Definition::Field(_) => Highlight::new(HlTag::Symbol(SymbolKind::Field)), Definition::Module(module) => { let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Module)); - if module.is_crate_root(db) { + if module.is_crate_root() { h |= HlMod::CrateRoot; } h diff --git a/lib/la-arena/src/lib.rs b/lib/la-arena/src/lib.rs index 1f8ef01a5b..5107f29439 100644 --- a/lib/la-arena/src/lib.rs +++ b/lib/la-arena/src/lib.rs @@ -18,6 +18,18 @@ pub use map::{ArenaMap, Entry, OccupiedEntry, VacantEntry}; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct RawIdx(u32); +impl RawIdx { + /// Constructs a [`RawIdx`] from a u32. + pub const fn from_u32(u32: u32) -> Self { + RawIdx(u32) + } + + /// Deconstructs a [`RawIdx`] into the underlying u32. + pub const fn into_u32(self) -> u32 { + self.0 + } +} + impl From for u32 { #[inline] fn from(raw: RawIdx) -> u32 { @@ -94,12 +106,12 @@ impl fmt::Debug for Idx { impl Idx { /// Creates a new index from a [`RawIdx`]. - pub fn from_raw(raw: RawIdx) -> Self { + pub const fn from_raw(raw: RawIdx) -> Self { Idx { raw, _ty: PhantomData } } /// Converts this index into the underlying [`RawIdx`]. - pub fn into_raw(self) -> RawIdx { + pub const fn into_raw(self) -> RawIdx { self.raw } } From 5c466ccc2bdfc978abccc988b59018273b5a210e Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 1 Jun 2023 15:04:38 +0200 Subject: [PATCH 2/6] Refactor out some crate wide data in DefMap into nested struct --- crates/hir-def/src/body/tests/block.rs | 4 +- crates/hir-def/src/nameres.rs | 83 +++++++++++-------- crates/hir-def/src/nameres/attr_resolution.rs | 4 +- crates/hir-def/src/nameres/collector.rs | 34 ++++---- crates/hir-def/src/nameres/path_resolution.rs | 2 +- crates/hir-def/src/nameres/tests/macros.rs | 4 +- 6 files changed, 73 insertions(+), 58 deletions(-) diff --git a/crates/hir-def/src/body/tests/block.rs b/crates/hir-def/src/body/tests/block.rs index 2899ca4337..6e77744f21 100644 --- a/crates/hir-def/src/body/tests/block.rs +++ b/crates/hir-def/src/body/tests/block.rs @@ -148,8 +148,8 @@ fn f() { } "#, expect![[r#" - BlockId(1) in ModuleId { krate: Idx::(0), block: Some(BlockId(0)), local_id: Idx::(1) } - BlockId(0) in ModuleId { krate: Idx::(0), block: None, local_id: Idx::(0) } + BlockId(1) in BlockRelativeModuleId { block: Some(BlockId(0)), local_id: Idx::(1) } + BlockId(0) in BlockRelativeModuleId { block: None, local_id: Idx::(0) } crate scope "#]], ); diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index 053ab5890e..86ba905203 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -109,14 +109,23 @@ pub struct DefMap { /// this contains all kinds of macro, not just `macro_rules!` macro. macro_use_prelude: FxHashMap, + /// Tracks which custom derives are in scope for an item, to allow resolution of derive helper + /// attributes. + derive_helpers_in_scope: FxHashMap, Vec<(Name, MacroId, MacroCallId)>>, + + diagnostics: Vec, + + // FIXME: Arc this so we can share it with block def maps + data: CrateData, +} + +#[derive(Debug, PartialEq, Eq)] +struct CrateData { /// Side table for resolving derive helpers. exported_derives: FxHashMap>, fn_proc_macro_mapping: FxHashMap, /// The error that occurred when failing to load the proc-macro dll. proc_macro_loading_error: Option>, - /// Tracks which custom derives are in scope for an item, to allow resolution of derive helper - /// attributes. - derive_helpers_in_scope: FxHashMap, Vec<(Name, MacroId, MacroCallId)>>, /// Custom attributes registered with `#![register_attr]`. registered_attrs: Vec, @@ -131,7 +140,6 @@ pub struct DefMap { edition: Edition, recursion_limit: Option, - diagnostics: Vec, } /// For `DefMap`s computed for a block expression, this stores its location in the parent map. @@ -278,7 +286,7 @@ impl DefMap { let module_data = ModuleData::new(ModuleOrigin::BlockExpr { block: block.ast_id }, visibility); - let mut def_map = DefMap::empty(krate, parent_map.edition, module_data); + let mut def_map = DefMap::empty(krate, parent_map.data.edition, module_data); def_map.block = Some(BlockInfo { block: block_id, parent: BlockRelativeModuleId { @@ -300,23 +308,25 @@ impl DefMap { _c: Count::new(), block: None, krate, - edition, - recursion_limit: None, extern_prelude: FxHashMap::default(), macro_use_prelude: FxHashMap::default(), - exported_derives: FxHashMap::default(), - fn_proc_macro_mapping: FxHashMap::default(), - proc_macro_loading_error: None, derive_helpers_in_scope: FxHashMap::default(), prelude: None, modules, - registered_attrs: Vec::new(), - registered_tools: Vec::new(), - unstable_features: FxHashSet::default(), diagnostics: Vec::new(), - rustc_coherence_is_core: false, - no_core: false, - no_std: false, + data: CrateData { + recursion_limit: None, + 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, + }, } } @@ -339,31 +349,31 @@ impl DefMap { } pub fn registered_tools(&self) -> &[SmolStr] { - &self.registered_tools + &self.data.registered_tools } pub fn registered_attrs(&self) -> &[SmolStr] { - &self.registered_attrs + &self.data.registered_attrs } pub fn is_unstable_feature_enabled(&self, feature: &str) -> bool { - self.unstable_features.contains(feature) + self.data.unstable_features.contains(feature) } pub fn is_rustc_coherence_is_core(&self) -> bool { - self.rustc_coherence_is_core + self.data.rustc_coherence_is_core } pub fn is_no_std(&self) -> bool { - self.no_std || self.no_core + self.data.no_std || self.data.no_core } pub fn fn_as_proc_macro(&self, id: FunctionId) -> Option { - self.fn_proc_macro_mapping.get(&id).copied() + self.data.fn_proc_macro_mapping.get(&id).copied() } pub fn proc_macro_loading_error(&self) -> Option<&str> { - self.proc_macro_loading_error.as_deref() + self.data.proc_macro_loading_error.as_deref() } pub fn krate(&self) -> CrateId { @@ -540,25 +550,28 @@ impl DefMap { // Exhaustive match to require handling new fields. let Self { _c: _, - exported_derives, extern_prelude, macro_use_prelude, diagnostics, modules, - registered_attrs, - registered_tools, - fn_proc_macro_mapping, derive_helpers_in_scope, - unstable_features, - proc_macro_loading_error: _, block: _, - edition: _, - recursion_limit: _, krate: _, prelude: _, - rustc_coherence_is_core: _, - no_core: _, - no_std: _, + data: + CrateData { + exported_derives, + fn_proc_macro_mapping, + registered_attrs, + registered_tools, + unstable_features, + proc_macro_loading_error: _, + rustc_coherence_is_core: _, + no_core: _, + no_std: _, + edition: _, + recursion_limit: _, + }, } = self; extern_prelude.shrink_to_fit(); @@ -583,7 +596,7 @@ impl DefMap { } pub fn recursion_limit(&self) -> Option { - self.recursion_limit + self.data.recursion_limit } } diff --git a/crates/hir-def/src/nameres/attr_resolution.rs b/crates/hir-def/src/nameres/attr_resolution.rs index 6567bda709..a7abf44591 100644 --- a/crates/hir-def/src/nameres/attr_resolution.rs +++ b/crates/hir-def/src/nameres/attr_resolution.rs @@ -78,7 +78,7 @@ impl DefMap { let name = name.to_smol_str(); let pred = |n: &_| *n == name; - let registered = self.registered_tools.iter().map(SmolStr::as_str); + let registered = self.data.registered_tools.iter().map(SmolStr::as_str); let is_tool = TOOL_MODULES.iter().copied().chain(registered).any(pred); // FIXME: tool modules can be shadowed by actual modules if is_tool { @@ -86,7 +86,7 @@ impl DefMap { } if segments.len() == 1 { - let mut registered = self.registered_attrs.iter().map(SmolStr::as_str); + let mut registered = self.data.registered_attrs.iter().map(SmolStr::as_str); let is_inert = find_builtin_attr_idx(&name).is_some() || registered.any(pred); return is_inert; } diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index b431b6f647..53e1273341 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -98,11 +98,11 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: DefMap, tree_id: T .collect() } Some(Err(e)) => { - def_map.proc_macro_loading_error = Some(e.clone().into_boxed_str()); + def_map.data.proc_macro_loading_error = Some(e.clone().into_boxed_str()); Vec::new() } None => { - def_map.proc_macro_loading_error = + def_map.data.proc_macro_loading_error = Some("No proc-macros present for crate".to_owned().into_boxed_str()); Vec::new() } @@ -306,7 +306,7 @@ impl DefCollector<'_> { if *attr_name == hir_expand::name![recursion_limit] { if let Some(limit) = attr.string_value() { if let Ok(limit) = limit.parse() { - self.def_map.recursion_limit = Some(limit); + self.def_map.data.recursion_limit = Some(limit); } } continue; @@ -320,17 +320,17 @@ impl DefCollector<'_> { } if *attr_name == hir_expand::name![no_core] { - self.def_map.no_core = true; + self.def_map.data.no_core = true; continue; } if *attr_name == hir_expand::name![no_std] { - self.def_map.no_std = true; + self.def_map.data.no_std = true; continue; } if attr_name.as_text().as_deref() == Some("rustc_coherence_is_core") { - self.def_map.rustc_coherence_is_core = true; + self.def_map.data.rustc_coherence_is_core = true; continue; } @@ -344,7 +344,7 @@ impl DefCollector<'_> { [name] => Some(name.to_smol_str()), _ => None, }); - self.def_map.unstable_features.extend(features); + self.def_map.data.unstable_features.extend(features); } let attr_is_register_like = *attr_name == hir_expand::name![register_attr] @@ -359,10 +359,10 @@ impl DefCollector<'_> { }; if *attr_name == hir_expand::name![register_attr] { - self.def_map.registered_attrs.push(registered_name.to_smol_str()); + self.def_map.data.registered_attrs.push(registered_name.to_smol_str()); cov_mark::hit!(register_attr); } else { - self.def_map.registered_tools.push(registered_name.to_smol_str()); + self.def_map.data.registered_tools.push(registered_name.to_smol_str()); cov_mark::hit!(register_tool); } } @@ -530,12 +530,12 @@ impl DefCollector<'_> { fn inject_prelude(&mut self) { // See compiler/rustc_builtin_macros/src/standard_library_imports.rs - if self.def_map.no_core { + if self.def_map.data.no_core { // libcore does not get a prelude. return; } - let krate = if self.def_map.no_std { + let krate = if self.def_map.data.no_std { name![core] } else { let std = name![std]; @@ -548,13 +548,13 @@ impl DefCollector<'_> { } }; - let edition = match self.def_map.edition { + let edition = match self.def_map.data.edition { Edition::Edition2015 => name![rust_2015], Edition::Edition2018 => name![rust_2018], Edition::Edition2021 => name![rust_2021], }; - let path_kind = match self.def_map.edition { + let path_kind = match self.def_map.data.edition { Edition::Edition2015 => PathKind::Plain, _ => PathKind::Abs, }; @@ -611,10 +611,11 @@ impl DefCollector<'_> { self.define_proc_macro(def.name.clone(), proc_macro_id); if let ProcMacroKind::CustomDerive { helpers } = def.kind { self.def_map + .data .exported_derives .insert(macro_id_to_def_id(self.db, proc_macro_id.into()), helpers); } - self.def_map.fn_proc_macro_mapping.insert(fn_id, proc_macro_id); + self.def_map.data.fn_proc_macro_mapping.insert(fn_id, proc_macro_id); } /// Define a macro with `macro_rules`. @@ -773,7 +774,7 @@ impl DefCollector<'_> { fn resolve_import(&self, module_id: LocalModuleId, import: &Import) -> PartialResolvedImport { let _p = profile::span("resolve_import") .detail(|| format!("{}", import.path.display(self.db.upcast()))); - tracing::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition); + tracing::debug!("resolving import: {:?} ({:?})", import, self.def_map.data.edition); if import.is_extern_crate { let name = import .path @@ -1153,7 +1154,7 @@ impl DefCollector<'_> { // Record its helper attributes. if def_id.krate != self.def_map.krate { let def_map = self.db.crate_def_map(def_id.krate); - if let Some(helpers) = def_map.exported_derives.get(&def_id) { + if let Some(helpers) = def_map.data.exported_derives.get(&def_id) { self.def_map .derive_helpers_in_scope .entry(ast_id.ast_id.map(|it| it.upcast())) @@ -2166,6 +2167,7 @@ impl ModCollector<'_, '_> { if let Some(helpers) = helpers_opt { self.def_collector .def_map + .data .exported_derives .insert(macro_id_to_def_id(self.def_collector.db, macro_id.into()), helpers); } diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs index 751536db38..bfba6eab6d 100644 --- a/crates/hir-def/src/nameres/path_resolution.rs +++ b/crates/hir-def/src/nameres/path_resolution.rs @@ -218,7 +218,7 @@ impl DefMap { // rust-lang/rust#57745) // FIXME there must be a nicer way to write this condition PathKind::Plain | PathKind::Abs - if self.edition == Edition::Edition2015 + if self.data.edition == Edition::Edition2015 && (path.kind == PathKind::Abs || mode == ResolveMode::Import) => { let (_, segment) = match segments.next() { diff --git a/crates/hir-def/src/nameres/tests/macros.rs b/crates/hir-def/src/nameres/tests/macros.rs index ae509de056..f4cca8d68d 100644 --- a/crates/hir-def/src/nameres/tests/macros.rs +++ b/crates/hir-def/src/nameres/tests/macros.rs @@ -1094,8 +1094,8 @@ pub fn derive_macro_2(_item: TokenStream) -> TokenStream { let krate = db.crate_graph().iter().next().unwrap(); let def_map = db.crate_def_map(krate); - assert_eq!(def_map.exported_derives.len(), 1); - match def_map.exported_derives.values().next() { + assert_eq!(def_map.data.exported_derives.len(), 1); + match def_map.data.exported_derives.values().next() { Some(helpers) => match &**helpers { [attr] => assert_eq!(attr.display(&db).to_string(), "helper_attr"), _ => unreachable!(), From bdca349573c00542635848a16276272fb0c1acc9 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 1 Jun 2023 15:27:05 +0200 Subject: [PATCH 3/6] Arc DefMap::data so the block def maps can share it --- crates/hir-def/src/nameres.rs | 51 ++++++++-------- crates/hir-def/src/nameres/collector.rs | 77 +++++++++++++------------ 2 files changed, 68 insertions(+), 60 deletions(-) diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index 86ba905203..e900de88dd 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -116,10 +116,10 @@ pub struct DefMap { diagnostics: Vec, // FIXME: Arc this so we can share it with block def maps - data: CrateData, + data: Arc, } -#[derive(Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq)] struct CrateData { /// Side table for resolving derive helpers. exported_derives: FxHashMap>, @@ -141,6 +141,28 @@ struct CrateData { edition: Edition, recursion_limit: Option, } +impl CrateData { + fn shrink_to_fit(&mut self) { + let Self { + exported_derives, + fn_proc_macro_mapping, + registered_attrs, + registered_tools, + unstable_features, + proc_macro_loading_error: _, + rustc_coherence_is_core: _, + no_core: _, + no_std: _, + edition: _, + recursion_limit: _, + } = self; + exported_derives.shrink_to_fit(); + fn_proc_macro_mapping.shrink_to_fit(); + registered_attrs.shrink_to_fit(); + registered_tools.shrink_to_fit(); + unstable_features.shrink_to_fit(); + } +} /// For `DefMap`s computed for a block expression, this stores its location in the parent map. #[derive(Debug, PartialEq, Eq, Clone, Copy)] @@ -287,6 +309,7 @@ impl DefMap { ModuleData::new(ModuleOrigin::BlockExpr { block: block.ast_id }, visibility); 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 { @@ -314,7 +337,7 @@ impl DefMap { prelude: None, modules, diagnostics: Vec::new(), - data: CrateData { + data: Arc::new(CrateData { recursion_limit: None, exported_derives: FxHashMap::default(), fn_proc_macro_mapping: FxHashMap::default(), @@ -326,7 +349,7 @@ impl DefMap { no_core: false, no_std: false, edition, - }, + }), } } @@ -558,32 +581,14 @@ impl DefMap { block: _, krate: _, prelude: _, - data: - CrateData { - exported_derives, - fn_proc_macro_mapping, - registered_attrs, - registered_tools, - unstable_features, - proc_macro_loading_error: _, - rustc_coherence_is_core: _, - no_core: _, - no_std: _, - edition: _, - recursion_limit: _, - }, + data: _, } = self; extern_prelude.shrink_to_fit(); macro_use_prelude.shrink_to_fit(); - exported_derives.shrink_to_fit(); diagnostics.shrink_to_fit(); modules.shrink_to_fit(); - registered_attrs.shrink_to_fit(); - registered_tools.shrink_to_fit(); - fn_proc_macro_mapping.shrink_to_fit(); derive_helpers_in_scope.shrink_to_fit(); - unstable_features.shrink_to_fit(); for (_, module) in modules.iter_mut() { module.children.shrink_to_fit(); module.scope.shrink_to_fit(); diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 53e1273341..9e35c47d4f 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -86,7 +86,7 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: DefMap, tree_id: T let proc_macros = if is_proc_macro { match db.proc_macros().get(&def_map.krate) { Some(Ok(proc_macros)) => { - proc_macros + Ok(proc_macros .iter() .enumerate() .map(|(idx, it)| { @@ -95,20 +95,13 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: DefMap, tree_id: T tt::Ident { text: it.name.clone(), span: tt::TokenId::unspecified() }; (name.as_name(), ProcMacroExpander::new(base_db::ProcMacroId(idx as u32))) }) - .collect() - } - Some(Err(e)) => { - def_map.data.proc_macro_loading_error = Some(e.clone().into_boxed_str()); - Vec::new() - } - None => { - def_map.data.proc_macro_loading_error = - Some("No proc-macros present for crate".to_owned().into_boxed_str()); - Vec::new() + .collect()) } + Some(Err(e)) => Err(e.clone().into_boxed_str()), + None => Err("No proc-macros present for crate".to_owned().into_boxed_str()), } } else { - vec![] + Ok(vec![]) }; let mut collector = DefCollector { @@ -263,7 +256,7 @@ struct DefCollector<'a> { /// built by the build system, and is the list of proc. macros we can actually expand. It is /// empty when proc. macro support is disabled (in which case we still do name resolution for /// them). - proc_macros: Vec<(Name, ProcMacroExpander)>, + proc_macros: Result, Box>, is_proc_macro: bool, from_glob_import: PerNsGlobImports, /// If we fail to resolve an attribute on a `ModItem`, we fall back to ignoring the attribute. @@ -290,6 +283,11 @@ impl DefCollector<'_> { let module_id = DefMap::ROOT; let attrs = item_tree.top_level_attrs(self.db, self.def_map.krate); + let crate_data = Arc::get_mut(&mut self.def_map.data).unwrap(); + + if let Err(e) = &self.proc_macros { + crate_data.proc_macro_loading_error = Some(e.clone()); + } // Process other crate-level attributes. for attr in &*attrs { @@ -306,7 +304,7 @@ impl DefCollector<'_> { if *attr_name == hir_expand::name![recursion_limit] { if let Some(limit) = attr.string_value() { if let Ok(limit) = limit.parse() { - self.def_map.data.recursion_limit = Some(limit); + crate_data.recursion_limit = Some(limit); } } continue; @@ -320,17 +318,17 @@ impl DefCollector<'_> { } if *attr_name == hir_expand::name![no_core] { - self.def_map.data.no_core = true; + crate_data.no_core = true; continue; } if *attr_name == hir_expand::name![no_std] { - self.def_map.data.no_std = true; + crate_data.no_std = true; continue; } if attr_name.as_text().as_deref() == Some("rustc_coherence_is_core") { - self.def_map.data.rustc_coherence_is_core = true; + crate_data.rustc_coherence_is_core = true; continue; } @@ -344,7 +342,7 @@ impl DefCollector<'_> { [name] => Some(name.to_smol_str()), _ => None, }); - self.def_map.data.unstable_features.extend(features); + crate_data.unstable_features.extend(features); } let attr_is_register_like = *attr_name == hir_expand::name![register_attr] @@ -359,14 +357,15 @@ impl DefCollector<'_> { }; if *attr_name == hir_expand::name![register_attr] { - self.def_map.data.registered_attrs.push(registered_name.to_smol_str()); + crate_data.registered_attrs.push(registered_name.to_smol_str()); cov_mark::hit!(register_attr); } else { - self.def_map.data.registered_tools.push(registered_name.to_smol_str()); + crate_data.registered_tools.push(registered_name.to_smol_str()); cov_mark::hit!(register_tool); } } + crate_data.shrink_to_fit(); self.inject_prelude(); ModCollector { @@ -598,24 +597,29 @@ impl DefCollector<'_> { def: ProcMacroDef, id: ItemTreeId, fn_id: FunctionId, - module_id: ModuleId, ) { + if self.def_map.block.is_some() { + return; + } + let crate_root = self.def_map.module_id(DefMap::ROOT); + let kind = def.kind.to_basedb_kind(); - let (expander, kind) = match self.proc_macros.iter().find(|(n, _)| n == &def.name) { - Some(&(_, expander)) => (expander, kind), - None => (ProcMacroExpander::dummy(), kind), - }; + let (expander, kind) = + match self.proc_macros.as_ref().map(|it| it.iter().find(|(n, _)| n == &def.name)) { + Ok(Some(&(_, expander))) => (expander, kind), + _ => (ProcMacroExpander::dummy(), kind), + }; let proc_macro_id = - ProcMacroLoc { container: module_id, id, expander, kind }.intern(self.db); + ProcMacroLoc { container: crate_root, id, expander, kind }.intern(self.db); self.define_proc_macro(def.name.clone(), proc_macro_id); + let crate_data = Arc::get_mut(&mut self.def_map.data).unwrap(); if let ProcMacroKind::CustomDerive { helpers } = def.kind { - self.def_map - .data + crate_data .exported_derives .insert(macro_id_to_def_id(self.db, proc_macro_id.into()), helpers); } - self.def_map.data.fn_proc_macro_mapping.insert(fn_id, proc_macro_id); + crate_data.fn_proc_macro_mapping.insert(fn_id, proc_macro_id); } /// Define a macro with `macro_rules`. @@ -1639,12 +1643,10 @@ impl ModCollector<'_, '_> { let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); if self.def_collector.is_proc_macro && self.module_id == DefMap::ROOT { if let Some(proc_macro) = attrs.parse_proc_macro_decl(&it.name) { - let crate_root = def_map.module_id(DefMap::ROOT); self.def_collector.export_proc_macro( proc_macro, ItemTreeId::new(self.tree_id, id), fn_id, - crate_root, ); } } @@ -2165,11 +2167,12 @@ impl ModCollector<'_, '_> { &self.item_tree[mac.visibility], ); if let Some(helpers) = helpers_opt { - self.def_collector - .def_map - .data - .exported_derives - .insert(macro_id_to_def_id(self.def_collector.db, macro_id.into()), helpers); + if self.def_collector.def_map.block.is_none() { + Arc::get_mut(&mut self.def_collector.def_map.data) + .unwrap() + .exported_derives + .insert(macro_id_to_def_id(self.def_collector.db, macro_id.into()), helpers); + } } } @@ -2277,7 +2280,7 @@ mod tests { unresolved_macros: Vec::new(), mod_dirs: FxHashMap::default(), cfg_options: &CfgOptions::default(), - proc_macros: Default::default(), + proc_macros: Ok(vec![]), from_glob_import: Default::default(), skip_attrs: Default::default(), is_proc_macro: false, From 1e6406e22338af234180071c5b82e390cb43904b Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 1 Jun 2023 15:49:05 +0200 Subject: [PATCH 4/6] Move extern prelude into CrateData --- crates/hir-def/src/nameres.rs | 26 +++++++------ crates/hir-def/src/nameres/collector.rs | 39 +++++++++++-------- crates/hir-def/src/nameres/path_resolution.rs | 9 +++-- 3 files changed, 43 insertions(+), 31 deletions(-) diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index e900de88dd..e4693a2b78 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -103,8 +103,6 @@ pub struct DefMap { /// but that attribute is nightly and when used in a block, it affects resolution globally /// so we aren't handling this correctly anyways). prelude: Option, - /// The extern prelude is only populated for non-block DefMaps - extern_prelude: FxHashMap, /// `macro_use` prelude that contains macros from `#[macro_use]`'d external crates. Note that /// this contains all kinds of macro, not just `macro_rules!` macro. macro_use_prelude: FxHashMap, @@ -115,12 +113,13 @@ pub struct DefMap { diagnostics: Vec, - // FIXME: Arc this so we can share it with block def maps data: Arc, } #[derive(Clone, Debug, PartialEq, Eq)] struct CrateData { + extern_prelude: FxHashMap, + /// Side table for resolving derive helpers. exported_derives: FxHashMap>, fn_proc_macro_mapping: FxHashMap, @@ -141,9 +140,11 @@ struct CrateData { edition: Edition, recursion_limit: Option, } + impl CrateData { fn shrink_to_fit(&mut self) { let Self { + extern_prelude, exported_derives, fn_proc_macro_mapping, registered_attrs, @@ -156,6 +157,7 @@ impl CrateData { edition: _, recursion_limit: _, } = self; + extern_prelude.shrink_to_fit(); exported_derives.shrink_to_fit(); fn_proc_macro_mapping.shrink_to_fit(); registered_attrs.shrink_to_fit(); @@ -181,7 +183,11 @@ struct BlockRelativeModuleId { impl BlockRelativeModuleId { fn def_map(self, db: &dyn DefDatabase, krate: CrateId) -> Arc { - ModuleId { krate, block: self.block, local_id: self.local_id }.def_map(db) + self.into_module(krate).def_map(db) + } + + fn into_module(self, krate: CrateId) -> ModuleId { + ModuleId { krate, block: self.block, local_id: self.local_id } } } @@ -330,15 +336,14 @@ impl DefMap { DefMap { _c: Count::new(), block: None, + modules, krate, - extern_prelude: FxHashMap::default(), + prelude: None, macro_use_prelude: FxHashMap::default(), derive_helpers_in_scope: FxHashMap::default(), - prelude: None, - modules, diagnostics: Vec::new(), data: Arc::new(CrateData { - recursion_limit: None, + extern_prelude: FxHashMap::default(), exported_derives: FxHashMap::default(), fn_proc_macro_mapping: FxHashMap::default(), proc_macro_loading_error: None, @@ -349,6 +354,7 @@ impl DefMap { no_core: false, no_std: false, edition, + recursion_limit: None, }), } } @@ -412,7 +418,7 @@ impl DefMap { } pub(crate) fn extern_prelude(&self) -> impl Iterator + '_ { - self.extern_prelude.iter().map(|(name, def)| (name, *def)) + self.data.extern_prelude.iter().map(|(name, def)| (name, *def)) } pub(crate) fn macro_use_prelude(&self) -> impl Iterator + '_ { @@ -573,7 +579,6 @@ impl DefMap { // Exhaustive match to require handling new fields. let Self { _c: _, - extern_prelude, macro_use_prelude, diagnostics, modules, @@ -584,7 +589,6 @@ impl DefMap { data: _, } = self; - extern_prelude.shrink_to_fit(); macro_use_prelude.shrink_to_fit(); diagnostics.shrink_to_fit(); modules.shrink_to_fit(); diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 9e35c47d4f..29ee13648e 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -5,7 +5,7 @@ use std::{iter, mem}; -use base_db::{CrateId, Edition, FileId}; +use base_db::{CrateId, Dependency, Edition, FileId}; use cfg::{CfgExpr, CfgOptions}; use either::Either; use hir_expand::{ @@ -62,7 +62,7 @@ static GLOB_RECURSION_LIMIT: Limit = Limit::new(100); static EXPANSION_DEPTH_LIMIT: Limit = Limit::new(128); static FIXED_POINT_LIMIT: Limit = Limit::new(8192); -pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: DefMap, tree_id: TreeId) -> DefMap { +pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeId) -> DefMap { let crate_graph = db.crate_graph(); let mut deps = FxHashMap::default(); @@ -70,14 +70,8 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: DefMap, tree_id: T let krate = &crate_graph[def_map.krate]; for dep in &krate.dependencies { tracing::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id); - let dep_def_map = db.crate_def_map(dep.crate_id); - let dep_root = dep_def_map.module_id(DefMap::ROOT); - deps.insert(dep.as_name(), dep_root); - - if dep.is_prelude() && !tree_id.is_block() { - def_map.extern_prelude.insert(dep.as_name(), dep_root); - } + deps.insert(dep.as_name(), dep.clone()); } let cfg_options = &krate.cfg_options; @@ -245,7 +239,7 @@ enum MacroDirectiveKind { struct DefCollector<'a> { db: &'a dyn DefDatabase, def_map: DefMap, - deps: FxHashMap, + deps: FxHashMap, glob_imports: FxHashMap>, unresolved_imports: Vec, indeterminate_imports: Vec, @@ -289,6 +283,15 @@ impl DefCollector<'_> { crate_data.proc_macro_loading_error = Some(e.clone()); } + for (name, dep) in &self.deps { + if dep.is_prelude() { + crate_data.extern_prelude.insert( + name.clone(), + ModuleId { krate: dep.crate_id, block: None, local_id: DefMap::ROOT }, + ); + } + } + // Process other crate-level attributes. for attr in &*attrs { if let Some(cfg) = attr.cfg() { @@ -832,15 +835,16 @@ impl DefCollector<'_> { if *name == name!(self) { cov_mark::hit!(extern_crate_self_as); let root = match self.def_map.block { - Some(_) => { - let def_map = self.def_map.crate_root(self.db).def_map(self.db); - def_map.module_id(DefMap::ROOT) - } + Some(_) => self.def_map.crate_root(self.db), None => self.def_map.module_id(DefMap::ROOT), }; Some(root) } else { - self.deps.get(name).copied() + self.deps.get(name).map(|dep| ModuleId { + krate: dep.crate_id, + block: None, + local_id: DefMap::ROOT, + }) } } @@ -883,7 +887,10 @@ impl DefCollector<'_> { { if let (Some(ModuleDefId::ModuleId(def)), Some(name)) = (def.take_types(), name) { - self.def_map.extern_prelude.insert(name.clone(), def); + Arc::get_mut(&mut self.def_map.data) + .unwrap() + .extern_prelude + .insert(name.clone(), def); } } diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs index bfba6eab6d..c5335aaf12 100644 --- a/crates/hir-def/src/nameres/path_resolution.rs +++ b/crates/hir-def/src/nameres/path_resolution.rs @@ -80,8 +80,8 @@ impl DefMap { name: &Name, ) -> Option { match self.block { - Some(_) => self.crate_root(db).def_map(db).extern_prelude.get(name).copied(), - None => self.extern_prelude.get(name).copied(), + Some(_) => self.crate_root(db).def_map(db).data.extern_prelude.get(name).copied(), + None => self.data.extern_prelude.get(name).copied(), } } @@ -304,7 +304,7 @@ impl DefMap { Some((_, segment)) => segment, None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), }; - if let Some(&def) = self.extern_prelude.get(segment) { + if let Some(&def) = self.data.extern_prelude.get(segment) { tracing::debug!("absolute path {:?} resolved to crate {:?}", path, def); PerNs::types(def.into(), Visibility::Public) } else { @@ -453,7 +453,8 @@ impl DefMap { }; let extern_prelude = || { - self.extern_prelude + self.data + .extern_prelude .get(name) .map_or(PerNs::none(), |&it| PerNs::types(it.into(), Visibility::Public)) }; From 54e3ef658a83dea6a9af282627496114df6dd641 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 1 Jun 2023 15:50:19 +0200 Subject: [PATCH 5/6] Rename nameres::CrateData to DefMapCrateData --- crates/hir-def/src/nameres.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index e4693a2b78..b5a30f9d88 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -113,11 +113,12 @@ pub struct DefMap { diagnostics: Vec, - data: Arc, + data: Arc, } +/// Data that belongs to a crate which is shared between a crate's def map and all its block def maps. #[derive(Clone, Debug, PartialEq, Eq)] -struct CrateData { +struct DefMapCrateData { extern_prelude: FxHashMap, /// Side table for resolving derive helpers. @@ -141,7 +142,7 @@ struct CrateData { recursion_limit: Option, } -impl CrateData { +impl DefMapCrateData { fn shrink_to_fit(&mut self) { let Self { extern_prelude, @@ -342,7 +343,7 @@ impl DefMap { macro_use_prelude: FxHashMap::default(), derive_helpers_in_scope: FxHashMap::default(), diagnostics: Vec::new(), - data: Arc::new(CrateData { + data: Arc::new(DefMapCrateData { extern_prelude: FxHashMap::default(), exported_derives: FxHashMap::default(), fn_proc_macro_mapping: FxHashMap::default(), From 11b937177bbad6afcffebefd7cd81934ae6b0baa Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 1 Jun 2023 17:58:08 +0200 Subject: [PATCH 6/6] Skip extern prelude path resolution in block def maps --- crates/hir-def/src/find_path.rs | 4 +-- crates/hir-def/src/nameres.rs | 11 ++----- crates/hir-def/src/nameres/collector.rs | 6 +--- crates/hir-def/src/nameres/path_resolution.rs | 32 +++++++++---------- 4 files changed, 21 insertions(+), 32 deletions(-) diff --git a/crates/hir-def/src/find_path.rs b/crates/hir-def/src/find_path.rs index 1e299fecc9..e8cc2eab46 100644 --- a/crates/hir-def/src/find_path.rs +++ b/crates/hir-def/src/find_path.rs @@ -81,7 +81,7 @@ fn find_path_inner( } let def_map = from.def_map(db); - let crate_root = def_map.crate_root(db); + let crate_root = def_map.crate_root(); // - if the item is a module, jump straight to module search if let ItemInNs::Types(ModuleDefId::ModuleId(module_id)) = item { let mut visited_modules = FxHashSet::default(); @@ -454,7 +454,7 @@ fn find_local_import_locations( worklist.push(ancestor); } - let def_map = def_map.crate_root(db).def_map(db); + let def_map = def_map.crate_root().def_map(db); let mut seen: FxHashSet<_> = FxHashSet::default(); diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index b5a30f9d88..9b520bc303 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -431,15 +431,8 @@ impl DefMap { ModuleId { krate: self.krate, local_id, block } } - pub(crate) fn crate_root(&self, db: &dyn DefDatabase) -> ModuleId { - self.with_ancestor_maps(db, Self::ROOT, &mut |def_map, _module| { - if def_map.block.is_none() { - Some(def_map.module_id(Self::ROOT)) - } else { - None - } - }) - .expect("DefMap chain without root") + pub(crate) fn crate_root(&self) -> ModuleId { + ModuleId { krate: self.krate, block: None, local_id: DefMap::ROOT } } pub(crate) fn resolve_path( diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 29ee13648e..06542b4b1e 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -834,11 +834,7 @@ impl DefCollector<'_> { fn resolve_extern_crate(&self, name: &Name) -> Option { if *name == name!(self) { cov_mark::hit!(extern_crate_self_as); - let root = match self.def_map.block { - Some(_) => self.def_map.crate_root(self.db), - None => self.def_map.module_id(DefMap::ROOT), - }; - Some(root) + Some(self.def_map.crate_root()) } else { self.deps.get(name).map(|dep| ModuleId { krate: dep.crate_id, diff --git a/crates/hir-def/src/nameres/path_resolution.rs b/crates/hir-def/src/nameres/path_resolution.rs index c5335aaf12..5f6163175a 100644 --- a/crates/hir-def/src/nameres/path_resolution.rs +++ b/crates/hir-def/src/nameres/path_resolution.rs @@ -20,7 +20,7 @@ use crate::{ path::{ModPath, PathKind}, per_ns::PerNs, visibility::{RawVisibility, Visibility}, - AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId, + AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, }; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -74,17 +74,6 @@ impl PerNs { } impl DefMap { - pub(super) fn resolve_name_in_extern_prelude( - &self, - db: &dyn DefDatabase, - name: &Name, - ) -> Option { - match self.block { - Some(_) => self.crate_root(db).def_map(db).data.extern_prelude.get(name).copied(), - None => self.data.extern_prelude.get(name).copied(), - } - } - pub(crate) fn resolve_visibility( &self, db: &dyn DefDatabase, @@ -204,7 +193,7 @@ impl DefMap { PathKind::DollarCrate(krate) => { if krate == self.krate { cov_mark::hit!(macro_dollar_crate_self); - PerNs::types(self.crate_root(db).into(), Visibility::Public) + PerNs::types(self.crate_root().into(), Visibility::Public) } else { let def_map = db.crate_def_map(krate); let module = def_map.module_id(Self::ROOT); @@ -212,7 +201,7 @@ impl DefMap { PerNs::types(module.into(), Visibility::Public) } } - PathKind::Crate => PerNs::types(self.crate_root(db).into(), Visibility::Public), + PathKind::Crate => PerNs::types(self.crate_root().into(), Visibility::Public), // plain import or absolute path in 2015: crate-relative with // fallback to extern prelude (with the simplification in // rust-lang/rust#57745) @@ -453,6 +442,10 @@ impl DefMap { }; let extern_prelude = || { + if self.block.is_some() { + // Don't resolve extern prelude in block `DefMap`s. + return PerNs::none(); + } self.data .extern_prelude .get(name) @@ -479,13 +472,20 @@ impl DefMap { ) -> PerNs { let from_crate_root = match self.block { Some(_) => { - let def_map = self.crate_root(db).def_map(db); + let def_map = self.crate_root().def_map(db); def_map[Self::ROOT].scope.get(name) } None => self[Self::ROOT].scope.get(name), }; let from_extern_prelude = || { - self.resolve_name_in_extern_prelude(db, name) + if self.block.is_some() { + // Don't resolve extern prelude in block `DefMap`s. + return PerNs::none(); + } + self.data + .extern_prelude + .get(name) + .copied() .map_or(PerNs::none(), |it| PerNs::types(it.into(), Visibility::Public)) };