mirror of https://github.com/rust-lang/rust.git
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:
parent
80bdcbf50a
commit
0bfebc6105
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue