Skip to content

Show proc-macro loading errors in unresolved-proc-macro diagnostics #12544

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions crates/base-db/src/fixture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ impl ChangeFixture {
meta.cfg.clone(),
meta.cfg,
meta.env,
Default::default(),
Ok(Vec::new()),
false,
origin,
);
Expand Down Expand Up @@ -194,7 +194,7 @@ impl ChangeFixture {
default_cfg.clone(),
default_cfg,
Env::default(),
Default::default(),
Ok(Vec::new()),
false,
CrateOrigin::CratesIo { repo: None },
);
Expand Down Expand Up @@ -231,7 +231,7 @@ impl ChangeFixture {
CfgOptions::default(),
CfgOptions::default(),
Env::default(),
Vec::new(),
Ok(Vec::new()),
false,
CrateOrigin::Lang(LangCrateOrigin::Core),
);
Expand Down Expand Up @@ -268,7 +268,7 @@ impl ChangeFixture {
CfgOptions::default(),
CfgOptions::default(),
Env::default(),
proc_macro,
Ok(proc_macro),
true,
CrateOrigin::CratesIo { repo: None },
);
Expand Down
30 changes: 16 additions & 14 deletions crates/base-db/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,8 @@ pub enum ProcMacroExpansionError {
System(String),
}

pub type ProcMacroLoadResult = Result<Vec<ProcMacro>, String>;

#[derive(Debug, Clone)]
pub struct ProcMacro {
pub name: SmolStr,
Expand All @@ -254,7 +256,7 @@ pub struct CrateData {
pub potential_cfg_options: CfgOptions,
pub env: Env,
pub dependencies: Vec<Dependency>,
pub proc_macro: Vec<ProcMacro>,
pub proc_macro: ProcMacroLoadResult,
pub origin: CrateOrigin,
pub is_proc_macro: bool,
}
Expand Down Expand Up @@ -300,19 +302,19 @@ impl Dependency {
impl CrateGraph {
pub fn add_crate_root(
&mut self,
file_id: FileId,
root_file_id: FileId,
edition: Edition,
display_name: Option<CrateDisplayName>,
version: Option<String>,
cfg_options: CfgOptions,
potential_cfg_options: CfgOptions,
env: Env,
proc_macro: Vec<ProcMacro>,
proc_macro: ProcMacroLoadResult,
is_proc_macro: bool,
origin: CrateOrigin,
) -> CrateId {
let data = CrateData {
root_file_id: file_id,
root_file_id,
edition,
version,
display_name,
Expand Down Expand Up @@ -628,7 +630,7 @@ mod tests {
CfgOptions::default(),
CfgOptions::default(),
Env::default(),
Default::default(),
Ok(Vec::new()),
false,
CrateOrigin::CratesIo { repo: None },
);
Expand All @@ -640,7 +642,7 @@ mod tests {
CfgOptions::default(),
CfgOptions::default(),
Env::default(),
Default::default(),
Ok(Vec::new()),
false,
CrateOrigin::CratesIo { repo: None },
);
Expand All @@ -652,7 +654,7 @@ mod tests {
CfgOptions::default(),
CfgOptions::default(),
Env::default(),
Default::default(),
Ok(Vec::new()),
false,
CrateOrigin::CratesIo { repo: None },
);
Expand All @@ -678,7 +680,7 @@ mod tests {
CfgOptions::default(),
CfgOptions::default(),
Env::default(),
Default::default(),
Ok(Vec::new()),
false,
CrateOrigin::CratesIo { repo: None },
);
Expand All @@ -690,7 +692,7 @@ mod tests {
CfgOptions::default(),
CfgOptions::default(),
Env::default(),
Default::default(),
Ok(Vec::new()),
false,
CrateOrigin::CratesIo { repo: None },
);
Expand All @@ -713,7 +715,7 @@ mod tests {
CfgOptions::default(),
CfgOptions::default(),
Env::default(),
Default::default(),
Ok(Vec::new()),
false,
CrateOrigin::CratesIo { repo: None },
);
Expand All @@ -725,7 +727,7 @@ mod tests {
CfgOptions::default(),
CfgOptions::default(),
Env::default(),
Default::default(),
Ok(Vec::new()),
false,
CrateOrigin::CratesIo { repo: None },
);
Expand All @@ -737,7 +739,7 @@ mod tests {
CfgOptions::default(),
CfgOptions::default(),
Env::default(),
Default::default(),
Ok(Vec::new()),
false,
CrateOrigin::CratesIo { repo: None },
);
Expand All @@ -760,7 +762,7 @@ mod tests {
CfgOptions::default(),
CfgOptions::default(),
Env::default(),
Default::default(),
Ok(Vec::new()),
false,
CrateOrigin::CratesIo { repo: None },
);
Expand All @@ -772,7 +774,7 @@ mod tests {
CfgOptions::default(),
CfgOptions::default(),
Env::default(),
Default::default(),
Ok(Vec::new()),
false,
CrateOrigin::CratesIo { repo: None },
);
Expand Down
2 changes: 1 addition & 1 deletion crates/base-db/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub use crate::{
input::{
CrateData, CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency,
Edition, Env, LangCrateOrigin, ProcMacro, ProcMacroExpander, ProcMacroExpansionError,
ProcMacroId, ProcMacroKind, SourceRoot, SourceRootId,
ProcMacroId, ProcMacroKind, ProcMacroLoadResult, SourceRoot, SourceRootId,
},
};
pub use salsa::{self, Cancelled};
Expand Down
7 changes: 7 additions & 0 deletions crates/hir-def/src/nameres.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ pub struct DefMap {
/// Side table for resolving derive helpers.
exported_derives: FxHashMap<MacroDefId, Box<[Name]>>,
fn_proc_macro_mapping: FxHashMap<FunctionId, ProcMacroId>,
/// The error that occurred when failing to load the proc-macro dll.
proc_macro_loading_error: Option<Box<str>>,

/// Custom attributes registered with `#![register_attr]`.
registered_attrs: Vec<SmolStr>,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -305,6 +308,9 @@ impl DefMap {
pub fn fn_as_proc_macro(&self, id: FunctionId) -> Option<ProcMacroId> {
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
Expand Down Expand Up @@ -460,6 +466,7 @@ impl DefMap {
registered_attrs,
registered_tools,
fn_proc_macro_mapping,
proc_macro_loading_error: _,
block: _,
edition: _,
recursion_limit: _,
Expand Down
54 changes: 39 additions & 15 deletions crates/hir-def/src/nameres/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,19 +74,26 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: DefMap, tree_id: T
}

let cfg_options = &krate.cfg_options;
let proc_macros = krate
.proc_macro
.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();
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()
}
Err(e) => {
def_map.proc_macro_loading_error = Some(e.clone().into_boxed_str());
Vec::new()
}
};
let is_proc_macro = krate.is_proc_macro;

let mut collector = DefCollector {
Expand Down Expand Up @@ -1128,7 +1135,19 @@ impl DefCollector<'_> {

let def = match resolver(path.clone()) {
Some(def) if def.is_attribute() => def,
_ => return true,
_ => {
self.def_map.diagnostics.push(DefDiagnostic::unresolved_proc_macro(
directive.module_id,
MacroCallKind::Attr {
ast_id,
attr_args: Default::default(),
invoc_attr_index: attr.id.ast_index,
is_derive: false,
},
None,
));
return true;
}
};
if matches!(
def,
Expand Down Expand Up @@ -1232,6 +1251,7 @@ impl DefCollector<'_> {
self.def_map.diagnostics.push(DefDiagnostic::unresolved_proc_macro(
directive.module_id,
loc.kind,
Some(loc.def.krate),
));

return recollect_without(self);
Expand Down Expand Up @@ -1283,7 +1303,11 @@ impl DefCollector<'_> {
let diag = match err {
hir_expand::ExpandError::UnresolvedProcMacro => {
// Missing proc macros are non-fatal, so they are handled specially.
DefDiagnostic::unresolved_proc_macro(module_id, loc.kind.clone())
DefDiagnostic::unresolved_proc_macro(
module_id,
loc.kind.clone(),
Some(loc.def.krate),
)
}
_ => DefDiagnostic::macro_error(module_id, loc.kind.clone(), err.to_string()),
};
Expand Down
11 changes: 8 additions & 3 deletions crates/hir-def/src/nameres/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -23,7 +24,7 @@ pub enum DefDiagnosticKind {

UnconfiguredCode { ast: AstId<ast::Item>, cfg: CfgExpr, opts: CfgOptions },

UnresolvedProcMacro { ast: MacroCallKind },
UnresolvedProcMacro { ast: MacroCallKind, krate: Option<CrateId> },

UnresolvedMacroCall { ast: MacroCallKind, path: ModPath },

Expand Down Expand Up @@ -81,8 +82,12 @@ impl DefDiagnostic {
Self { in_module: container, kind: DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } }
}

pub(super) fn unresolved_proc_macro(container: LocalModuleId, ast: MacroCallKind) -> Self {
Self { in_module: container, kind: DefDiagnosticKind::UnresolvedProcMacro { ast } }
pub(super) fn unresolved_proc_macro(
container: LocalModuleId,
ast: MacroCallKind,
krate: Option<CrateId>,
) -> Self {
Self { in_module: container, kind: DefDiagnosticKind::UnresolvedProcMacro { ast, krate } }
}

pub(super) fn macro_error(
Expand Down
10 changes: 9 additions & 1 deletion crates/hir-expand/src/proc_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,15 @@ impl ProcMacroExpander {
match self.proc_macro_id {
Some(id) => {
let krate_graph = db.crate_graph();
let proc_macro = match krate_graph[self.krate].proc_macro.get(id.0 as usize) {
let proc_macros = match &krate_graph[self.krate].proc_macro {
Ok(proc_macros) => proc_macros,
Err(e) => {
return ExpandResult::only_err(ExpandError::Other(
e.clone().into_boxed_str(),
))
}
};
let proc_macro = match proc_macros.get(id.0 as usize) {
Some(proc_macro) => proc_macro,
None => {
return ExpandResult::only_err(ExpandError::Other(
Expand Down
3 changes: 3 additions & 0 deletions crates/hir/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -87,6 +88,8 @@ pub struct UnresolvedProcMacro {
pub precise_location: Option<TextRange>,
pub macro_name: Option<String>,
pub kind: MacroKind,
/// The crate id of the proc-macro this macro belongs to, or `None` if the proc-macro can't be found.
pub krate: Option<CrateId>,
}

#[derive(Debug, Clone, Eq, PartialEq)]
Expand Down
8 changes: 6 additions & 2 deletions crates/hir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@ fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag:
);
}

DefDiagnosticKind::UnresolvedProcMacro { ast } => {
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());
Expand Down Expand Up @@ -689,7 +689,10 @@ fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag:
)
}
};
acc.push(UnresolvedProcMacro { node, precise_location, macro_name, kind }.into());
acc.push(
UnresolvedProcMacro { node, precise_location, macro_name, kind, krate: *krate }
.into(),
);
}

DefDiagnosticKind::UnresolvedMacroCall { ast, path } => {
Expand Down Expand Up @@ -1163,6 +1166,7 @@ impl DefWithBody {
precise_location: None,
macro_name: None,
kind: MacroKind::ProcMacro,
krate: None,
}
.into(),
),
Expand Down
Loading