about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir-def/src/nameres.rs51
-rw-r--r--crates/hir-def/src/nameres/collector.rs77
2 files changed, 68 insertions, 60 deletions
diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs
index 86ba9052031..e900de88dd0 100644
--- a/crates/hir-def/src/nameres.rs
+++ b/crates/hir-def/src/nameres.rs
@@ -116,10 +116,10 @@ pub struct DefMap {
     diagnostics: Vec<DefDiagnostic>,
 
     // FIXME: Arc this so we can share it with block def maps
-    data: CrateData,
+    data: Arc<CrateData>,
 }
 
-#[derive(Debug, PartialEq, Eq)]
+#[derive(Clone, Debug, PartialEq, Eq)]
 struct CrateData {
     /// Side table for resolving derive helpers.
     exported_derives: FxHashMap<MacroDefId, Box<[Name]>>,
@@ -141,6 +141,28 @@ struct CrateData {
     edition: Edition,
     recursion_limit: Option<u32>,
 }
+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 53e12733412..9e35c47d4fb 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<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.
@@ -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<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
-                .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,