diff options
| author | Pavel Grigorenko <GrigorenkoPV@ya.ru> | 2024-09-23 02:12:53 +0300 |
|---|---|---|
| committer | Pavel Grigorenko <GrigorenkoPV@ya.ru> | 2024-09-23 02:12:53 +0300 |
| commit | 9cd668beed38a8e98933733854a224c70998bf16 (patch) | |
| tree | 0ac8ea5f3c8b8839224855bac9725e19c323137f /compiler/rustc_parse/src | |
| parent | 8ed95d1d9e149b5242316c91b3849c58f8320470 (diff) | |
| download | rust-9cd668beed38a8e98933733854a224c70998bf16.tar.gz rust-9cd668beed38a8e98933733854a224c70998bf16.zip | |
Parser: better error messages for `@` in struct patterns
Diffstat (limited to 'compiler/rustc_parse/src')
| -rw-r--r-- | compiler/rustc_parse/src/errors.rs | 19 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/pat.rs | 54 |
2 files changed, 60 insertions, 13 deletions
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index e9fe2e6c1dd..e16ab5b4b06 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2584,6 +2584,25 @@ pub(crate) struct EnumPatternInsteadOfIdentifier { } #[derive(Diagnostic)] +#[diag(parse_at_dot_dot_in_struct_pattern)] +pub(crate) struct AtDotDotInStructPattern { + #[primary_span] + pub span: Span, + #[suggestion(code = "", style = "verbose", applicability = "machine-applicable")] + pub remove: Span, + pub ident: Ident, +} + +#[derive(Diagnostic)] +#[diag(parse_at_in_struct_pattern)] +#[note] +#[help] +pub(crate) struct AtInStructPattern { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] #[diag(parse_dot_dot_dot_for_remaining_fields)] pub(crate) struct DotDotDotForRemainingFields { #[primary_span] diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 647df25c82e..b4cbe1accf4 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -17,15 +17,16 @@ use thin_vec::{thin_vec, ThinVec}; use super::{ForceCollect, Parser, PathStyle, Restrictions, Trailing, UsePreAttrPos}; use crate::errors::{ - self, AmbiguousRangePattern, DotDotDotForRemainingFields, DotDotDotRangeToPatternNotAllowed, - DotDotDotRestPattern, EnumPatternInsteadOfIdentifier, ExpectedBindingLeftOfAt, - ExpectedCommaAfterPatternField, GenericArgsInPatRequireTurbofishSyntax, - InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, InclusiveRangeNoEnd, InvalidMutInPattern, - ParenRangeSuggestion, PatternOnWrongSideOfAt, RemoveLet, RepeatedMutInPattern, - SwitchRefBoxOrder, TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg, - TrailingVertNotAllowed, UnexpectedExpressionInPattern, UnexpectedExpressionInPatternSugg, - UnexpectedLifetimeInPattern, UnexpectedParenInRangePat, UnexpectedParenInRangePatSugg, - UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern, WrapInParens, + self, AmbiguousRangePattern, AtDotDotInStructPattern, AtInStructPattern, + DotDotDotForRemainingFields, DotDotDotRangeToPatternNotAllowed, DotDotDotRestPattern, + EnumPatternInsteadOfIdentifier, ExpectedBindingLeftOfAt, ExpectedCommaAfterPatternField, + GenericArgsInPatRequireTurbofishSyntax, InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, + InclusiveRangeNoEnd, InvalidMutInPattern, ParenRangeSuggestion, PatternOnWrongSideOfAt, + RemoveLet, RepeatedMutInPattern, SwitchRefBoxOrder, TopLevelOrPatternNotAllowed, + TopLevelOrPatternNotAllowedSugg, TrailingVertNotAllowed, UnexpectedExpressionInPattern, + UnexpectedExpressionInPatternSugg, UnexpectedLifetimeInPattern, UnexpectedParenInRangePat, + UnexpectedParenInRangePatSugg, UnexpectedVertVertBeforeFunctionParam, + UnexpectedVertVertInPattern, WrapInParens, }; use crate::parser::expr::{could_be_unclosed_char_literal, DestructuredFloat}; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; @@ -1433,7 +1434,7 @@ impl<'a> Parser<'a> { /// Parses the fields of a struct-like pattern. fn parse_pat_fields(&mut self) -> PResult<'a, (ThinVec<PatField>, PatFieldsRest)> { - let mut fields = ThinVec::new(); + let mut fields: ThinVec<PatField> = ThinVec::new(); let mut etc = PatFieldsRest::None; let mut ate_comma = true; let mut delayed_err: Option<Diag<'a>> = None; @@ -1454,12 +1455,22 @@ impl<'a> Parser<'a> { // check that a comma comes after every field if !ate_comma { - let mut err = - self.dcx().create_err(ExpectedCommaAfterPatternField { span: self.token.span }); + let err = if self.token == token::At { + let prev_field = fields + .last() + .expect("Unreachable on first iteration, not empty otherwise") + .ident; + self.report_misplaced_at_in_struct_pat(prev_field) + } else { + let mut err = self + .dcx() + .create_err(ExpectedCommaAfterPatternField { span: self.token.span }); + self.recover_misplaced_pattern_modifiers(&fields, &mut err); + err + }; if let Some(delayed) = delayed_err { delayed.emit(); } - self.recover_misplaced_pattern_modifiers(&fields, &mut err); return Err(err); } ate_comma = false; @@ -1594,6 +1605,23 @@ impl<'a> Parser<'a> { Ok((fields, etc)) } + #[deny(rustc::untranslatable_diagnostic)] + fn report_misplaced_at_in_struct_pat(&self, prev_field: Ident) -> Diag<'a> { + debug_assert_eq!(self.token, token::At); + let span = prev_field.span.to(self.token.span); + if let Some(dot_dot_span) = + self.look_ahead(1, |t| if t == &token::DotDot { Some(t.span) } else { None }) + { + self.dcx().create_err(AtDotDotInStructPattern { + span: span.to(dot_dot_span), + remove: span.until(dot_dot_span), + ident: prev_field, + }) + } else { + self.dcx().create_err(AtInStructPattern { span: span }) + } + } + /// If the user writes `S { ref field: name }` instead of `S { field: ref name }`, we suggest /// the correct code. fn recover_misplaced_pattern_modifiers(&self, fields: &ThinVec<PatField>, err: &mut Diag<'a>) { |
