mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Rollup merge of #48338 - estebank:match-missing-comma, r=petrochenkov
Fixes #47311. r? @nrc
This commit is contained in:
commit
8c7c8fb212
@ -652,9 +652,11 @@ impl<'a> Parser<'a> {
|
||||
} else {
|
||||
let token_str = Parser::token_to_string(t);
|
||||
let this_token_str = self.this_token_to_string();
|
||||
Err(self.fatal(&format!("expected `{}`, found `{}`",
|
||||
token_str,
|
||||
this_token_str)))
|
||||
let mut err = self.fatal(&format!("expected `{}`, found `{}`",
|
||||
token_str,
|
||||
this_token_str));
|
||||
err.span_label(self.span, format!("expected `{}`", token_str));
|
||||
Err(err)
|
||||
}
|
||||
} else {
|
||||
self.expect_one_of(unsafe { slice::from_raw_parts(t, 1) }, &[])
|
||||
@ -1172,7 +1174,7 @@ impl<'a> Parser<'a> {
|
||||
sep: SeqSep,
|
||||
f: F)
|
||||
-> PResult<'a, Vec<T>> where
|
||||
F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
|
||||
F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
|
||||
{
|
||||
self.expect(bra)?;
|
||||
let result = self.parse_seq_to_before_end(ket, sep, f)?;
|
||||
@ -1190,7 +1192,7 @@ impl<'a> Parser<'a> {
|
||||
sep: SeqSep,
|
||||
f: F)
|
||||
-> PResult<'a, Spanned<Vec<T>>> where
|
||||
F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
|
||||
F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
|
||||
{
|
||||
let lo = self.span;
|
||||
self.expect(bra)?;
|
||||
@ -1485,7 +1487,10 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
_ => {
|
||||
let token_str = self.this_token_to_string();
|
||||
return Err(self.fatal(&format!("expected `;` or `{{`, found `{}`", token_str)));
|
||||
let mut err = self.fatal(&format!("expected `;` or `{{`, found `{}`",
|
||||
token_str));
|
||||
err.span_label(self.span, "expected `;` or `{`");
|
||||
return Err(err);
|
||||
}
|
||||
};
|
||||
(ident, ast::TraitItemKind::Method(sig, body), generics)
|
||||
@ -2216,7 +2221,12 @@ impl<'a> Parser<'a> {
|
||||
TokenTree::Delimited(_, delimited) => Ok((delim, delimited.stream().into())),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
_ => Err(self.fatal("expected open delimiter")),
|
||||
_ => {
|
||||
let msg = "expected open delimiter";
|
||||
let mut err = self.fatal(msg);
|
||||
err.span_label(self.span, msg);
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2349,7 +2359,10 @@ impl<'a> Parser<'a> {
|
||||
if self.eat_keyword(keywords::Loop) {
|
||||
return self.parse_loop_expr(Some(label), lo, attrs)
|
||||
}
|
||||
return Err(self.fatal("expected `while`, `for`, or `loop` after a label"))
|
||||
let msg = "expected `while`, `for`, or `loop` after a label";
|
||||
let mut err = self.fatal(msg);
|
||||
err.span_label(self.span, msg);
|
||||
return Err(err);
|
||||
}
|
||||
if self.eat_keyword(keywords::Loop) {
|
||||
let lo = self.prev_span;
|
||||
@ -2408,6 +2421,7 @@ impl<'a> Parser<'a> {
|
||||
// Catch this syntax error here, instead of in `parse_ident`, so
|
||||
// that we can explicitly mention that let is not to be used as an expression
|
||||
let mut db = self.fatal("expected expression, found statement (`let`)");
|
||||
db.span_label(self.span, "expected expression");
|
||||
db.note("variable declaration using `let` is a statement");
|
||||
return Err(db);
|
||||
} else if self.token.is_path_start() {
|
||||
@ -2443,7 +2457,9 @@ impl<'a> Parser<'a> {
|
||||
self.cancel(&mut err);
|
||||
let msg = format!("expected expression, found {}",
|
||||
self.this_token_descr());
|
||||
return Err(self.fatal(&msg));
|
||||
let mut err = self.fatal(&msg);
|
||||
err.span_label(self.span, "expected expression");
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2733,7 +2749,9 @@ impl<'a> Parser<'a> {
|
||||
self.look_ahead(1, |t| t.is_ident()) => {
|
||||
self.bump();
|
||||
let name = match self.token { token::Ident(ident) => ident, _ => unreachable!() };
|
||||
self.fatal(&format!("unknown macro variable `{}`", name)).emit();
|
||||
let mut err = self.fatal(&format!("unknown macro variable `{}`", name));
|
||||
err.span_label(self.span, "unknown macro variable");
|
||||
err.emit();
|
||||
return
|
||||
}
|
||||
token::Interpolated(ref nt) => {
|
||||
@ -3212,7 +3230,13 @@ impl<'a> Parser<'a> {
|
||||
err.span_label(sp, "expected if condition here");
|
||||
return Err(err)
|
||||
}
|
||||
let thn = self.parse_block()?;
|
||||
let not_block = self.token != token::OpenDelim(token::Brace);
|
||||
let thn = self.parse_block().map_err(|mut err| {
|
||||
if not_block {
|
||||
err.span_label(lo, "this `if` statement has a condition, but no block");
|
||||
}
|
||||
err
|
||||
})?;
|
||||
let mut els: Option<P<Expr>> = None;
|
||||
let mut hi = thn.span;
|
||||
if self.eat_keyword(keywords::Else) {
|
||||
@ -3404,14 +3428,52 @@ 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| {
|
||||
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.span_label(arrow_span,
|
||||
"while parsing the `match` arm starting here");
|
||||
}
|
||||
}
|
||||
err
|
||||
})?;
|
||||
} else {
|
||||
self.eat(&token::Comma);
|
||||
}
|
||||
@ -3609,8 +3671,9 @@ impl<'a> Parser<'a> {
|
||||
self.bump();
|
||||
if self.token != token::CloseDelim(token::Brace) {
|
||||
let token_str = self.this_token_to_string();
|
||||
return Err(self.fatal(&format!("expected `{}`, found `{}`", "}",
|
||||
token_str)))
|
||||
let mut err = self.fatal(&format!("expected `{}`, found `{}`", "}", token_str));
|
||||
err.span_label(self.span, "expected `}`");
|
||||
return Err(err);
|
||||
}
|
||||
etc = true;
|
||||
break;
|
||||
@ -3721,7 +3784,10 @@ impl<'a> Parser<'a> {
|
||||
self.expect_and()?;
|
||||
let mutbl = self.parse_mutability();
|
||||
if let token::Lifetime(ident) = self.token {
|
||||
return Err(self.fatal(&format!("unexpected lifetime `{}` in pattern", ident)));
|
||||
let mut err = self.fatal(&format!("unexpected lifetime `{}` in pattern",
|
||||
ident));
|
||||
err.span_label(self.span, "unexpected lifetime");
|
||||
return Err(err);
|
||||
}
|
||||
let subpat = self.parse_pat()?;
|
||||
pat = PatKind::Ref(subpat, mutbl);
|
||||
@ -3806,7 +3872,10 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
token::OpenDelim(token::Brace) => {
|
||||
if qself.is_some() {
|
||||
return Err(self.fatal("unexpected `{` after qualified path"));
|
||||
let msg = "unexpected `{` after qualified path";
|
||||
let mut err = self.fatal(msg);
|
||||
err.span_label(self.span, msg);
|
||||
return Err(err);
|
||||
}
|
||||
// Parse struct pattern
|
||||
self.bump();
|
||||
@ -3820,7 +3889,10 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
token::OpenDelim(token::Paren) => {
|
||||
if qself.is_some() {
|
||||
return Err(self.fatal("unexpected `(` after qualified path"));
|
||||
let msg = "unexpected `(` after qualified path";
|
||||
let mut err = self.fatal(msg);
|
||||
err.span_label(self.span, msg);
|
||||
return Err(err);
|
||||
}
|
||||
// Parse tuple struct or enum pattern
|
||||
let (fields, ddpos, _) = self.parse_parenthesized_pat_list()?;
|
||||
@ -3850,7 +3922,9 @@ impl<'a> Parser<'a> {
|
||||
Err(mut err) => {
|
||||
self.cancel(&mut err);
|
||||
let msg = format!("expected pattern, found {}", self.this_token_descr());
|
||||
return Err(self.fatal(&msg));
|
||||
let mut err = self.fatal(&msg);
|
||||
err.span_label(self.span, "expected pattern");
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4250,9 +4324,11 @@ impl<'a> Parser<'a> {
|
||||
""
|
||||
};
|
||||
let tok_str = self.this_token_to_string();
|
||||
return Err(self.fatal(&format!("expected {}`(` or `{{`, found `{}`",
|
||||
ident_str,
|
||||
tok_str)))
|
||||
let mut err = self.fatal(&format!("expected {}`(` or `{{`, found `{}`",
|
||||
ident_str,
|
||||
tok_str));
|
||||
err.span_label(self.span, format!("expected {}`(` or `{{`", ident_str));
|
||||
return Err(err)
|
||||
},
|
||||
};
|
||||
|
||||
@ -5559,8 +5635,12 @@ impl<'a> Parser<'a> {
|
||||
body
|
||||
} else {
|
||||
let token_str = self.this_token_to_string();
|
||||
return Err(self.fatal(&format!("expected `where`, `{{`, `(`, or `;` after struct \
|
||||
name, found `{}`", token_str)))
|
||||
let mut err = self.fatal(&format!(
|
||||
"expected `where`, `{{`, `(`, or `;` after struct name, found `{}`",
|
||||
token_str
|
||||
));
|
||||
err.span_label(self.span, "expected `where`, `{`, `(`, or `;` after struct name");
|
||||
return Err(err);
|
||||
};
|
||||
|
||||
Ok((class_name, ItemKind::Struct(vdata, generics), None))
|
||||
@ -5579,8 +5659,10 @@ impl<'a> Parser<'a> {
|
||||
VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID)
|
||||
} else {
|
||||
let token_str = self.this_token_to_string();
|
||||
return Err(self.fatal(&format!("expected `where` or `{{` after union \
|
||||
name, found `{}`", token_str)))
|
||||
let mut err = self.fatal(&format!(
|
||||
"expected `where` or `{{` after union name, found `{}`", token_str));
|
||||
err.span_label(self.span, "expected `where` or `{` after union name");
|
||||
return Err(err);
|
||||
};
|
||||
|
||||
Ok((class_name, ItemKind::Union(vdata, generics), None))
|
||||
@ -5627,9 +5709,10 @@ impl<'a> Parser<'a> {
|
||||
self.eat(&token::CloseDelim(token::Brace));
|
||||
} else {
|
||||
let token_str = self.this_token_to_string();
|
||||
return Err(self.fatal(&format!("expected `where`, or `{{` after struct \
|
||||
name, found `{}`",
|
||||
token_str)));
|
||||
let mut err = self.fatal(&format!(
|
||||
"expected `where`, or `{{` after struct name, found `{}`", token_str));
|
||||
err.span_label(self.span, "expected `where`, or `{` after struct name");
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
Ok(fields)
|
||||
@ -5802,9 +5885,11 @@ impl<'a> Parser<'a> {
|
||||
if !self.eat(term) {
|
||||
let token_str = self.this_token_to_string();
|
||||
let mut err = self.fatal(&format!("expected item, found `{}`", token_str));
|
||||
let msg = "consider removing this semicolon";
|
||||
if token_str == ";" {
|
||||
let msg = "consider removing this semicolon";
|
||||
err.span_suggestion_short(self.span, msg, "".to_string());
|
||||
} else {
|
||||
err.span_label(self.span, "expected item");
|
||||
}
|
||||
return Err(err);
|
||||
}
|
||||
@ -6961,7 +7046,12 @@ impl<'a> Parser<'a> {
|
||||
self.expect_no_suffix(sp, "string literal", suf);
|
||||
Ok((s, style))
|
||||
}
|
||||
_ => Err(self.fatal("expected string literal"))
|
||||
_ => {
|
||||
let msg = "expected string literal";
|
||||
let mut err = self.fatal(msg);
|
||||
err.span_label(self.span, msg);
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ error: expected expression, found `_`
|
||||
--> $DIR/underscore.rs:18:9
|
||||
|
|
||||
LL | _
|
||||
| ^
|
||||
| ^ expected expression
|
||||
|
|
||||
::: $DIR/main.rs:15:5
|
||||
|
|
||||
|
@ -19,7 +19,7 @@ error: expected `[`, found `#`
|
||||
--> $DIR/issue-40006.rs:20:17
|
||||
|
|
||||
LL | fn xxx() { ### } //~ ERROR missing
|
||||
| ^
|
||||
| ^ expected `[`
|
||||
|
||||
error: missing `fn`, `type`, or `const` for trait-item declaration
|
||||
--> $DIR/issue-40006.rs:20:21
|
||||
|
18
src/test/ui/if-without-block.rs
Normal file
18
src/test/ui/if-without-block.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn main() {
|
||||
let n = 1;
|
||||
if 5 == {
|
||||
//~^ NOTE this `if` statement has a condition, but no block
|
||||
println!("five");
|
||||
}
|
||||
}
|
||||
//~^ ERROR expected `{`, found `}`
|
11
src/test/ui/if-without-block.stderr
Normal file
11
src/test/ui/if-without-block.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error: expected `{`, found `}`
|
||||
--> $DIR/if-without-block.rs:17:1
|
||||
|
|
||||
LL | if 5 == {
|
||||
| -- this `if` statement has a condition, but no block
|
||||
...
|
||||
LL | }
|
||||
| ^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -38,7 +38,7 @@ error: expected expression, found reserved keyword `typeof`
|
||||
--> $DIR/macro-context.rs:13:17
|
||||
|
|
||||
LL | () => ( i ; typeof ); //~ ERROR expected expression, found reserved keyword `typeof`
|
||||
| ^^^^^^
|
||||
| ^^^^^^ expected expression
|
||||
...
|
||||
LL | m!();
|
||||
| ----- in this macro invocation
|
||||
|
@ -2,11 +2,15 @@ error: expected `{`, found `=>`
|
||||
--> $DIR/missing-block-hint.rs:13:18
|
||||
|
|
||||
LL | if (foo) => {} //~ ERROR expected `{`, found `=>`
|
||||
| ^^
|
||||
| -- ^^
|
||||
| |
|
||||
| this `if` statement has a condition, but no block
|
||||
|
||||
error: expected `{`, found `bar`
|
||||
--> $DIR/missing-block-hint.rs:17:13
|
||||
|
|
||||
LL | if (foo)
|
||||
| -- this `if` statement has a condition, but no block
|
||||
LL | bar; //~ ERROR expected `{`, found `bar`
|
||||
| ^^^-
|
||||
| |
|
||||
|
@ -26,7 +26,7 @@ error: expected expression, found `;`
|
||||
--> $DIR/token-error-correct.rs:14:13
|
||||
|
|
||||
LL | foo(bar(;
|
||||
| ^
|
||||
| ^ expected expression
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
19
src/test/ui/suggestions/missing-comma-in-match.rs
Normal file
19
src/test/ui/suggestions/missing-comma-in-match.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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
|
||||
_ => 2
|
||||
};
|
||||
}
|
10
src/test/ui/suggestions/missing-comma-in-match.stderr
Normal file
10
src/test/ui/suggestions/missing-comma-in-match.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error: expected one of `,`, `.`, `?`, `}`, or an operator, found `=>`
|
||||
--> $DIR/missing-comma-in-match.rs:14:18
|
||||
|
|
||||
LL | &None => 1
|
||||
| - help: missing a comma here to end this `match` arm
|
||||
LL | &Some(2) => { 3 }
|
||||
| ^^ expected one of `,`, `.`, `?`, `}`, or an operator here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -20,7 +20,7 @@ error: expected expression, found `)`
|
||||
--> $DIR/issue-10636-2.rs:18:1
|
||||
|
|
||||
LL | } //~ ERROR: incorrect close delimiter
|
||||
| ^
|
||||
| ^ expected expression
|
||||
|
||||
error[E0601]: main function not found
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user