diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs index e923d883ec..536eecf020 100644 --- a/crates/hir-def/src/nameres.rs +++ b/crates/hir-def/src/nameres.rs @@ -103,6 +103,8 @@ pub struct DefMap { /// 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>, /// Custom attributes registered with `#![register_attr]`. registered_attrs: Vec, @@ -273,6 +275,7 @@ impl DefMap { extern_prelude: FxHashMap::default(), exported_derives: FxHashMap::default(), fn_proc_macro_mapping: FxHashMap::default(), + proc_macro_loading_error: None, prelude: None, root, modules, @@ -305,6 +308,9 @@ impl DefMap { pub fn fn_as_proc_macro(&self, id: FunctionId) -> Option { self.fn_proc_macro_mapping.get(&id).copied() } + pub fn proc_macro_loading_error(&self) -> Option<&str> { + self.proc_macro_loading_error.as_deref() + } pub(crate) fn krate(&self) -> CrateId { self.krate @@ -460,6 +466,7 @@ impl DefMap { registered_attrs, registered_tools, fn_proc_macro_mapping, + proc_macro_loading_error: _, block: _, edition: _, recursion_limit: _, diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index 46f752f00a..6a9f569ea8 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -74,26 +74,25 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: DefMap, tree_id: T } let cfg_options = &krate.cfg_options; - let (proc_macros, proc_macro_err) = match &krate.proc_macro { + let proc_macros = match &krate.proc_macro { Ok(proc_macros) => { - ( - proc_macros - .iter() - .enumerate() - .map(|(idx, it)| { - // FIXME: a hacky way to create a Name from string. - let name = - tt::Ident { text: it.name.clone(), id: tt::TokenId::unspecified() }; - ( - name.as_name(), - ProcMacroExpander::new(def_map.krate, base_db::ProcMacroId(idx as u32)), - ) - }) - .collect(), - None, - ) + proc_macros + .iter() + .enumerate() + .map(|(idx, it)| { + // FIXME: a hacky way to create a Name from string. + let name = tt::Ident { text: it.name.clone(), id: tt::TokenId::unspecified() }; + ( + name.as_name(), + ProcMacroExpander::new(def_map.krate, base_db::ProcMacroId(idx as u32)), + ) + }) + .collect() + } + Err(e) => { + def_map.proc_macro_loading_error = Some(e.clone().into_boxed_str()); + Vec::new() } - Err(e) => (Vec::new(), Some(e.clone())), }; let is_proc_macro = krate.is_proc_macro; @@ -108,7 +107,6 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: DefMap, tree_id: T mod_dirs: FxHashMap::default(), cfg_options, proc_macros, - proc_macro_err, from_glob_import: Default::default(), skip_attrs: Default::default(), derive_helpers_in_scope: Default::default(), @@ -250,7 +248,6 @@ struct DefCollector<'a> { /// empty when proc. macro support is disabled (in which case we still do name resolution for /// them). proc_macros: Vec<(Name, ProcMacroExpander)>, - proc_macro_err: Option, 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. @@ -1147,7 +1144,7 @@ impl DefCollector<'_> { invoc_attr_index: attr.id.ast_index, is_derive: false, }, - self.proc_macro_err.clone(), + None, )); return true; } @@ -1254,7 +1251,7 @@ impl DefCollector<'_> { self.def_map.diagnostics.push(DefDiagnostic::unresolved_proc_macro( directive.module_id, loc.kind, - self.proc_macro_err.clone(), + Some(loc.def.krate), )); return recollect_without(self); @@ -1309,7 +1306,7 @@ impl DefCollector<'_> { DefDiagnostic::unresolved_proc_macro( module_id, loc.kind.clone(), - self.proc_macro_err.clone(), + Some(loc.def.krate), ) } _ => DefDiagnostic::macro_error(module_id, loc.kind.clone(), err.to_string()), @@ -2124,7 +2121,6 @@ mod tests { mod_dirs: FxHashMap::default(), cfg_options: &CfgOptions::default(), proc_macros: Default::default(), - proc_macro_err: None, from_glob_import: Default::default(), skip_attrs: Default::default(), derive_helpers_in_scope: Default::default(), diff --git a/crates/hir-def/src/nameres/diagnostics.rs b/crates/hir-def/src/nameres/diagnostics.rs index 927237962d..3ebc5629d7 100644 --- a/crates/hir-def/src/nameres/diagnostics.rs +++ b/crates/hir-def/src/nameres/diagnostics.rs @@ -1,5 +1,6 @@ //! Diagnostics emitted during DefMap construction. +use base_db::CrateId; use cfg::{CfgExpr, CfgOptions}; use hir_expand::MacroCallKind; use la_arena::Idx; @@ -23,7 +24,7 @@ pub enum DefDiagnosticKind { UnconfiguredCode { ast: AstId, cfg: CfgExpr, opts: CfgOptions }, - UnresolvedProcMacro { ast: MacroCallKind, proc_macro_err: Option }, + UnresolvedProcMacro { ast: MacroCallKind, krate: Option }, UnresolvedMacroCall { ast: MacroCallKind, path: ModPath }, @@ -84,12 +85,9 @@ impl DefDiagnostic { pub(super) fn unresolved_proc_macro( container: LocalModuleId, ast: MacroCallKind, - proc_macro_err: Option, + krate: Option, ) -> Self { - Self { - in_module: container, - kind: DefDiagnosticKind::UnresolvedProcMacro { ast, proc_macro_err }, - } + Self { in_module: container, kind: DefDiagnosticKind::UnresolvedProcMacro { ast, krate } } } pub(super) fn macro_error( diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs index 4dd23dfa14..1f65c05c1e 100644 --- a/crates/hir/src/diagnostics.rs +++ b/crates/hir/src/diagnostics.rs @@ -3,6 +3,7 @@ //! //! This probably isn't the best way to do this -- ideally, diagnistics should //! be expressed in terms of hir types themselves. +use base_db::CrateId; use cfg::{CfgExpr, CfgOptions}; use either::Either; use hir_def::path::ModPath; @@ -87,7 +88,8 @@ pub struct UnresolvedProcMacro { pub precise_location: Option, pub macro_name: Option, pub kind: MacroKind, - pub proc_macro_err: Option, + /// The crate id of the proc-macro this macro belongs to, or `None` if the proc-macro can't be found. + pub krate: Option, } #[derive(Debug, Clone, Eq, PartialEq)] diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 9f7a2d63fe..3f0d586bf6 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -627,7 +627,7 @@ fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec, diag: ); } - DefDiagnosticKind::UnresolvedProcMacro { ast, proc_macro_err } => { + DefDiagnosticKind::UnresolvedProcMacro { ast, krate } => { let (node, precise_location, macro_name, kind) = match ast { MacroCallKind::FnLike { ast_id, .. } => { let node = ast_id.to_node(db.upcast()); @@ -690,14 +690,8 @@ fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec, diag: } }; acc.push( - UnresolvedProcMacro { - node, - precise_location, - macro_name, - kind, - proc_macro_err: proc_macro_err.clone(), - } - .into(), + UnresolvedProcMacro { node, precise_location, macro_name, kind, krate: *krate } + .into(), ); } @@ -1172,7 +1166,7 @@ impl DefWithBody { precise_location: None, macro_name: None, kind: MacroKind::ProcMacro, - proc_macro_err: None, + krate: None, } .into(), ), diff --git a/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs b/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs index 5f905de4f1..5ebfe33dab 100644 --- a/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs +++ b/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs @@ -1,3 +1,5 @@ +use hir::db::DefDatabase; + use crate::{Diagnostic, DiagnosticsContext, Severity}; // Diagnostic: unresolved-proc-macro @@ -30,10 +32,11 @@ pub(crate) fn unresolved_proc_macro( None => "proc macro not expanded".to_string(), }; let severity = if config_enabled { Severity::Error } else { Severity::WeakWarning }; + let def_map = d.krate.map(|krate| ctx.sema.db.crate_def_map(krate)); let message = format!( "{message}: {}", if config_enabled { - match &d.proc_macro_err { + match def_map.as_ref().and_then(|def_map| def_map.proc_macro_loading_error()) { Some(e) => e, None => "proc macro not found", }