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
8 changed files with 27 additions and 29 deletions
|
@ -71,6 +71,8 @@ expand_macro_const_stability =
|
||||||
.label = invalid const stability attribute
|
.label = invalid const stability attribute
|
||||||
.label2 = const stability attribute affects this macro
|
.label2 = const stability attribute affects this macro
|
||||||
|
|
||||||
|
expand_macro_expands_to_match_arm = macros cannot expand to match arms
|
||||||
|
|
||||||
expand_malformed_feature_attribute =
|
expand_malformed_feature_attribute =
|
||||||
malformed `feature` attribute input
|
malformed `feature` attribute input
|
||||||
.expected = expected just one word
|
.expected = expected just one word
|
||||||
|
|
|
@ -304,6 +304,8 @@ pub(crate) struct IncompleteParse<'a> {
|
||||||
pub label_span: Span,
|
pub label_span: Span,
|
||||||
pub macro_path: &'a ast::Path,
|
pub macro_path: &'a ast::Path,
|
||||||
pub kind_name: &'a str,
|
pub kind_name: &'a str,
|
||||||
|
#[note(expand_macro_expands_to_match_arm)]
|
||||||
|
pub expands_to_match_arm: Option<()>,
|
||||||
|
|
||||||
#[suggestion(
|
#[suggestion(
|
||||||
expand_suggestion_add_semi,
|
expand_suggestion_add_semi,
|
||||||
|
|
|
@ -955,12 +955,15 @@ pub fn ensure_complete_parse<'a>(
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let expands_to_match_arm = kind_name == "pattern" && parser.token == token::FatArrow;
|
||||||
|
|
||||||
parser.sess.emit_err(IncompleteParse {
|
parser.sess.emit_err(IncompleteParse {
|
||||||
span: def_site_span,
|
span: def_site_span,
|
||||||
token,
|
token,
|
||||||
label_span: span,
|
label_span: span,
|
||||||
macro_path,
|
macro_path,
|
||||||
kind_name,
|
kind_name,
|
||||||
|
expands_to_match_arm: expands_to_match_arm.then_some(()),
|
||||||
add_semicolon,
|
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_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`
|
parse_macro_invocation_visibility = can't qualify macro invocation with `pub`
|
||||||
.suggestion = remove the visibility
|
.suggestion = remove the visibility
|
||||||
.help = try adjusting the macro to put `{$vis}` inside the invocation
|
.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(
|
pub(crate) fn maybe_recover_unexpected_comma(
|
||||||
&mut self,
|
&mut self,
|
||||||
lo: Span,
|
lo: Span,
|
||||||
is_mac_invoc: bool,
|
|
||||||
rt: CommaRecoveryMode,
|
rt: CommaRecoveryMode,
|
||||||
) -> PResult<'a, ()> {
|
) -> PResult<'a, ()> {
|
||||||
if self.token != token::Comma {
|
if self.token != token::Comma {
|
||||||
|
@ -2844,28 +2843,24 @@ impl<'a> Parser<'a> {
|
||||||
let seq_span = lo.to(self.prev_token.span);
|
let seq_span = lo.to(self.prev_token.span);
|
||||||
let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern");
|
let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern");
|
||||||
if let Ok(seq_snippet) = self.span_to_snippet(seq_span) {
|
if let Ok(seq_snippet) = self.span_to_snippet(seq_span) {
|
||||||
if is_mac_invoc {
|
err.multipart_suggestion(
|
||||||
err.note(fluent::parse_macro_expands_to_match_arm);
|
format!(
|
||||||
} else {
|
"try adding parentheses to match on a tuple{}",
|
||||||
err.multipart_suggestion(
|
if let CommaRecoveryMode::LikelyTuple = rt { "" } else { "..." },
|
||||||
format!(
|
),
|
||||||
"try adding parentheses to match on a tuple{}",
|
vec![
|
||||||
if let CommaRecoveryMode::LikelyTuple = rt { "" } else { "..." },
|
(seq_span.shrink_to_lo(), "(".to_string()),
|
||||||
),
|
(seq_span.shrink_to_hi(), ")".to_string()),
|
||||||
vec![
|
],
|
||||||
(seq_span.shrink_to_lo(), "(".to_string()),
|
Applicability::MachineApplicable,
|
||||||
(seq_span.shrink_to_hi(), ")".to_string()),
|
);
|
||||||
],
|
if let CommaRecoveryMode::EitherTupleOrPipe = rt {
|
||||||
|
err.span_suggestion(
|
||||||
|
seq_span,
|
||||||
|
"...or a vertical bar to match on multiple alternatives",
|
||||||
|
seq_snippet.replace(',', " |"),
|
||||||
Applicability::MachineApplicable,
|
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)
|
Err(err)
|
||||||
|
|
|
@ -155,11 +155,7 @@ impl<'a> Parser<'a> {
|
||||||
Err(err) => return Err(err),
|
Err(err) => return Err(err),
|
||||||
};
|
};
|
||||||
if rc == RecoverComma::Yes && !first_pat.could_be_never_pattern() {
|
if rc == RecoverComma::Yes && !first_pat.could_be_never_pattern() {
|
||||||
self.maybe_recover_unexpected_comma(
|
self.maybe_recover_unexpected_comma(first_pat.span, rt)?;
|
||||||
first_pat.span,
|
|
||||||
matches!(first_pat.kind, PatKind::MacCall(_)),
|
|
||||||
rt,
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the next token is not a `|`,
|
// If the next token is not a `|`,
|
||||||
|
@ -201,7 +197,7 @@ impl<'a> Parser<'a> {
|
||||||
err
|
err
|
||||||
})?;
|
})?;
|
||||||
if rc == RecoverComma::Yes && !pat.could_be_never_pattern() {
|
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);
|
pats.push(pat);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ macro_rules! arm {
|
||||||
$pattern => $block
|
$pattern => $block
|
||||||
//~^ ERROR macro expansion ignores token `=>` and any following
|
//~^ ERROR macro expansion ignores token `=>` and any following
|
||||||
//~| NOTE the usage of `arm!` is likely invalid in pattern context
|
//~| 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
|
| ---------------- caused by the macro expansion here
|
||||||
|
|
|
|
||||||
= note: the usage of `arm!` is likely invalid in pattern context
|
= 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
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue