fix: Report proc macro errors in expressions correctly as well

They didn't have a krate before, resulting in the generic "proc macro
not found" error.

Also improve error messages a bit more.
This commit is contained in:
Florian Diebold 2022-06-28 10:41:10 +02:00
parent 9eaf96c9ea
commit 8b3ec12aac
12 changed files with 69 additions and 69 deletions

View file

@ -312,7 +312,7 @@ pub struct SyntheticSyntax;
pub enum BodyDiagnostic { pub enum BodyDiagnostic {
InactiveCode { node: InFile<SyntaxNodePtr>, cfg: CfgExpr, opts: CfgOptions }, InactiveCode { node: InFile<SyntaxNodePtr>, cfg: CfgExpr, opts: CfgOptions },
MacroError { node: InFile<AstPtr<ast::MacroCall>>, message: String }, MacroError { node: InFile<AstPtr<ast::MacroCall>>, message: String },
UnresolvedProcMacro { node: InFile<AstPtr<ast::MacroCall>> }, UnresolvedProcMacro { node: InFile<AstPtr<ast::MacroCall>>, krate: CrateId },
UnresolvedMacroCall { node: InFile<AstPtr<ast::MacroCall>>, path: ModPath }, UnresolvedMacroCall { node: InFile<AstPtr<ast::MacroCall>>, path: ModPath },
} }

View file

@ -572,9 +572,10 @@ impl ExprCollector<'_> {
if record_diagnostics { if record_diagnostics {
match &res.err { match &res.err {
Some(ExpandError::UnresolvedProcMacro) => { Some(ExpandError::UnresolvedProcMacro(krate)) => {
self.source_map.diagnostics.push(BodyDiagnostic::UnresolvedProcMacro { self.source_map.diagnostics.push(BodyDiagnostic::UnresolvedProcMacro {
node: InFile::new(outer_file, syntax_ptr), node: InFile::new(outer_file, syntax_ptr),
krate: *krate,
}); });
} }
Some(err) => { Some(err) => {

View file

@ -22,6 +22,7 @@ use itertools::Itertools;
use la_arena::Idx; use la_arena::Idx;
use limit::Limit; use limit::Limit;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use stdx::always;
use syntax::{ast, SmolStr}; use syntax::{ast, SmolStr};
use crate::{ use crate::{
@ -1234,7 +1235,7 @@ impl DefCollector<'_> {
self.def_map.diagnostics.push(DefDiagnostic::unresolved_proc_macro( self.def_map.diagnostics.push(DefDiagnostic::unresolved_proc_macro(
directive.module_id, directive.module_id,
loc.kind, loc.kind,
Some(loc.def.krate), loc.def.krate,
)); ));
return recollect_without(self); return recollect_without(self);
} }
@ -1258,7 +1259,7 @@ impl DefCollector<'_> {
self.def_map.diagnostics.push(DefDiagnostic::unresolved_proc_macro( self.def_map.diagnostics.push(DefDiagnostic::unresolved_proc_macro(
directive.module_id, directive.module_id,
loc.kind, loc.kind,
Some(loc.def.krate), loc.def.krate,
)); ));
return recollect_without(self); return recollect_without(self);
@ -1308,13 +1309,10 @@ impl DefCollector<'_> {
let err = self.db.macro_expand_error(macro_call_id); let err = self.db.macro_expand_error(macro_call_id);
if let Some(err) = err { if let Some(err) = err {
let diag = match err { let diag = match err {
hir_expand::ExpandError::UnresolvedProcMacro => { hir_expand::ExpandError::UnresolvedProcMacro(krate) => {
always!(krate == loc.def.krate);
// Missing proc macros are non-fatal, so they are handled specially. // Missing proc macros are non-fatal, so they are handled specially.
DefDiagnostic::unresolved_proc_macro( DefDiagnostic::unresolved_proc_macro(module_id, loc.kind.clone(), loc.def.krate)
module_id,
loc.kind.clone(),
Some(loc.def.krate),
)
} }
_ => DefDiagnostic::macro_error(module_id, loc.kind.clone(), err.to_string()), _ => DefDiagnostic::macro_error(module_id, loc.kind.clone(), err.to_string()),
}; };

View file

@ -24,7 +24,7 @@ pub enum DefDiagnosticKind {
UnconfiguredCode { ast: AstId<ast::Item>, cfg: CfgExpr, opts: CfgOptions }, UnconfiguredCode { ast: AstId<ast::Item>, cfg: CfgExpr, opts: CfgOptions },
UnresolvedProcMacro { ast: MacroCallKind, krate: Option<CrateId> }, UnresolvedProcMacro { ast: MacroCallKind, krate: CrateId },
UnresolvedMacroCall { ast: MacroCallKind, path: ModPath }, UnresolvedMacroCall { ast: MacroCallKind, path: ModPath },
@ -85,7 +85,7 @@ impl DefDiagnostic {
pub(super) fn unresolved_proc_macro( pub(super) fn unresolved_proc_macro(
container: LocalModuleId, container: LocalModuleId,
ast: MacroCallKind, ast: MacroCallKind,
krate: Option<CrateId>, krate: CrateId,
) -> Self { ) -> Self {
Self { in_module: container, kind: DefDiagnosticKind::UnresolvedProcMacro { ast, krate } } Self { in_module: container, kind: DefDiagnosticKind::UnresolvedProcMacro { ast, krate } }
} }

View file

@ -43,7 +43,7 @@ pub type ExpandResult<T> = ValueResult<T, ExpandError>;
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
pub enum ExpandError { pub enum ExpandError {
UnresolvedProcMacro, UnresolvedProcMacro(CrateId),
Mbe(mbe::ExpandError), Mbe(mbe::ExpandError),
Other(Box<str>), Other(Box<str>),
} }
@ -57,7 +57,7 @@ impl From<mbe::ExpandError> for ExpandError {
impl fmt::Display for ExpandError { impl fmt::Display for ExpandError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
ExpandError::UnresolvedProcMacro => f.write_str("unresolved proc-macro"), ExpandError::UnresolvedProcMacro(_) => f.write_str("unresolved proc-macro"),
ExpandError::Mbe(it) => it.fmt(f), ExpandError::Mbe(it) => it.fmt(f),
ExpandError::Other(it) => f.write_str(it), ExpandError::Other(it) => f.write_str(it),
} }

View file

@ -75,7 +75,7 @@ impl ProcMacroExpander {
}, },
} }
} }
None => ExpandResult::only_err(ExpandError::UnresolvedProcMacro), None => ExpandResult::only_err(ExpandError::UnresolvedProcMacro(self.krate)),
} }
} }
} }

View file

@ -90,7 +90,7 @@ pub struct UnresolvedProcMacro {
pub macro_name: Option<String>, pub macro_name: Option<String>,
pub kind: MacroKind, pub kind: MacroKind,
/// The crate id of the proc-macro this macro belongs to, or `None` if the proc-macro can't be found. /// 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>, pub krate: CrateId,
} }
#[derive(Debug, Clone, Eq, PartialEq)] #[derive(Debug, Clone, Eq, PartialEq)]

View file

@ -1159,13 +1159,13 @@ impl DefWithBody {
} }
.into(), .into(),
), ),
BodyDiagnostic::UnresolvedProcMacro { node } => acc.push( BodyDiagnostic::UnresolvedProcMacro { node, krate } => acc.push(
UnresolvedProcMacro { UnresolvedProcMacro {
node: node.clone().map(|it| it.into()), node: node.clone().map(|it| it.into()),
precise_location: None, precise_location: None,
macro_name: None, macro_name: None,
kind: MacroKind::ProcMacro, kind: MacroKind::ProcMacro,
krate: None, krate: *krate,
} }
.into(), .into(),
), ),

View file

@ -32,13 +32,13 @@ pub(crate) fn unresolved_proc_macro(
None => "proc macro not expanded".to_string(), None => "proc macro not expanded".to_string(),
}; };
let severity = if config_enabled { Severity::Error } else { Severity::WeakWarning }; 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 def_map = ctx.sema.db.crate_def_map(d.krate);
let message = format!( let message = format!(
"{message}: {}", "{message}: {}",
if config_enabled { if config_enabled {
match def_map.as_ref().and_then(|def_map| def_map.proc_macro_loading_error()) { match def_map.proc_macro_loading_error() {
Some(e) => e, Some(e) => e,
None => "proc macro not found", None => "proc macro not found in the built dylib",
} }
} else { } else {
match d.kind { match d.kind {

View file

@ -173,7 +173,7 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
}, },
], ],
proc_macro: Err( proc_macro: Err(
"no build data", "crate has not (yet) been built",
), ),
origin: CratesIo { origin: CratesIo {
repo: None, repo: None,
@ -248,7 +248,7 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
}, },
], ],
proc_macro: Err( proc_macro: Err(
"no build data", "crate has not (yet) been built",
), ),
origin: CratesIo { origin: CratesIo {
repo: None, repo: None,
@ -313,7 +313,7 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
}, },
dependencies: [], dependencies: [],
proc_macro: Err( proc_macro: Err(
"no build data", "crate has not (yet) been built",
), ),
origin: CratesIo { origin: CratesIo {
repo: Some( repo: Some(
@ -390,7 +390,7 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
}, },
], ],
proc_macro: Err( proc_macro: Err(
"no build data", "crate has not (yet) been built",
), ),
origin: CratesIo { origin: CratesIo {
repo: None, repo: None,
@ -465,7 +465,7 @@ fn cargo_hello_world_project_model_with_wildcard_overrides() {
}, },
], ],
proc_macro: Err( proc_macro: Err(
"no build data", "crate has not (yet) been built",
), ),
origin: CratesIo { origin: CratesIo {
repo: None, repo: None,
@ -555,7 +555,7 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
}, },
], ],
proc_macro: Err( proc_macro: Err(
"no build data", "crate has not (yet) been built",
), ),
origin: CratesIo { origin: CratesIo {
repo: None, repo: None,
@ -632,7 +632,7 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
}, },
], ],
proc_macro: Err( proc_macro: Err(
"no build data", "crate has not (yet) been built",
), ),
origin: CratesIo { origin: CratesIo {
repo: None, repo: None,
@ -697,7 +697,7 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
}, },
dependencies: [], dependencies: [],
proc_macro: Err( proc_macro: Err(
"no build data", "crate has not (yet) been built",
), ),
origin: CratesIo { origin: CratesIo {
repo: Some( repo: Some(
@ -776,7 +776,7 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
}, },
], ],
proc_macro: Err( proc_macro: Err(
"no build data", "crate has not (yet) been built",
), ),
origin: CratesIo { origin: CratesIo {
repo: None, repo: None,
@ -853,7 +853,7 @@ fn cargo_hello_world_project_model_with_selective_overrides() {
}, },
], ],
proc_macro: Err( proc_macro: Err(
"no build data", "crate has not (yet) been built",
), ),
origin: CratesIo { origin: CratesIo {
repo: None, repo: None,
@ -934,7 +934,7 @@ fn cargo_hello_world_project_model() {
}, },
], ],
proc_macro: Err( proc_macro: Err(
"no build data", "crate has not (yet) been built",
), ),
origin: CratesIo { origin: CratesIo {
repo: None, repo: None,
@ -1011,7 +1011,7 @@ fn cargo_hello_world_project_model() {
}, },
], ],
proc_macro: Err( proc_macro: Err(
"no build data", "crate has not (yet) been built",
), ),
origin: CratesIo { origin: CratesIo {
repo: None, repo: None,
@ -1076,7 +1076,7 @@ fn cargo_hello_world_project_model() {
}, },
dependencies: [], dependencies: [],
proc_macro: Err( proc_macro: Err(
"no build data", "crate has not (yet) been built",
), ),
origin: CratesIo { origin: CratesIo {
repo: Some( repo: Some(
@ -1155,7 +1155,7 @@ fn cargo_hello_world_project_model() {
}, },
], ],
proc_macro: Err( proc_macro: Err(
"no build data", "crate has not (yet) been built",
), ),
origin: CratesIo { origin: CratesIo {
repo: None, repo: None,
@ -1232,7 +1232,7 @@ fn cargo_hello_world_project_model() {
}, },
], ],
proc_macro: Err( proc_macro: Err(
"no build data", "crate has not (yet) been built",
), ),
origin: CratesIo { origin: CratesIo {
repo: None, repo: None,
@ -1288,8 +1288,8 @@ fn rust_project_hello_world_project_model() {
prelude: true, prelude: true,
}, },
], ],
proc_macro: Ok( proc_macro: Err(
[], "no proc macro loaded for sysroot crate",
), ),
origin: Lang( origin: Lang(
Alloc, Alloc,
@ -1322,8 +1322,8 @@ fn rust_project_hello_world_project_model() {
entries: {}, entries: {},
}, },
dependencies: [], dependencies: [],
proc_macro: Ok( proc_macro: Err(
[], "no proc macro loaded for sysroot crate",
), ),
origin: Lang( origin: Lang(
Other, Other,
@ -1356,8 +1356,8 @@ fn rust_project_hello_world_project_model() {
entries: {}, entries: {},
}, },
dependencies: [], dependencies: [],
proc_macro: Ok( proc_macro: Err(
[], "no proc macro loaded for sysroot crate",
), ),
origin: Lang( origin: Lang(
Other, Other,
@ -1400,8 +1400,8 @@ fn rust_project_hello_world_project_model() {
prelude: true, prelude: true,
}, },
], ],
proc_macro: Ok( proc_macro: Err(
[], "no proc macro loaded for sysroot crate",
), ),
origin: Lang( origin: Lang(
Other, Other,
@ -1434,8 +1434,8 @@ fn rust_project_hello_world_project_model() {
entries: {}, entries: {},
}, },
dependencies: [], dependencies: [],
proc_macro: Ok( proc_macro: Err(
[], "no proc macro loaded for sysroot crate",
), ),
origin: Lang( origin: Lang(
Core, Core,
@ -1539,8 +1539,8 @@ fn rust_project_hello_world_project_model() {
entries: {}, entries: {},
}, },
dependencies: [], dependencies: [],
proc_macro: Ok( proc_macro: Err(
[], "no proc macro loaded for sysroot crate",
), ),
origin: Lang( origin: Lang(
Other, Other,
@ -1573,8 +1573,8 @@ fn rust_project_hello_world_project_model() {
entries: {}, entries: {},
}, },
dependencies: [], dependencies: [],
proc_macro: Ok( proc_macro: Err(
[], "no proc macro loaded for sysroot crate",
), ),
origin: Lang( origin: Lang(
Other, Other,
@ -1607,8 +1607,8 @@ fn rust_project_hello_world_project_model() {
entries: {}, entries: {},
}, },
dependencies: [], dependencies: [],
proc_macro: Ok( proc_macro: Err(
[], "no proc macro loaded for sysroot crate",
), ),
origin: Lang( origin: Lang(
Other, Other,
@ -1641,8 +1641,8 @@ fn rust_project_hello_world_project_model() {
entries: {}, entries: {},
}, },
dependencies: [], dependencies: [],
proc_macro: Ok( proc_macro: Err(
[], "no proc macro loaded for sysroot crate",
), ),
origin: Lang( origin: Lang(
Test, Test,
@ -1757,8 +1757,8 @@ fn rust_project_hello_world_project_model() {
prelude: true, prelude: true,
}, },
], ],
proc_macro: Ok( proc_macro: Err(
[], "no proc macro loaded for sysroot crate",
), ),
origin: Lang( origin: Lang(
Std, Std,
@ -1791,8 +1791,8 @@ fn rust_project_hello_world_project_model() {
entries: {}, entries: {},
}, },
dependencies: [], dependencies: [],
proc_macro: Ok( proc_macro: Err(
[], "no proc macro loaded for sysroot crate",
), ),
origin: Lang( origin: Lang(
Other, Other,

View file

@ -873,7 +873,7 @@ fn add_target_crate_root(
let proc_macro = match build_data.as_ref().map(|it| it.proc_macro_dylib_path.as_ref()) { let proc_macro = match build_data.as_ref().map(|it| it.proc_macro_dylib_path.as_ref()) {
Some(Some(it)) => load_proc_macro(it), Some(Some(it)) => load_proc_macro(it),
Some(None) => Err("no proc macro dylib present".into()), Some(None) => Err("no proc macro dylib present".into()),
None => Err("no build data".into()), None => Err("crate has not (yet) been built".into()),
}; };
let display_name = CrateDisplayName::from_canonical_name(cargo_name.to_string()); let display_name = CrateDisplayName::from_canonical_name(cargo_name.to_string());
@ -929,7 +929,7 @@ fn sysroot_to_crate_graph(
cfg_options.clone(), cfg_options.clone(),
cfg_options.clone(), cfg_options.clone(),
env, env,
Ok(Vec::new()), Err("no proc macro loaded for sysroot crate".into()),
false, false,
CrateOrigin::Lang(LangCrateOrigin::from(&*sysroot[krate].name)), CrateOrigin::Lang(LangCrateOrigin::from(&*sysroot[krate].name)),
); );

View file

@ -540,17 +540,18 @@ pub(crate) fn load_proc_macro(
path: &AbsPath, path: &AbsPath,
dummy_replace: &[Box<str>], dummy_replace: &[Box<str>],
) -> ProcMacroLoadResult { ) -> ProcMacroLoadResult {
let res: Result<_, String> = (|| { let res: Result<Vec<_>, String> = (|| {
let dylib = MacroDylib::new(path.to_path_buf()) let dylib = MacroDylib::new(path.to_path_buf())
.map_err(|io| format!("Proc-macro dylib loading failed: {io}"))?; .map_err(|io| format!("Proc-macro dylib loading failed: {io}"))?;
Ok(if let Some(it) = server { let server = server.ok_or_else(|| format!("Proc-macro server not started"))?;
let vec = it.load_dylib(dylib).map_err(|e| format!("{e}"))?; let vec = server.load_dylib(dylib).map_err(|e| format!("{e}"))?;
vec.into_iter() if vec.is_empty() {
return Err("proc macro library returned no proc macros".to_string());
}
Ok(vec
.into_iter()
.map(|expander| expander_to_proc_macro(expander, dummy_replace)) .map(|expander| expander_to_proc_macro(expander, dummy_replace))
.collect() .collect())
} else {
Vec::new()
})
})(); })();
return match res { return match res {
Ok(proc_macros) => { Ok(proc_macros) => {