1
Fork 0

Specify macro is invalid in certain contexts

This commit is contained in:
Catherine 2023-07-24 04:55:47 +00:00 committed by Catherine Flores
parent 8771282d4e
commit 287db04636
13 changed files with 209 additions and 26 deletions

View file

@ -2591,6 +2591,7 @@ 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 {
@ -2611,24 +2612,28 @@ 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) {
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(',', " |"),
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()),
],
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

@ -1,8 +1,8 @@
use crate::errors;
use super::diagnostics::{dummy_arg, ConsumeClosingDelim};
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken};
use crate::errors::{self, MacroExpandsToAdtField};
use crate::fluent_generated as fluent;
use ast::StaticItem;
use rustc_ast::ast::*;
use rustc_ast::ptr::P;
@ -1342,6 +1342,13 @@ impl<'a> Parser<'a> {
}
let ident = this.parse_field_ident("enum", vlo)?;
if this.token == token::Not {
return this.unexpected().map_err(|mut err| {
err.note(fluent::parse_macro_expands_to_enum_variant);
err
});
}
let struct_def = if this.check(&token::OpenDelim(Delimiter::Brace)) {
// Parse a struct variant.
let (fields, recovered) =
@ -1369,7 +1376,7 @@ impl<'a> Parser<'a> {
Ok((Some(vr), TrailingToken::MaybeComma))
},
).map_err(|mut err|{
).map_err(|mut err| {
err.help("enum variants can be `Variant`, `Variant = <integer>`, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }`");
err
})
@ -1691,9 +1698,10 @@ impl<'a> Parser<'a> {
Ok(a_var)
}
fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> {
fn expect_field_ty_separator(&mut self, adt_ty: &str) -> PResult<'a, ()> {
if let Err(mut err) = self.expect(&token::Colon) {
let sm = self.sess.source_map();
let mac_invoc = self.token.kind == token::Not;
let eq_typo = self.token.kind == token::Eq && self.look_ahead(1, |t| t.is_path_start());
let semi_typo = self.token.kind == token::Semi
&& self.look_ahead(1, |t| {
@ -1705,7 +1713,9 @@ impl<'a> Parser<'a> {
_ => true,
}
});
if eq_typo || semi_typo {
if mac_invoc {
err.subdiagnostic(MacroExpandsToAdtField { adt_ty }).emit();
} else if eq_typo || semi_typo {
self.bump();
// Gracefully handle small typos.
err.span_suggestion_short(
@ -1713,8 +1723,8 @@ impl<'a> Parser<'a> {
"field names and their types are separated with `:`",
":",
Applicability::MachineApplicable,
);
err.emit();
)
.emit();
} else {
return Err(err);
}
@ -1731,7 +1741,7 @@ impl<'a> Parser<'a> {
attrs: AttrVec,
) -> PResult<'a, FieldDef> {
let name = self.parse_field_ident(adt_ty, lo)?;
self.expect_field_ty_separator()?;
self.expect_field_ty_separator(adt_ty)?;
let ty = self.parse_ty()?;
if self.token.kind == token::Colon && self.look_ahead(1, |tok| tok.kind != token::Colon) {
self.sess.emit_err(errors::SingleColonStructType { span: self.token.span });

View file

@ -135,7 +135,11 @@ impl<'a> Parser<'a> {
// Parse the first pattern (`p_0`).
let mut first_pat = self.parse_pat_no_top_alt(expected)?;
if rc == RecoverComma::Yes {
self.maybe_recover_unexpected_comma(first_pat.span, rt)?;
self.maybe_recover_unexpected_comma(
first_pat.span,
matches!(first_pat.kind, PatKind::MacCall(_)),
rt,
)?;
}
// If the next token is not a `|`,
@ -177,7 +181,11 @@ impl<'a> Parser<'a> {
err
})?;
if rc == RecoverComma::Yes {
self.maybe_recover_unexpected_comma(pat.span, rt)?;
self.maybe_recover_unexpected_comma(
pat.span,
matches!(pat.kind, PatKind::MacCall(_)),
rt,
)?;
}
pats.push(pat);
}