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 `=>`.
This commit is contained in:
Nadrieril 2023-11-27 00:50:51 +01:00
parent 80bdcbf50a
commit 0bfebc6105
8 changed files with 27 additions and 29 deletions

View File

@ -71,6 +71,8 @@ expand_macro_const_stability =
.label = invalid const stability attribute
.label2 = const stability attribute affects this macro
expand_macro_expands_to_match_arm = macros cannot expand to match arms
expand_malformed_feature_attribute =
malformed `feature` attribute input
.expected = expected just one word

View File

@ -304,6 +304,8 @@ pub(crate) struct IncompleteParse<'a> {
pub label_span: Span,
pub macro_path: &'a ast::Path,
pub kind_name: &'a str,
#[note(expand_macro_expands_to_match_arm)]
pub expands_to_match_arm: Option<()>,
#[suggestion(
expand_suggestion_add_semi,

View File

@ -955,12 +955,15 @@ pub fn ensure_complete_parse<'a>(
_ => None,
};
let expands_to_match_arm = kind_name == "pattern" && parser.token == token::FatArrow;
parser.sess.emit_err(IncompleteParse {
span: def_site_span,
token,
label_span: span,
macro_path,
kind_name,
expands_to_match_arm: expands_to_match_arm.then_some(()),
add_semicolon,
});
}

View File

@ -456,8 +456,6 @@ parse_macro_expands_to_adt_field = macros cannot expand to {$adt_ty} fields
parse_macro_expands_to_enum_variant = macros cannot expand to enum variants
parse_macro_expands_to_match_arm = macros cannot expand to match arms
parse_macro_invocation_visibility = can't qualify macro invocation with `pub`
.suggestion = remove the visibility
.help = try adjusting the macro to put `{$vis}` inside the invocation

View File

@ -2823,7 +2823,6 @@ impl<'a> Parser<'a> {
pub(crate) fn maybe_recover_unexpected_comma(
&mut self,
lo: Span,
is_mac_invoc: bool,
rt: CommaRecoveryMode,
) -> PResult<'a, ()> {
if self.token != token::Comma {
@ -2844,28 +2843,24 @@ impl<'a> Parser<'a> {
let seq_span = lo.to(self.prev_token.span);
let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern");
if let Ok(seq_snippet) = self.span_to_snippet(seq_span) {
if is_mac_invoc {
err.note(fluent::parse_macro_expands_to_match_arm);
} else {
err.multipart_suggestion(
format!(
"try adding parentheses to match on a tuple{}",
if let CommaRecoveryMode::LikelyTuple = rt { "" } else { "..." },
),
vec![
(seq_span.shrink_to_lo(), "(".to_string()),
(seq_span.shrink_to_hi(), ")".to_string()),
],
err.multipart_suggestion(
format!(
"try adding parentheses to match on a tuple{}",
if let CommaRecoveryMode::LikelyTuple = rt { "" } else { "..." },
),
vec![
(seq_span.shrink_to_lo(), "(".to_string()),
(seq_span.shrink_to_hi(), ")".to_string()),
],
Applicability::MachineApplicable,
);
if let CommaRecoveryMode::EitherTupleOrPipe = rt {
err.span_suggestion(
seq_span,
"...or a vertical bar to match on multiple alternatives",
seq_snippet.replace(',', " |"),
Applicability::MachineApplicable,
);
if let CommaRecoveryMode::EitherTupleOrPipe = rt {
err.span_suggestion(
seq_span,
"...or a vertical bar to match on multiple alternatives",
seq_snippet.replace(',', " |"),
Applicability::MachineApplicable,
);
}
}
}
Err(err)

View File

@ -155,11 +155,7 @@ impl<'a> Parser<'a> {
Err(err) => return Err(err),
};
if rc == RecoverComma::Yes && !first_pat.could_be_never_pattern() {
self.maybe_recover_unexpected_comma(
first_pat.span,
matches!(first_pat.kind, PatKind::MacCall(_)),
rt,
)?;
self.maybe_recover_unexpected_comma(first_pat.span, rt)?;
}
// If the next token is not a `|`,
@ -201,7 +197,7 @@ impl<'a> Parser<'a> {
err
})?;
if rc == RecoverComma::Yes && !pat.could_be_never_pattern() {
self.maybe_recover_unexpected_comma(pat.span, false, rt)?;
self.maybe_recover_unexpected_comma(pat.span, rt)?;
}
pats.push(pat);
}

View File

@ -3,6 +3,7 @@ macro_rules! arm {
$pattern => $block
//~^ ERROR macro expansion ignores token `=>` and any following
//~| NOTE the usage of `arm!` is likely invalid in pattern context
//~| NOTE macros cannot expand to match arms
};
}

View File

@ -8,6 +8,7 @@ LL | arm!(None => {}),
| ---------------- caused by the macro expansion here
|
= note: the usage of `arm!` is likely invalid in pattern context
= note: macros cannot expand to match arms
error: aborting due to 1 previous error