Skip to content

Commit 30f0257

Browse files
committed
Detect and report macro kind mismatches early, and more precisely
This eliminates the case in `failed_to_match_macro` to check for a function-like invocation of a macro with no function-like rules. Instead, macro kind mismatches now result in an unresolved macro, and we detect this case in `unresolved_macro_suggestions`, which now carefully distinguishes between a kind mismatch and other errors. This also handles cases of forward-referenced attributes and cyclic attributes. Expand test coverage to include all of these cases.
1 parent 1148626 commit 30f0257

File tree

6 files changed

+108
-29
lines changed

6 files changed

+108
-29
lines changed

compiler/rustc_expand/src/mbe/diagnostics.rs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,6 @@ pub(super) fn failed_to_match_macro(
5858

5959
let Some(BestFailure { token, msg: label, remaining_matcher, .. }) = tracker.best_failure
6060
else {
61-
// FIXME: we should report this at macro resolution time, as we do for
62-
// `resolve_macro_cannot_use_as_attr`. We can do that once we track multiple macro kinds for a
63-
// Def.
64-
if attr_args.is_none() && !rules.iter().any(|rule| matches!(rule, MacroRule::Func { .. })) {
65-
let msg = format!("macro has no rules for function-like invocation `{name}!`");
66-
let mut err = psess.dcx().struct_span_err(sp, msg);
67-
if !def_head_span.is_dummy() {
68-
let msg = "this macro has no rules for function-like invocation";
69-
err.span_label(def_head_span, msg);
70-
}
71-
return (sp, err.emit());
72-
}
7361
return (sp, psess.dcx().span_delayed_bug(sp, "failed to match a macro"));
7462
};
7563

compiler/rustc_resolve/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,9 @@ resolve_lowercase_self =
242242
attempt to use a non-constant value in a constant
243243
.suggestion = try using `Self`
244244
245+
resolve_macro_cannot_use_as_fn_like =
246+
`{$ident}` exists, but has no rules for function-like invocation
247+
245248
resolve_macro_cannot_use_as_attr =
246249
`{$ident}` exists, but has no `attr` rules
247250

compiler/rustc_resolve/src/diagnostics.rs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,11 +1556,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15561556
if let Some((def_id, unused_ident)) = unused_macro {
15571557
let scope = self.local_macro_def_scopes[&def_id];
15581558
let parent_nearest = parent_scope.module.nearest_parent_mod();
1559-
if Some(parent_nearest) == scope.opt_def_id() {
1559+
let unused_macro_kinds = self.local_macro_map[def_id].ext.macro_kinds();
1560+
if !unused_macro_kinds.contains(macro_kind.into()) {
15601561
match macro_kind {
15611562
MacroKind::Bang => {
1562-
err.subdiagnostic(MacroDefinedLater { span: unused_ident.span });
1563-
err.subdiagnostic(MacroSuggMovePosition { span: ident.span, ident });
1563+
err.subdiagnostic(MacroRulesNot::Func { span: unused_ident.span, ident });
15641564
}
15651565
MacroKind::Attr => {
15661566
err.subdiagnostic(MacroRulesNot::Attr { span: unused_ident.span, ident });
@@ -1569,14 +1569,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15691569
err.subdiagnostic(MacroRulesNot::Derive { span: unused_ident.span, ident });
15701570
}
15711571
}
1572-
15731572
return;
15741573
}
1575-
}
1576-
1577-
if self.macro_names.contains(&ident.normalize_to_macros_2_0()) {
1578-
err.subdiagnostic(AddedMacroUse);
1579-
return;
1574+
if Some(parent_nearest) == scope.opt_def_id() {
1575+
err.subdiagnostic(MacroDefinedLater { span: unused_ident.span });
1576+
err.subdiagnostic(MacroSuggMovePosition { span: ident.span, ident });
1577+
return;
1578+
}
15801579
}
15811580

15821581
if ident.name == kw::Default
@@ -1652,6 +1651,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
16521651
err.subdiagnostic(note);
16531652
return;
16541653
}
1654+
1655+
if self.macro_names.contains(&ident.normalize_to_macros_2_0()) {
1656+
err.subdiagnostic(AddedMacroUse);
1657+
return;
1658+
}
16551659
}
16561660

16571661
/// Given an attribute macro that failed to be resolved, look for `derive` macros that could

compiler/rustc_resolve/src/errors.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,12 @@ pub(crate) struct MacroSuggMovePosition {
672672

673673
#[derive(Subdiagnostic)]
674674
pub(crate) enum MacroRulesNot {
675+
#[label(resolve_macro_cannot_use_as_fn_like)]
676+
Func {
677+
#[primary_span]
678+
span: Span,
679+
ident: Ident,
680+
},
675681
#[label(resolve_macro_cannot_use_as_attr)]
676682
Attr {
677683
#[primary_span]

tests/ui/macros/macro-rules-attr-error.rs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,46 @@ macro_rules! local_attr {
77
//~^^ ERROR: local_attr
88
}
99

10+
//~v NOTE: `fn_only` exists, but has no `attr` rules
11+
macro_rules! fn_only {
12+
{} => {}
13+
}
14+
15+
//~v NOTE: `attr_only` exists, but has no rules for function-like invocation
16+
macro_rules! attr_only {
17+
attr() {} => {}
18+
}
19+
1020
fn main() {
21+
//~v NOTE: in this expansion of #[local_attr]
1122
#[local_attr]
1223
struct S;
1324

14-
local_attr!(arg); //~ ERROR: macro has no rules for function-like invocation
25+
//~vv ERROR: cannot find macro `local_attr` in this scope
26+
//~| NOTE: `local_attr` is in scope, but it is an attribute
27+
local_attr!(arg);
28+
29+
//~v ERROR: cannot find attribute `fn_only` in this scope
30+
#[fn_only]
31+
struct S;
32+
33+
attr_only!(); //~ ERROR: cannot find macro `attr_only` in this scope
34+
}
35+
36+
//~vv ERROR: cannot find attribute `forward_referenced_attr` in this scope
37+
//~| NOTE: consider moving the definition of `forward_referenced_attr` before this call
38+
#[forward_referenced_attr]
39+
struct S;
40+
41+
//~v NOTE: a macro with the same name exists, but it appears later
42+
macro_rules! forward_referenced_attr {
43+
attr() {} => {}
44+
}
45+
46+
//~vv ERROR: cannot find attribute `cyclic_attr` in this scope
47+
//~| NOTE: consider moving the definition of `cyclic_attr` before this call
48+
#[cyclic_attr]
49+
//~v NOTE: a macro with the same name exists, but it appears later
50+
macro_rules! cyclic_attr {
51+
attr() {} => {}
1552
}

tests/ui/macros/macro-rules-attr-error.stderr

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,55 @@ LL | #[local_attr]
99
|
1010
= note: this error originates in the attribute macro `local_attr` (in Nightly builds, run with -Z macro-backtrace for more info)
1111

12-
error: macro has no rules for function-like invocation `local_attr!`
13-
--> $DIR/macro-rules-attr-error.rs:14:5
12+
error: cannot find macro `local_attr` in this scope
13+
--> $DIR/macro-rules-attr-error.rs:27:5
1414
|
15-
LL | macro_rules! local_attr {
16-
| ----------------------- this macro has no rules for function-like invocation
17-
...
1815
LL | local_attr!(arg);
19-
| ^^^^^^^^^^^^^^^^
16+
| ^^^^^^^^^^
17+
|
18+
= note: `local_attr` is in scope, but it is an attribute: `#[local_attr]`
19+
20+
error: cannot find attribute `fn_only` in this scope
21+
--> $DIR/macro-rules-attr-error.rs:30:7
22+
|
23+
LL | macro_rules! fn_only {
24+
| ------- `fn_only` exists, but has no `attr` rules
25+
...
26+
LL | #[fn_only]
27+
| ^^^^^^^
28+
29+
error: cannot find macro `attr_only` in this scope
30+
--> $DIR/macro-rules-attr-error.rs:33:5
31+
|
32+
LL | macro_rules! attr_only {
33+
| --------- `attr_only` exists, but has no rules for function-like invocation
34+
...
35+
LL | attr_only!();
36+
| ^^^^^^^^^
37+
38+
error: cannot find attribute `forward_referenced_attr` in this scope
39+
--> $DIR/macro-rules-attr-error.rs:38:3
40+
|
41+
LL | #[forward_referenced_attr]
42+
| ^^^^^^^^^^^^^^^^^^^^^^^ consider moving the definition of `forward_referenced_attr` before this call
43+
|
44+
note: a macro with the same name exists, but it appears later
45+
--> $DIR/macro-rules-attr-error.rs:42:14
46+
|
47+
LL | macro_rules! forward_referenced_attr {
48+
| ^^^^^^^^^^^^^^^^^^^^^^^
49+
50+
error: cannot find attribute `cyclic_attr` in this scope
51+
--> $DIR/macro-rules-attr-error.rs:48:3
52+
|
53+
LL | #[cyclic_attr]
54+
| ^^^^^^^^^^^ consider moving the definition of `cyclic_attr` before this call
55+
|
56+
note: a macro with the same name exists, but it appears later
57+
--> $DIR/macro-rules-attr-error.rs:50:14
58+
|
59+
LL | macro_rules! cyclic_attr {
60+
| ^^^^^^^^^^^
2061

21-
error: aborting due to 2 previous errors
62+
error: aborting due to 6 previous errors
2263

0 commit comments

Comments
 (0)