diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index eadd2892d93ec..1c3c433d8b731 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -777,6 +777,9 @@ parse_unexpected_lifetime_in_pattern = unexpected lifetime `{$symbol}` in patter parse_unexpected_parentheses_in_for_head = unexpected parentheses surrounding `for` loop head .suggestion = remove parentheses in `for` loop +parse_unexpected_parentheses_in_match_arm_pattern = unexpected parentheses surrounding `match` arm pattern + .suggestion = remove parentheses surrounding the pattern + parse_unexpected_self_in_generic_parameters = unexpected keyword `Self` in generic parameters .note = you cannot use `Self` as a generic parameter because it is reserved for associated items diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index e5d4cb6f4da27..03e047b297dc5 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1275,12 +1275,28 @@ pub(crate) struct ParenthesesInForHead { #[derive(Subdiagnostic)] #[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] pub(crate) struct ParenthesesInForHeadSugg { - #[suggestion_part(code = "{left_snippet}")] + #[suggestion_part(code = " ")] + pub left: Span, + #[suggestion_part(code = " ")] + pub right: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_unexpected_parentheses_in_match_arm_pattern)] +pub(crate) struct ParenthesesInMatchPat { + #[primary_span] + pub span: Vec, + #[subdiagnostic] + pub sugg: ParenthesesInMatchPatSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")] +pub(crate) struct ParenthesesInMatchPatSugg { + #[suggestion_part(code = "")] pub left: Span, - pub left_snippet: String, - #[suggestion_part(code = "{right_snippet}")] + #[suggestion_part(code = "")] pub right: Span, - pub right_snippet: String, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index ecb840f067eb3..8921c1c6a03fd 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -11,12 +11,12 @@ use crate::errors::{ DoubleColonInBound, ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg, GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg, HelpIdentifierStartsWithNumber, InInTypo, IncorrectAwait, IncorrectSemicolon, - IncorrectUseOfAwait, ParenthesesInForHead, ParenthesesInForHeadSugg, - PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg, SelfParamNotFirst, - StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, StructLiteralNeedingParens, - StructLiteralNeedingParensSugg, SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma, - TernaryOperator, UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration, - UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, WrapType, + IncorrectUseOfAwait, PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg, + SelfParamNotFirst, StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, + StructLiteralNeedingParens, StructLiteralNeedingParensSugg, SuggAddMissingLetStmt, + SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator, UnexpectedConstInGenericParam, + UnexpectedConstParamDeclaration, UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, + UseEqInstead, WrapType, }; use crate::fluent_generated as fluent; @@ -1994,56 +1994,6 @@ impl<'a> Parser<'a> { } } - /// Recovers a situation like `for ( $pat in $expr )` - /// and suggest writing `for $pat in $expr` instead. - /// - /// This should be called before parsing the `$block`. - pub(super) fn recover_parens_around_for_head( - &mut self, - pat: P, - begin_paren: Option, - ) -> P { - match (&self.token.kind, begin_paren) { - (token::CloseDelim(Delimiter::Parenthesis), Some(begin_par_sp)) => { - self.bump(); - - let sm = self.sess.source_map(); - let left = begin_par_sp; - let right = self.prev_token.span; - let left_snippet = if let Ok(snip) = sm.span_to_prev_source(left) - && !snip.ends_with(' ') - { - " ".to_string() - } else { - "".to_string() - }; - - let right_snippet = if let Ok(snip) = sm.span_to_next_source(right) - && !snip.starts_with(' ') - { - " ".to_string() - } else { - "".to_string() - }; - - self.sess.emit_err(ParenthesesInForHead { - span: vec![left, right], - // With e.g. `for (x) in y)` this would replace `(x) in y)` - // with `x) in y)` which is syntactically invalid. - // However, this is prevented before we get here. - sugg: ParenthesesInForHeadSugg { left, right, left_snippet, right_snippet }, - }); - - // Unwrap `(pat)` into `pat` to avoid the `unused_parens` lint. - pat.and_then(|pat| match pat.kind { - PatKind::Paren(pat) => pat, - _ => P(pat), - }) - } - _ => pat, - } - } - pub(super) fn recover_seq_parse_error( &mut self, delim: Delimiter, diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e334837c1d41f..b1b77305e4fd9 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -10,7 +10,7 @@ use super::{ use crate::errors; use crate::maybe_recover_from_interpolated_ty_qpath; use ast::mut_visit::{noop_visit_expr, MutVisitor}; -use ast::{GenBlockKind, Path, PathSegment}; +use ast::{GenBlockKind, Pat, Path, PathSegment}; use core::mem; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; @@ -2609,30 +2609,72 @@ impl<'a> Parser<'a> { } } - /// Parses `for in ` (`for` token already eaten). - fn parse_expr_for(&mut self, opt_label: Option