From b13eb61a2cdfac1e094c2a4d608086f40cea5e01 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 7 Jun 2022 02:19:18 -0700 Subject: [PATCH] Recover missing comma after match arm --- compiler/rustc_parse/src/parser/expr.rs | 51 ++++++++++++++----- .../ui/parser/match-arm-without-braces.rs | 6 +-- .../ui/parser/match-arm-without-braces.stderr | 10 ++-- 3 files changed, 44 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index b786c52e688..324e04b1981 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2718,13 +2718,12 @@ fn check_let_expr(expr: &Expr) -> (bool, bool) { )); } this.expect_one_of(&[token::Comma], &[token::CloseDelim(Delimiter::Brace)]) - .map_err(|mut err| { - match (sm.span_to_lines(expr.span), sm.span_to_lines(arm_start_span)) { - (Ok(ref expr_lines), Ok(ref arm_start_lines)) - if arm_start_lines.lines[0].end_col - == expr_lines.lines[0].end_col - && expr_lines.lines.len() == 2 - && this.token == token::FatArrow => + .or_else(|mut err| { + if this.token == token::FatArrow { + if let Ok(expr_lines) = sm.span_to_lines(expr.span) + && let Ok(arm_start_lines) = sm.span_to_lines(arm_start_span) + && arm_start_lines.lines[0].end_col == expr_lines.lines[0].end_col + && expr_lines.lines.len() == 2 { // We check whether there's any trailing code in the parse span, // if there isn't, we very likely have the following: @@ -2743,15 +2742,41 @@ fn check_let_expr(expr: &Expr) -> (bool, bool) { ",".to_owned(), Applicability::MachineApplicable, ); + return Err(err); } - _ => { - err.span_label( - arrow_span, - "while parsing the `match` arm starting here", - ); + } else { + // FIXME(compiler-errors): We could also recover `; PAT =>` here + + // Try to parse a following `PAT =>`, if successful + // then we should recover. + let mut snapshot = this.create_snapshot_for_diagnostic(); + let pattern_follows = snapshot + .parse_pat_allow_top_alt( + None, + RecoverComma::Yes, + RecoverColon::Yes, + CommaRecoveryMode::EitherTupleOrPipe, + ) + .map_err(|err| err.cancel()) + .is_ok(); + if pattern_follows && snapshot.check(&TokenKind::FatArrow) { + err.cancel(); + this.struct_span_err( + hi.shrink_to_hi(), + "expected `,` following `match` arm", + ) + .span_suggestion( + hi.shrink_to_hi(), + "missing a comma here to end this `match` arm", + ",".to_owned(), + Applicability::MachineApplicable, + ) + .emit(); + return Ok(true); } } - err + err.span_label(arrow_span, "while parsing the `match` arm starting here"); + Err(err) })?; } else { this.eat(&token::Comma); diff --git a/src/test/ui/parser/match-arm-without-braces.rs b/src/test/ui/parser/match-arm-without-braces.rs index 55a88742769..bba38fd0fa4 100644 --- a/src/test/ui/parser/match-arm-without-braces.rs +++ b/src/test/ui/parser/match-arm-without-braces.rs @@ -45,9 +45,9 @@ fn main() { 15; } match S::get(16) { - Some(Val::Foo) => 17 - _ => 18, //~ ERROR expected one of - } + Some(Val::Foo) => 17 //~ ERROR expected `,` following `match` arm + _ => 18, + }; match S::get(19) { Some(Val::Foo) => 20; //~ ERROR `match` arm body without braces diff --git a/src/test/ui/parser/match-arm-without-braces.stderr b/src/test/ui/parser/match-arm-without-braces.stderr index 4831d79ef2b..37d55aa53f8 100644 --- a/src/test/ui/parser/match-arm-without-braces.stderr +++ b/src/test/ui/parser/match-arm-without-braces.stderr @@ -52,15 +52,11 @@ LL ~ { 14; LL ~ 15; } | -error: expected one of `,`, `.`, `?`, `}`, or an operator, found reserved identifier `_` - --> $DIR/match-arm-without-braces.rs:49:9 +error: expected `,` following `match` arm + --> $DIR/match-arm-without-braces.rs:48:29 | LL | Some(Val::Foo) => 17 - | -- - expected one of `,`, `.`, `?`, `}`, or an operator - | | - | while parsing the `match` arm starting here -LL | _ => 18, - | ^ unexpected token + | ^ help: missing a comma here to end this `match` arm: `,` error: `match` arm body without braces --> $DIR/match-arm-without-braces.rs:53:11 -- 2.44.0