Skip to content

Commit 0bfebc6

Browse files
committed
Detect attempts to expand a macro to a match arm again
Because a macro invocation can expand to a never pattern, we can't rule out a `arm!(),` arm at parse time. Instead we detect that case at expansion time, if the macro tries to output a pattern followed by `=>`.
1 parent 80bdcbf commit 0bfebc6

File tree

8 files changed

+27
-29
lines changed

8 files changed

+27
-29
lines changed

compiler/rustc_expand/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ expand_macro_const_stability =
7171
.label = invalid const stability attribute
7272
.label2 = const stability attribute affects this macro
7373
74+
expand_macro_expands_to_match_arm = macros cannot expand to match arms
75+
7476
expand_malformed_feature_attribute =
7577
malformed `feature` attribute input
7678
.expected = expected just one word

compiler/rustc_expand/src/errors.rs

+2
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,8 @@ pub(crate) struct IncompleteParse<'a> {
304304
pub label_span: Span,
305305
pub macro_path: &'a ast::Path,
306306
pub kind_name: &'a str,
307+
#[note(expand_macro_expands_to_match_arm)]
308+
pub expands_to_match_arm: Option<()>,
307309

308310
#[suggestion(
309311
expand_suggestion_add_semi,

compiler/rustc_expand/src/expand.rs

+3
Original file line numberDiff line numberDiff line change
@@ -955,12 +955,15 @@ pub fn ensure_complete_parse<'a>(
955955
_ => None,
956956
};
957957

958+
let expands_to_match_arm = kind_name == "pattern" && parser.token == token::FatArrow;
959+
958960
parser.sess.emit_err(IncompleteParse {
959961
span: def_site_span,
960962
token,
961963
label_span: span,
962964
macro_path,
963965
kind_name,
966+
expands_to_match_arm: expands_to_match_arm.then_some(()),
964967
add_semicolon,
965968
});
966969
}

compiler/rustc_parse/messages.ftl

-2
Original file line numberDiff line numberDiff line change
@@ -456,8 +456,6 @@ parse_macro_expands_to_adt_field = macros cannot expand to {$adt_ty} fields
456456
457457
parse_macro_expands_to_enum_variant = macros cannot expand to enum variants
458458
459-
parse_macro_expands_to_match_arm = macros cannot expand to match arms
460-
461459
parse_macro_invocation_visibility = can't qualify macro invocation with `pub`
462460
.suggestion = remove the visibility
463461
.help = try adjusting the macro to put `{$vis}` inside the invocation

compiler/rustc_parse/src/parser/diagnostics.rs

+16-21
Original file line numberDiff line numberDiff line change
@@ -2823,7 +2823,6 @@ impl<'a> Parser<'a> {
28232823
pub(crate) fn maybe_recover_unexpected_comma(
28242824
&mut self,
28252825
lo: Span,
2826-
is_mac_invoc: bool,
28272826
rt: CommaRecoveryMode,
28282827
) -> PResult<'a, ()> {
28292828
if self.token != token::Comma {
@@ -2844,28 +2843,24 @@ impl<'a> Parser<'a> {
28442843
let seq_span = lo.to(self.prev_token.span);
28452844
let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern");
28462845
if let Ok(seq_snippet) = self.span_to_snippet(seq_span) {
2847-
if is_mac_invoc {
2848-
err.note(fluent::parse_macro_expands_to_match_arm);
2849-
} else {
2850-
err.multipart_suggestion(
2851-
format!(
2852-
"try adding parentheses to match on a tuple{}",
2853-
if let CommaRecoveryMode::LikelyTuple = rt { "" } else { "..." },
2854-
),
2855-
vec![
2856-
(seq_span.shrink_to_lo(), "(".to_string()),
2857-
(seq_span.shrink_to_hi(), ")".to_string()),
2858-
],
2846+
err.multipart_suggestion(
2847+
format!(
2848+
"try adding parentheses to match on a tuple{}",
2849+
if let CommaRecoveryMode::LikelyTuple = rt { "" } else { "..." },
2850+
),
2851+
vec![
2852+
(seq_span.shrink_to_lo(), "(".to_string()),
2853+
(seq_span.shrink_to_hi(), ")".to_string()),
2854+
],
2855+
Applicability::MachineApplicable,
2856+
);
2857+
if let CommaRecoveryMode::EitherTupleOrPipe = rt {
2858+
err.span_suggestion(
2859+
seq_span,
2860+
"...or a vertical bar to match on multiple alternatives",
2861+
seq_snippet.replace(',', " |"),
28592862
Applicability::MachineApplicable,
28602863
);
2861-
if let CommaRecoveryMode::EitherTupleOrPipe = rt {
2862-
err.span_suggestion(
2863-
seq_span,
2864-
"...or a vertical bar to match on multiple alternatives",
2865-
seq_snippet.replace(',', " |"),
2866-
Applicability::MachineApplicable,
2867-
);
2868-
}
28692864
}
28702865
}
28712866
Err(err)

compiler/rustc_parse/src/parser/pat.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -155,11 +155,7 @@ impl<'a> Parser<'a> {
155155
Err(err) => return Err(err),
156156
};
157157
if rc == RecoverComma::Yes && !first_pat.could_be_never_pattern() {
158-
self.maybe_recover_unexpected_comma(
159-
first_pat.span,
160-
matches!(first_pat.kind, PatKind::MacCall(_)),
161-
rt,
162-
)?;
158+
self.maybe_recover_unexpected_comma(first_pat.span, rt)?;
163159
}
164160

165161
// If the next token is not a `|`,
@@ -201,7 +197,7 @@ impl<'a> Parser<'a> {
201197
err
202198
})?;
203199
if rc == RecoverComma::Yes && !pat.could_be_never_pattern() {
204-
self.maybe_recover_unexpected_comma(pat.span, false, rt)?;
200+
self.maybe_recover_unexpected_comma(pat.span, rt)?;
205201
}
206202
pats.push(pat);
207203
}

tests/ui/parser/macro/macro-expand-to-match-arm.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ macro_rules! arm {
33
$pattern => $block
44
//~^ ERROR macro expansion ignores token `=>` and any following
55
//~| NOTE the usage of `arm!` is likely invalid in pattern context
6+
//~| NOTE macros cannot expand to match arms
67
};
78
}
89

tests/ui/parser/macro/macro-expand-to-match-arm.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ LL | arm!(None => {}),
88
| ---------------- caused by the macro expansion here
99
|
1010
= note: the usage of `arm!` is likely invalid in pattern context
11+
= note: macros cannot expand to match arms
1112

1213
error: aborting due to 1 previous error
1314

0 commit comments

Comments
 (0)