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 | 157 |
1 files changed, 80 insertions, 77 deletions
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 64caf26299..06542b4b1e 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(dep_def_map.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; @@ -86,7 +80,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 +89,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.proc_macro_loading_error = Some(e.clone().into_boxed_str()); - Vec::new() - } - None => { - def_map.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 { @@ -252,7 +239,7 @@ enum MacroDirectiveKind { struct DefCollector<'a> { db: &'a dyn DefDatabase, def_map: DefMap, - deps: FxHashMap<Name, ModuleId>, + deps: FxHashMap<Name, Dependency>, glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility)>>, unresolved_imports: Vec<ImportDirective>, indeterminate_imports: Vec<ImportDirective>, @@ -263,7 +250,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<Vec<(Name, ProcMacroExpander)>, Box<str>>, 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. @@ -287,9 +274,23 @@ 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); + 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()); + } + + 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 { @@ -306,7 +307,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); + crate_data.recursion_limit = Some(limit); } } continue; @@ -320,17 +321,17 @@ impl DefCollector<'_> { } if *attr_name == hir_expand::name![no_core] { - self.def_map.no_core = true; + crate_data.no_core = true; continue; } if *attr_name == hir_expand::name![no_std] { - self.def_map.no_std = true; + crate_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; + crate_data.rustc_coherence_is_core = true; continue; } @@ -344,7 +345,7 @@ impl DefCollector<'_> { [name] => Some(name.to_smol_str()), _ => None, }); - self.def_map.unstable_features.extend(features); + crate_data.unstable_features.extend(features); } let attr_is_register_like = *attr_name == hir_expand::name![register_attr] @@ -359,14 +360,15 @@ impl DefCollector<'_> { }; if *attr_name == hir_expand::name![register_attr] { - self.def_map.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.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 { @@ -382,7 +384,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 +466,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); @@ -530,12 +532,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,25 +550,20 @@ 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, }; 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), _)) => { @@ -603,23 +600,29 @@ impl DefCollector<'_> { def: ProcMacroDef, id: ItemTreeId<item_tree::Function>, 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 + crate_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); + crate_data.fn_proc_macro_mapping.insert(fn_id, proc_macro_id); } /// Define a macro with `macro_rules`. @@ -661,7 +664,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 +715,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 +735,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. @@ -778,7 +781,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 @@ -831,16 +834,13 @@ impl DefCollector<'_> { fn resolve_extern_crate(&self, name: &Name) -> Option<ModuleId> { 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(def_map.root()) - } - None => self.def_map.module_id(self.def_map.root()), - }; - Some(root) + Some(self.def_map.crate_root()) } else { - self.deps.get(name).copied() + self.deps.get(name).map(|dep| ModuleId { + krate: dep.crate_id, + block: None, + local_id: DefMap::ROOT, + }) } } @@ -879,11 +879,14 @@ 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) { - self.def_map.extern_prelude.insert(name.clone(), def); + Arc::get_mut(&mut self.def_map.data) + .unwrap() + .extern_prelude + .insert(name.clone(), def); } } @@ -1158,7 +1161,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())) @@ -1525,7 +1528,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,14 +1644,12 @@ 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); self.def_collector.export_proc_macro( proc_macro, ItemTreeId::new(self.tree_id, id), fn_id, - crate_root, ); } } @@ -2169,10 +2170,12 @@ impl ModCollector<'_, '_> { &self.item_tree[mac.visibility], ); if let Some(helpers) = helpers_opt { - self.def_collector - .def_map - .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); + } } } @@ -2280,7 +2283,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, |