From a6342436343e01b32d4482a48994b8c22bcbe659 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 2 Dec 2020 16:52:14 +0100 Subject: Propagate eager expansion errors --- crates/hir_def/src/body.rs | 20 +++++++++++------- crates/hir_def/src/lib.rs | 51 +++++++++++++++++++++++++++++++++++++--------- 2 files changed, 54 insertions(+), 17 deletions(-) (limited to 'crates/hir_def/src') diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs index 33eb5e78c..92bcc1705 100644 --- a/crates/hir_def/src/body.rs +++ b/crates/hir_def/src/body.rs @@ -120,18 +120,24 @@ impl Expander { self.resolve_path_as_macro(db, &path) }; - let call_id = match macro_call.as_call_id(db, self.crate_def_map.krate, resolver) { + let mut err = None; + let call_id = + macro_call.as_call_id_with_errors(db, self.crate_def_map.krate, resolver, &mut |e| { + err.get_or_insert(e); + }); + let call_id = match call_id { Some(it) => it, None => { - // FIXME: this can mean other things too, but `as_call_id` doesn't provide enough - // info. - return ExpandResult::only_err(mbe::ExpandError::Other( - "failed to parse or resolve macro invocation".into(), - )); + if err.is_none() { + eprintln!("no error despite `as_call_id_with_errors` returning `None`"); + } + return ExpandResult { value: None, err }; } }; - let err = db.macro_expand_error(call_id); + if err.is_none() { + err = db.macro_expand_error(call_id); + } let file_id = call_id.as_file(); diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index 1b22d1eec..ce2be8e2b 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs @@ -465,21 +465,37 @@ pub trait AsMacroCall { db: &dyn db::DefDatabase, krate: CrateId, resolver: impl Fn(path::ModPath) -> Option, + ) -> Option { + self.as_call_id_with_errors(db, krate, resolver, &mut |_| ()) + } + + fn as_call_id_with_errors( + &self, + db: &dyn db::DefDatabase, + krate: CrateId, + resolver: impl Fn(path::ModPath) -> Option, + error_sink: &mut dyn FnMut(mbe::ExpandError), ) -> Option; } impl AsMacroCall for InFile<&ast::MacroCall> { - fn as_call_id( + fn as_call_id_with_errors( &self, db: &dyn db::DefDatabase, krate: CrateId, resolver: impl Fn(path::ModPath) -> Option, + error_sink: &mut dyn FnMut(mbe::ExpandError), ) -> Option { let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value)); let h = Hygiene::new(db.upcast(), self.file_id); - let path = path::ModPath::from_src(self.value.path()?, &h)?; + let path = self.value.path().and_then(|path| path::ModPath::from_src(path, &h)); + + if path.is_none() { + error_sink(mbe::ExpandError::Other("malformed macro invocation".into())); + } - AstIdWithPath::new(ast_id.file_id, ast_id.value, path).as_call_id(db, krate, resolver) + AstIdWithPath::new(ast_id.file_id, ast_id.value, path?) + .as_call_id_with_errors(db, krate, resolver, error_sink) } } @@ -497,22 +513,32 @@ impl AstIdWithPath { } impl AsMacroCall for AstIdWithPath { - fn as_call_id( + fn as_call_id_with_errors( &self, db: &dyn db::DefDatabase, krate: CrateId, resolver: impl Fn(path::ModPath) -> Option, + error_sink: &mut dyn FnMut(mbe::ExpandError), ) -> Option { - let def: MacroDefId = resolver(self.path.clone())?; + let def: MacroDefId = resolver(self.path.clone()).or_else(|| { + error_sink(mbe::ExpandError::Other("could not resolve macro".into())); + None + })?; if let MacroDefKind::BuiltInEager(_) = def.kind { let macro_call = InFile::new(self.ast_id.file_id, self.ast_id.to_node(db.upcast())); let hygiene = Hygiene::new(db.upcast(), self.ast_id.file_id); Some( - expand_eager_macro(db.upcast(), krate, macro_call, def, &|path: ast::Path| { - resolver(path::ModPath::from_src(path, &hygiene)?) - })? + expand_eager_macro( + db.upcast(), + krate, + macro_call, + def, + &|path: ast::Path| resolver(path::ModPath::from_src(path, &hygiene)?), + error_sink, + ) + .ok()? .into(), ) } else { @@ -522,13 +548,18 @@ impl AsMacroCall for AstIdWithPath { } impl AsMacroCall for AstIdWithPath { - fn as_call_id( + fn as_call_id_with_errors( &self, db: &dyn db::DefDatabase, krate: CrateId, resolver: impl Fn(path::ModPath) -> Option, + error_sink: &mut dyn FnMut(mbe::ExpandError), ) -> Option { - let def = resolver(self.path.clone())?; + let def: MacroDefId = resolver(self.path.clone()).or_else(|| { + error_sink(mbe::ExpandError::Other("could not resolve macro".into())); + None + })?; + Some( def.as_lazy_macro( db.upcast(), -- cgit v1.2.3