diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-03-17 07:20:28 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2021-03-17 07:20:28 +0000 |
commit | 6fcb5d772f16af0d1f62dad55fbde75072fb9e89 (patch) | |
tree | e4ddd896f9ca8ca1f99c346a49104b04bc4ca04c /crates/hir_def/src/lib.rs | |
parent | 83e6940efb42675226adb8d2856c095b8dce36c5 (diff) | |
parent | a79b5673e8f5d1f8d569bc7c984a293a972a7bb0 (diff) |
Merge #8048
8048: Fix missing unresolved macro diagnostic in function body r=edwin0cheng a=brandondong
This was an issue I found while working on https://github.com/rust-analyzer/rust-analyzer/pull/7970.
**Reproduction:**
1. Call a non-existent macro in a function body.
```
fn main() {
foo!();
}
```
2. No diagnostics are raised. An unresolved-macro-call diagnostic is expected.
3. If the macro call is instead outside of the function body, this works as expected.
I believe this worked previously and regressed in https://github.com/rust-analyzer/rust-analyzer/pull/7805.
**Behavior prior to https://github.com/rust-analyzer/rust-analyzer/pull/7805:**
- The unresolved-macro-call diagnostic did not exist. Instead, a macro-error diagnostic would be raised with the text "could not resolve macro [path]".
- This was implemented by adding an error to the error sink (https://github.com/rust-analyzer/rust-analyzer/pull/7805/files#diff-50a326c5ae465bd9b31ee4310186380aa06e4fa1f6b41dbc0aed5bcc656a3cb8L657).
- The error was propagated through https://github.com/rust-analyzer/rust-analyzer/blob/1a82af3527e476d52410ff4dfd2fb4c57466abcb/crates/hir_def/src/body.rs#L123 eventually reaching https://github.com/rust-analyzer/rust-analyzer/blob/1a82af3527e476d52410ff4dfd2fb4c57466abcb/crates/hir_def/src/body/lower.rs#L569.
**Behavior after:**
- Instead of writing to the error sink, an UnresolvedMacro error is now returned (https://github.com/rust-analyzer/rust-analyzer/pull/7805/files#diff-50a326c5ae465bd9b31ee4310186380aa06e4fa1f6b41dbc0aed5bcc656a3cb8R631).
- The parent caller throws away the error as its function signature is `Option<MacroCallId>` (https://github.com/rust-analyzer/rust-analyzer/pull/7805/files#diff-50a326c5ae465bd9b31ee4310186380aa06e4fa1f6b41dbc0aed5bcc656a3cb8R604).
- We instead now reach the warn condition (https://github.com/rust-analyzer/rust-analyzer/blob/1a82af3527e476d52410ff4dfd2fb4c57466abcb/crates/hir_def/src/body.rs#L124) and no diagnostics are created in https://github.com/rust-analyzer/rust-analyzer/blob/1a82af3527e476d52410ff4dfd2fb4c57466abcb/crates/hir_def/src/body/lower.rs#L575.
**Fix:**
- Make sure to propagate the UnresolvedMacro error. Report the error using the new unresolved-macro-call diagnostic.
Co-authored-by: Brandon <[email protected]>
Diffstat (limited to 'crates/hir_def/src/lib.rs')
-rw-r--r-- | crates/hir_def/src/lib.rs | 27 |
1 files changed, 15 insertions, 12 deletions
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index c6655c5fb..6758411a0 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -58,7 +58,7 @@ use std::{ | |||
58 | use base_db::{impl_intern_key, salsa, CrateId}; | 58 | use base_db::{impl_intern_key, salsa, CrateId}; |
59 | use hir_expand::{ | 59 | use hir_expand::{ |
60 | ast_id_map::FileAstId, | 60 | ast_id_map::FileAstId, |
61 | eager::{expand_eager_macro, ErrorEmitted}, | 61 | eager::{expand_eager_macro, ErrorEmitted, ErrorSink}, |
62 | hygiene::Hygiene, | 62 | hygiene::Hygiene, |
63 | AstId, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, | 63 | AstId, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, |
64 | }; | 64 | }; |
@@ -583,7 +583,7 @@ pub trait AsMacroCall { | |||
583 | krate: CrateId, | 583 | krate: CrateId, |
584 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | 584 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, |
585 | ) -> Option<MacroCallId> { | 585 | ) -> Option<MacroCallId> { |
586 | self.as_call_id_with_errors(db, krate, resolver, &mut |_| ()) | 586 | self.as_call_id_with_errors(db, krate, resolver, &mut |_| ()).ok()?.ok() |
587 | } | 587 | } |
588 | 588 | ||
589 | fn as_call_id_with_errors( | 589 | fn as_call_id_with_errors( |
@@ -592,7 +592,7 @@ pub trait AsMacroCall { | |||
592 | krate: CrateId, | 592 | krate: CrateId, |
593 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | 593 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, |
594 | error_sink: &mut dyn FnMut(mbe::ExpandError), | 594 | error_sink: &mut dyn FnMut(mbe::ExpandError), |
595 | ) -> Option<MacroCallId>; | 595 | ) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro>; |
596 | } | 596 | } |
597 | 597 | ||
598 | impl AsMacroCall for InFile<&ast::MacroCall> { | 598 | impl AsMacroCall for InFile<&ast::MacroCall> { |
@@ -601,25 +601,28 @@ impl AsMacroCall for InFile<&ast::MacroCall> { | |||
601 | db: &dyn db::DefDatabase, | 601 | db: &dyn db::DefDatabase, |
602 | krate: CrateId, | 602 | krate: CrateId, |
603 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | 603 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, |
604 | error_sink: &mut dyn FnMut(mbe::ExpandError), | 604 | mut error_sink: &mut dyn FnMut(mbe::ExpandError), |
605 | ) -> Option<MacroCallId> { | 605 | ) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> { |
606 | let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value)); | 606 | let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value)); |
607 | let h = Hygiene::new(db.upcast(), self.file_id); | 607 | let h = Hygiene::new(db.upcast(), self.file_id); |
608 | let path = self.value.path().and_then(|path| path::ModPath::from_src(path, &h)); | 608 | let path = self.value.path().and_then(|path| path::ModPath::from_src(path, &h)); |
609 | 609 | ||
610 | if path.is_none() { | 610 | let path = match error_sink |
611 | error_sink(mbe::ExpandError::Other("malformed macro invocation".into())); | 611 | .option(path, || mbe::ExpandError::Other("malformed macro invocation".into())) |
612 | } | 612 | { |
613 | Ok(path) => path, | ||
614 | Err(error) => { | ||
615 | return Ok(Err(error)); | ||
616 | } | ||
617 | }; | ||
613 | 618 | ||
614 | macro_call_as_call_id( | 619 | macro_call_as_call_id( |
615 | &AstIdWithPath::new(ast_id.file_id, ast_id.value, path?), | 620 | &AstIdWithPath::new(ast_id.file_id, ast_id.value, path), |
616 | db, | 621 | db, |
617 | krate, | 622 | krate, |
618 | resolver, | 623 | resolver, |
619 | error_sink, | 624 | error_sink, |
620 | ) | 625 | ) |
621 | .ok()? | ||
622 | .ok() | ||
623 | } | 626 | } |
624 | } | 627 | } |
625 | 628 | ||
@@ -636,7 +639,7 @@ impl<T: ast::AstNode> AstIdWithPath<T> { | |||
636 | } | 639 | } |
637 | } | 640 | } |
638 | 641 | ||
639 | struct UnresolvedMacro; | 642 | pub struct UnresolvedMacro; |
640 | 643 | ||
641 | fn macro_call_as_call_id( | 644 | fn macro_call_as_call_id( |
642 | call: &AstIdWithPath<ast::MacroCall>, | 645 | call: &AstIdWithPath<ast::MacroCall>, |