Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/nameres/collector.rs')
| -rw-r--r-- | crates/hir-def/src/nameres/collector.rs | 162 |
1 files changed, 111 insertions, 51 deletions
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index bf013c25ef..371e994334 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -5,7 +5,7 @@ use std::{cmp::Ordering, iter, mem, ops::Not}; -use base_db::{CrateId, CrateOrigin, Dependency, LangCrateOrigin}; +use base_db::{BuiltDependency, Crate, CrateOrigin, LangCrateOrigin}; use cfg::{CfgAtom, CfgExpr, CfgOptions}; use either::Either; use hir_expand::{ @@ -39,8 +39,8 @@ use crate::{ mod_resolution::ModDir, path_resolution::ReachedFixedPoint, proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroDef, ProcMacroKind}, - sub_namespace_match, BuiltinShadowMode, DefMap, MacroSubNs, ModuleData, ModuleOrigin, - ResolveMode, + sub_namespace_match, BuiltinShadowMode, DefMap, LocalDefMap, MacroSubNs, ModuleData, + ModuleOrigin, ResolveMode, }, path::{ImportAlias, ModPath, PathKind}, per_ns::{Item, PerNs}, @@ -57,10 +57,14 @@ use crate::{ const GLOB_RECURSION_LIMIT: usize = 100; const FIXED_POINT_LIMIT: usize = 8192; -pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeId) -> DefMap { - let crate_graph = db.crate_graph(); - - let krate = &crate_graph[def_map.krate]; +pub(super) fn collect_defs( + db: &dyn DefDatabase, + def_map: DefMap, + tree_id: TreeId, + crate_local_def_map: Option<Arc<LocalDefMap>>, +) -> (DefMap, LocalDefMap) { + let krate = &def_map.krate.data(db); + let cfg_options = def_map.krate.cfg_options(db); // populate external prelude and dependency list let mut deps = @@ -72,8 +76,10 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI } let proc_macros = if krate.is_proc_macro { - db.proc_macros() - .for_crate(def_map.krate, db.syntax_context(tree_id.file_id(), krate.edition)) + db.proc_macros_for_crate(def_map.krate) + .and_then(|proc_macros| { + proc_macros.list(db.syntax_context(tree_id.file_id(), krate.edition)) + }) .unwrap_or_default() } else { Default::default() @@ -82,13 +88,15 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI let mut collector = DefCollector { db, def_map, + local_def_map: LocalDefMap::default(), + crate_local_def_map, deps, glob_imports: FxHashMap::default(), unresolved_imports: Vec::new(), indeterminate_imports: Vec::new(), unresolved_macros: Vec::new(), mod_dirs: FxHashMap::default(), - cfg_options: &krate.cfg_options, + cfg_options, proc_macros, from_glob_import: Default::default(), skip_attrs: Default::default(), @@ -101,9 +109,10 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI collector.seed_with_top_level(); } collector.collect(); - let mut def_map = collector.finish(); + let (mut def_map, mut local_def_map) = collector.finish(); def_map.shrink_to_fit(); - def_map + local_def_map.shrink_to_fit(); + (def_map, local_def_map) } #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -205,8 +214,11 @@ enum MacroDirectiveKind { struct DefCollector<'a> { db: &'a dyn DefDatabase, def_map: DefMap, + local_def_map: LocalDefMap, + /// Set only in case of blocks. + crate_local_def_map: Option<Arc<LocalDefMap>>, // The dependencies of the current crate, including optional deps like `test`. - deps: FxHashMap<Name, Dependency>, + deps: FxHashMap<Name, BuiltDependency>, glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility, GlobId)>>, unresolved_imports: Vec<ImportDirective>, indeterminate_imports: Vec<(ImportDirective, PerNs)>, @@ -238,8 +250,7 @@ impl DefCollector<'_> { fn seed_with_top_level(&mut self) { let _p = tracing::info_span!("seed_with_top_level").entered(); - let crate_graph = self.db.crate_graph(); - let file_id = crate_graph[self.def_map.krate].root_file_id(); + let file_id = self.def_map.krate.data(self.db).root_file_id(); let item_tree = self.db.file_item_tree(file_id.into()); 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(); @@ -310,20 +321,24 @@ impl DefCollector<'_> { // don't do pre-configured attribute resolution yet. // So here check if we are no_core / no_std and we are trying to add the // corresponding dep from the sysroot - let skip = match crate_graph[dep.crate_id].origin { - CrateOrigin::Lang(LangCrateOrigin::Core) => { - crate_data.no_core && dep.is_sysroot() - } - CrateOrigin::Lang(LangCrateOrigin::Std) => { - crate_data.no_std && dep.is_sysroot() - } - _ => false, - }; + + // Depending on the crate data of a dependency seems bad for incrementality, but + // we only do that for sysroot crates (this is why the order of the `&&` is important) + // - which are normally standard library crate, which realistically aren't going + // to have their crate ID invalidated, because they stay on the same root file and + // they're dependencies of everything else, so if some collision miraculously occurs + // we will resolve it by disambiguating the other crate. + let skip = dep.is_sysroot() + && match dep.crate_id.data(self.db).origin { + CrateOrigin::Lang(LangCrateOrigin::Core) => crate_data.no_core, + CrateOrigin::Lang(LangCrateOrigin::Std) => crate_data.no_std, + _ => false, + }; if skip { continue; } - crate_data + self.local_def_map .extern_prelude .insert(name.clone(), (CrateRootModuleId { krate: dep.crate_id }, None)); } @@ -494,7 +509,7 @@ impl DefCollector<'_> { let krate = if self.def_map.data.no_std { Name::new_symbol_root(sym::core.clone()) - } else if self.def_map.extern_prelude().any(|(name, _)| *name == sym::std.clone()) { + } else if self.local_def_map().extern_prelude().any(|(name, _)| *name == sym::std.clone()) { Name::new_symbol_root(sym::std.clone()) } else { // If `std` does not exist for some reason, fall back to core. This mostly helps @@ -518,8 +533,14 @@ impl DefCollector<'_> { [krate, Name::new_symbol_root(sym::prelude.clone()), edition], ); - let (per_ns, _) = - self.def_map.resolve_path(self.db, DefMap::ROOT, &path, BuiltinShadowMode::Other, None); + let (per_ns, _) = self.def_map.resolve_path( + self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map), + self.db, + DefMap::ROOT, + &path, + BuiltinShadowMode::Other, + None, + ); match per_ns.types { Some(Item { def: ModuleDefId::ModuleId(m), import, .. }) => { @@ -535,6 +556,10 @@ impl DefCollector<'_> { } } + fn local_def_map(&mut self) -> &LocalDefMap { + self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map) + } + /// Adds a definition of procedural macro `name` to the root module. /// /// # Notes on procedural macro resolution @@ -660,7 +685,13 @@ impl DefCollector<'_> { ) { let vis = self .def_map - .resolve_visibility(self.db, module_id, vis, false) + .resolve_visibility( + self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map), + self.db, + module_id, + vis, + false, + ) .unwrap_or(Visibility::Public); self.def_map.modules[module_id].scope.declare(macro_.into()); self.update( @@ -694,7 +725,7 @@ impl DefCollector<'_> { /// created by `use` in the root module, ignoring the visibility of `use`. fn import_macros_from_extern_crate( &mut self, - krate: CrateId, + krate: Crate, names: Option<Vec<Name>>, extern_crate: Option<ExternCrateId>, ) { @@ -779,6 +810,7 @@ impl DefCollector<'_> { .entered(); tracing::debug!("resolving import: {:?} ({:?})", import, self.def_map.data.edition); let res = self.def_map.resolve_path_fp_with_macro( + self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map), self.db, ResolveMode::Import, module_id, @@ -814,7 +846,13 @@ impl DefCollector<'_> { let mut def = directive.status.namespaces(); let vis = self .def_map - .resolve_visibility(self.db, module_id, &directive.import.visibility, false) + .resolve_visibility( + self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map), + self.db, + module_id, + &directive.import.visibility, + false, + ) .unwrap_or(Visibility::Public); match import.source { @@ -1210,6 +1248,7 @@ impl DefCollector<'_> { }; let resolver = |path: &_| { let resolved_res = self.def_map.resolve_path_fp_with_macro( + self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map), self.db, ResolveMode::Other, directive.module_id, @@ -1495,7 +1534,7 @@ impl DefCollector<'_> { .collect(item_tree.top_level_items(), container); } - fn finish(mut self) -> DefMap { + fn finish(mut self) -> (DefMap, LocalDefMap) { // Emit diagnostics for all remaining unexpanded macros. let _p = tracing::info_span!("DefCollector::finish").entered(); @@ -1511,6 +1550,7 @@ impl DefCollector<'_> { self.def_map.krate, |path| { let resolved_res = self.def_map.resolve_path_fp_with_macro( + self.crate_local_def_map.as_deref().unwrap_or(&self.local_def_map), self.db, ResolveMode::Other, directive.module_id, @@ -1582,7 +1622,7 @@ impl DefCollector<'_> { )); } - self.def_map + (self.def_map, self.local_def_map) } } @@ -1635,9 +1675,9 @@ impl ModCollector<'_, '_> { None, ) }; - let resolve_vis = |def_map: &DefMap, visibility| { + let resolve_vis = |def_map: &DefMap, local_def_map: &LocalDefMap, visibility| { def_map - .resolve_visibility(db, module_id, visibility, false) + .resolve_visibility(local_def_map, db, module_id, visibility, false) .unwrap_or(Visibility::Public) }; @@ -1658,6 +1698,11 @@ impl ModCollector<'_, '_> { let module = self.def_collector.def_map.module_id(module_id); let def_map = &mut self.def_collector.def_map; + let local_def_map = self + .def_collector + .crate_local_def_map + .as_deref() + .unwrap_or(&self.def_collector.local_def_map); match item { ModItem::Mod(m) => self.collect_module(m, &attrs), @@ -1711,13 +1756,13 @@ impl ModCollector<'_, '_> { }; if let Some(resolved) = resolved { - let vis = resolve_vis(def_map, &self.item_tree[*visibility]); + let vis = resolve_vis(def_map, local_def_map, &self.item_tree[*visibility]); if is_crate_root { // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 if let Some(name) = name { - Arc::get_mut(&mut def_map.data) - .unwrap() + self.def_collector + .local_def_map .extern_prelude .insert(name.clone(), (resolved, Some(id))); } @@ -1784,7 +1829,7 @@ impl ModCollector<'_, '_> { let fn_id = FunctionLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db); - let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); + let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); if self.def_collector.def_map.block.is_none() && self.def_collector.is_proc_macro @@ -1804,7 +1849,7 @@ impl ModCollector<'_, '_> { ModItem::Struct(id) => { let it = &self.item_tree[id]; - let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); + let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, StructLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } @@ -1818,7 +1863,7 @@ impl ModCollector<'_, '_> { ModItem::Union(id) => { let it = &self.item_tree[id]; - let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); + let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, UnionLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } @@ -1835,7 +1880,7 @@ impl ModCollector<'_, '_> { EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } .intern(db); - let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); + let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def(self.def_collector, enum_.into(), &it.name, vis, false); let mut index = 0; @@ -1878,7 +1923,8 @@ impl ModCollector<'_, '_> { match &it.name { Some(name) => { - let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); + let vis = + resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def(self.def_collector, const_id.into(), name, vis, false); } None => { @@ -1892,7 +1938,7 @@ impl ModCollector<'_, '_> { ModItem::Static(id) => { let it = &self.item_tree[id]; - let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); + let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, StaticLoc { container, id: ItemTreeId::new(self.tree_id, id) } @@ -1906,7 +1952,7 @@ impl ModCollector<'_, '_> { ModItem::Trait(id) => { let it = &self.item_tree[id]; - let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); + let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, TraitLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } @@ -1920,7 +1966,7 @@ impl ModCollector<'_, '_> { ModItem::TraitAlias(id) => { let it = &self.item_tree[id]; - let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); + let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, TraitAliasLoc { container: module, id: ItemTreeId::new(self.tree_id, id) } @@ -1934,7 +1980,7 @@ impl ModCollector<'_, '_> { ModItem::TypeAlias(id) => { let it = &self.item_tree[id]; - let vis = resolve_vis(def_map, &self.item_tree[it.visibility]); + let vis = resolve_vis(def_map, local_def_map, &self.item_tree[it.visibility]); update_def( self.def_collector, TypeAliasLoc { container, id: ItemTreeId::new(self.tree_id, id) } @@ -1971,7 +2017,7 @@ impl ModCollector<'_, '_> { &mut self, extern_crate_id: ExternCrateId, macro_use_attrs: impl Iterator<Item = &'a Attr>, - target_crate: CrateId, + target_crate: Crate, ) { cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use); let mut single_imports = Vec::new(); @@ -2115,7 +2161,16 @@ impl ModCollector<'_, '_> { ) -> LocalModuleId { let def_map = &mut self.def_collector.def_map; let vis = def_map - .resolve_visibility(self.def_collector.db, self.module_id, visibility, false) + .resolve_visibility( + self.def_collector + .crate_local_def_map + .as_deref() + .unwrap_or(&self.def_collector.local_def_map), + self.def_collector.db, + self.module_id, + visibility, + false, + ) .unwrap_or(Visibility::Public); let origin = match definition { None => ModuleOrigin::Inline { @@ -2417,6 +2472,10 @@ impl ModCollector<'_, '_> { }, |path| { let resolved_res = self.def_collector.def_map.resolve_path_fp_with_macro( + self.def_collector + .crate_local_def_map + .as_deref() + .unwrap_or(&self.def_collector.local_def_map), db, ResolveMode::Other, self.module_id, @@ -2517,7 +2576,6 @@ impl ModCollector<'_, '_> { #[cfg(test)] mod tests { - use base_db::RootQueryDb; use test_fixture::WithFixture; use crate::{nameres::DefMapCrateData, test_db::TestDB}; @@ -2528,6 +2586,8 @@ mod tests { let mut collector = DefCollector { db, def_map, + local_def_map: LocalDefMap::default(), + crate_local_def_map: None, deps: FxHashMap::default(), glob_imports: FxHashMap::default(), unresolved_imports: Vec::new(), @@ -2550,7 +2610,7 @@ mod tests { let (db, file_id) = TestDB::with_single_file(not_ra_fixture); let krate = db.test_crate(); - let edition = db.crate_graph()[krate].edition; + let edition = krate.data(&db).edition; let module_origin = ModuleOrigin::CrateRoot { definition: file_id }; let def_map = DefMap::empty( krate, |