aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-03-15 18:24:22 +0000
committerGitHub <[email protected]>2021-03-15 18:24:22 +0000
commit47b74cadf9774f624ff13f8c7929c66be8247fc8 (patch)
tree6dc42e70ef3635bb53354b4e8991f517eb9b389d
parente24453c5ee46546b0852c15500d51f77b10a7a6f (diff)
parentebb10da563f1c3a0ebf48c1022bceb9641b6e964 (diff)
Merge #7970
7970: Fix incorrect diagnostics for failing built in macros r=jonas-schievink a=brandondong **Reproduction:** 1. Use a built in macro in such a way that rust-analyzer fails to expand it. For example: **lib.rs** ``` include!("<valid file but without a .rs extension so it is not indexed by rust-analyzer>"); ``` 2. rust-analyzer highlights the macro call and says the macro itself cannot be resolved even though include! is in the standard library (unresolved-macro-call diagnostic). 3. No macro-error diagnostic is raised. **Root cause for incorrect unresolved-macro-call diagnostic:** 1. collector:collect_macro_call is able to resolve include! in legacy scope but the expansion fails. Therefore, it's pushed into unexpanded_macros to be retried with module scope. 2. include! fails at the resolution step in collector:resolve_macros now that it's using module scope. Therefore, it's retained in unexpanded_macros. 3. Finally, collector:finish tries resolving the remaining unexpanded macros but only with module scope. include! again fails at the resolution step so a diagnostic is created. **Root cause for missing macro-error diagnostic:** 1. In collector:resolve_macros, directive.legacy is None since eager expansion failed in collector:collect_macro_call. The macro_call_as_call_id fails to resolve since we're retrying in module scope. Therefore, collect_macro_expansion is not called for the macro and no macro-error diagnostic is generated. **Fix:** - In collector:collect_macro_call, do not add failing built-in macros to the unexpanded_macros list and immediately raise the macro-error diagnostic. This is in contrast to lazy macros which are resolved in collector::resolve_macros and later expanded in collect_macro_expansion where a macro-error diagnostic may be raised. Co-authored-by: Brandon <[email protected]> Co-authored-by: brandondong <[email protected]>
-rw-r--r--crates/hir_def/src/diagnostics.rs2
-rw-r--r--crates/hir_def/src/nameres/collector.rs33
-rw-r--r--crates/hir_def/src/nameres/tests/diagnostics.rs45
3 files changed, 69 insertions, 11 deletions
diff --git a/crates/hir_def/src/diagnostics.rs b/crates/hir_def/src/diagnostics.rs
index ac7474f63..7188bb299 100644
--- a/crates/hir_def/src/diagnostics.rs
+++ b/crates/hir_def/src/diagnostics.rs
@@ -97,7 +97,7 @@ impl Diagnostic for UnresolvedImport {
97 97
98// Diagnostic: unresolved-macro-call 98// Diagnostic: unresolved-macro-call
99// 99//
100// This diagnostic is triggered if rust-analyzer is unable to resolove path to a 100// This diagnostic is triggered if rust-analyzer is unable to resolve the path to a
101// macro in a macro invocation. 101// macro in a macro invocation.
102#[derive(Debug)] 102#[derive(Debug)]
103pub struct UnresolvedMacroCall { 103pub struct UnresolvedMacroCall {
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 9ed48c506..81cf652b0 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -13,7 +13,7 @@ use hir_expand::{
13 builtin_macro::find_builtin_macro, 13 builtin_macro::find_builtin_macro,
14 name::{AsName, Name}, 14 name::{AsName, Name},
15 proc_macro::ProcMacroExpander, 15 proc_macro::ProcMacroExpander,
16 HirFileId, MacroCallId, MacroDefId, MacroDefKind, 16 HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
17}; 17};
18use hir_expand::{InFile, MacroCallLoc}; 18use hir_expand::{InFile, MacroCallLoc};
19use rustc_hash::{FxHashMap, FxHashSet}; 19use rustc_hash::{FxHashMap, FxHashSet};
@@ -1455,7 +1455,8 @@ impl ModCollector<'_, '_> {
1455 let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); 1455 let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone());
1456 1456
1457 // Case 1: try to resolve in legacy scope and expand macro_rules 1457 // Case 1: try to resolve in legacy scope and expand macro_rules
1458 if let Ok(Ok(macro_call_id)) = macro_call_as_call_id( 1458 let mut error = None;
1459 match macro_call_as_call_id(
1459 &ast_id, 1460 &ast_id,
1460 self.def_collector.db, 1461 self.def_collector.db,
1461 self.def_collector.def_map.krate, 1462 self.def_collector.def_map.krate,
@@ -1468,16 +1469,28 @@ impl ModCollector<'_, '_> {
1468 ) 1469 )
1469 }) 1470 })
1470 }, 1471 },
1471 &mut |_err| (), 1472 &mut |err| error = Some(err),
1472 ) { 1473 ) {
1473 self.def_collector.unexpanded_macros.push(MacroDirective { 1474 Ok(Ok(macro_call_id)) => {
1474 module_id: self.module_id, 1475 self.def_collector.unexpanded_macros.push(MacroDirective {
1475 ast_id, 1476 module_id: self.module_id,
1476 legacy: Some(macro_call_id), 1477 ast_id,
1477 depth: self.macro_depth + 1, 1478 legacy: Some(macro_call_id),
1478 }); 1479 depth: self.macro_depth + 1,
1480 });
1479 1481
1480 return; 1482 return;
1483 }
1484 Ok(Err(_)) => {
1485 // Built-in macro failed eager expansion.
1486 self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error(
1487 self.module_id,
1488 MacroCallKind::FnLike(ast_id.ast_id),
1489 error.unwrap().to_string(),
1490 ));
1491 return;
1492 }
1493 Err(UnresolvedMacro) => (),
1481 } 1494 }
1482 1495
1483 // Case 2: resolve in module scope, expand during name resolution. 1496 // Case 2: resolve in module scope, expand during name resolution.
diff --git a/crates/hir_def/src/nameres/tests/diagnostics.rs b/crates/hir_def/src/nameres/tests/diagnostics.rs
index 1b8e885b0..c22ef46fd 100644
--- a/crates/hir_def/src/nameres/tests/diagnostics.rs
+++ b/crates/hir_def/src/nameres/tests/diagnostics.rs
@@ -155,3 +155,48 @@ fn inactive_via_cfg_attr() {
155 "#, 155 "#,
156 ); 156 );
157} 157}
158
159#[test]
160fn unresolved_legacy_scope_macro() {
161 check_diagnostics(
162 r#"
163 //- /lib.rs
164 macro_rules! m { () => {} }
165
166 m!();
167 m2!();
168 //^^^^^^ unresolved macro call
169 "#,
170 );
171}
172
173#[test]
174fn unresolved_module_scope_macro() {
175 check_diagnostics(
176 r#"
177 //- /lib.rs
178 mod mac {
179 #[macro_export]
180 macro_rules! m { () => {} }
181 }
182
183 self::m!();
184 self::m2!();
185 //^^^^^^^^^^^^ unresolved macro call
186 "#,
187 );
188}
189
190#[test]
191fn builtin_macro_fails_expansion() {
192 check_diagnostics(
193 r#"
194 //- /lib.rs
195 #[rustc_builtin_macro]
196 macro_rules! include { () => {} }
197
198 include!("doesntexist");
199 //^^^^^^^^^^^^^^^^^^^^^^^^ could not convert tokens
200 "#,
201 );
202}