diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 09dd00fa5fa..2046bbfa713 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3404,14 +3404,48 @@ impl<'a> Parser<'a> { } else { None }; + let arrow_span = self.span; self.expect(&token::FatArrow)?; - let expr = self.parse_expr_res(Restrictions::STMT_EXPR, None)?; + let arm_start_span = self.span; + + let expr = self.parse_expr_res(Restrictions::STMT_EXPR, None) + .map_err(|mut err| { + err.span_label(arrow_span, "while parsing the match arm starting here"); + err + })?; let require_comma = classify::expr_requires_semi_to_be_stmt(&expr) && self.token != token::CloseDelim(token::Brace); if require_comma { - self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Brace)])?; + let cm = self.sess.codemap(); + self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Brace)]) + .map_err(|mut err| { + err.span_label(arrow_span, "while parsing the match arm starting here"); + match (cm.span_to_lines(expr.span), cm.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 + && self.token == token::FatArrow => { + // We check wether there's any trailing code in the parse span, if there + // isn't, we very likely have the following: + // + // X | &Y => "y" + // | -- - missing comma + // | | + // | arrow_span + // X | &X => "x" + // | - ^^ self.span + // | | + // | parsed until here as `"y" & X` + err.span_suggestion_short(cm.next_point(arm_start_span), + "missing a comma here to end this match arm", + ",".to_owned()); + } + _ => {} + } + err + })?; } else { self.eat(&token::Comma); } diff --git a/src/test/ui/suggestions/missing-comma-in-match.rs b/src/test/ui/suggestions/missing-comma-in-match.rs new file mode 100644 index 00000000000..e02a8df3343 --- /dev/null +++ b/src/test/ui/suggestions/missing-comma-in-match.rs @@ -0,0 +1,20 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + match &Some(3) { + &None => 1 + &Some(2) => { 3 } + //~^ ERROR expected one of `,`, `.`, `?`, `}`, or an operator, found `=>` + //~| NOTE expected one of `,`, `.`, `?`, `}`, or an operator here + //~^^^^ NOTE while parsing the match arm starting here + _ => 2 + }; +} diff --git a/src/test/ui/suggestions/missing-comma-in-match.stderr b/src/test/ui/suggestions/missing-comma-in-match.stderr new file mode 100644 index 00000000000..864fde49a5e --- /dev/null +++ b/src/test/ui/suggestions/missing-comma-in-match.stderr @@ -0,0 +1,12 @@ +error: expected one of `,`, `.`, `?`, `}`, or an operator, found `=>` + --> $DIR/missing-comma-in-match.rs:14:18 + | +13 | &None => 1 + | -- - help: missing a comma here to end this match arm + | | + | while parsing the match arm starting here +14 | &Some(2) => { 3 } + | ^^ expected one of `,`, `.`, `?`, `}`, or an operator here + +error: aborting due to previous error +