diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index a0c3fe35608..ea0c7e0e366 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -2637,7 +2637,15 @@ impl<'a> Parser<'a> {
let mut trailing_comma = false;
let mut recovered = false;
while self.token != token::CloseDelim(token::Paren) {
- es.push(self.parse_expr()?);
+ es.push(match self.parse_expr() {
+ Ok(es) => es,
+ Err(mut err) => { // recover from parse error in tuple list
+ err.emit();
+ self.consume_block(token::Paren);
+ hi = self.prev_span;
+ return Ok(self.mk_expr(lo.to(hi), ExprKind::Err, ThinVec::new()));
+ }
+ });
recovered = self.expect_one_of(
&[],
&[token::Comma, token::CloseDelim(token::Paren)],
@@ -3248,16 +3256,24 @@ impl<'a> Parser<'a> {
match self.token {
// expr(...)
token::OpenDelim(token::Paren) => {
- let es = self.parse_unspanned_seq(
+ match self.parse_unspanned_seq(
&token::OpenDelim(token::Paren),
&token::CloseDelim(token::Paren),
SeqSep::trailing_allowed(token::Comma),
|p| Ok(p.parse_expr()?)
- )?;
- hi = self.prev_span;
-
- let nd = self.mk_call(e, es);
- e = self.mk_expr(lo.to(hi), nd, ThinVec::new());
+ ) {
+ Ok(es) => {
+ let nd = self.mk_call(e, es);
+ hi = self.prev_span;
+ e = self.mk_expr(lo.to(hi), nd, ThinVec::new());
+ }
+ Err(mut err) => { // recover from parse error in argument list
+ err.emit();
+ self.consume_block(token::Paren);
+ hi = self.prev_span;
+ e = self.mk_expr(lo.to(hi), ExprKind::Err, ThinVec::new());
+ }
+ }
}
// expr[...]
@@ -4262,7 +4278,14 @@ impl<'a> Parser<'a> {
// Trailing commas are significant because (p) and (p,) are different patterns.
fn parse_parenthesized_pat_list(&mut self) -> PResult<'a, (Vec
>, Option, bool)> {
self.expect(&token::OpenDelim(token::Paren))?;
- let result = self.parse_pat_list()?;
+ let result = match self.parse_pat_list() {
+ Ok(result) => result,
+ Err(mut err) => { // recover from parse error in tuple pattern list
+ err.emit();
+ self.consume_block(token::Paren);
+ return Ok((vec![], Some(0), false));
+ }
+ };
self.expect(&token::CloseDelim(token::Paren))?;
Ok(result)
}
diff --git a/src/test/ui/issues/issue-34334.rs b/src/test/ui/issues/issue-34334.rs
index 5c4f5c86a7f..928d217441e 100644
--- a/src/test/ui/issues/issue-34334.rs
+++ b/src/test/ui/issues/issue-34334.rs
@@ -1,4 +1,10 @@
fn main () {
- let sr: Vec<(u32, _, _) = vec![]; //~ ERROR expected one of `,` or `>`, found `=`
+ let sr: Vec<(u32, _, _) = vec![];
+ //~^ ERROR expected one of `,` or `>`, found `=`
+ //~| ERROR expected value, found struct `Vec`
+ //~| ERROR mismatched types
+ //~| ERROR invalid left-hand side expression
+ //~| ERROR expected expression, found reserved identifier `_`
let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
+ //~^ ERROR no method named `iter` found for type `()` in the current scope
}
diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr
index 1b0babf9390..51ea0c6a908 100644
--- a/src/test/ui/issues/issue-34334.stderr
+++ b/src/test/ui/issues/issue-34334.stderr
@@ -1,10 +1,47 @@
+error: expected expression, found reserved identifier `_`
+ --> $DIR/issue-34334.rs:2:23
+ |
+LL | let sr: Vec<(u32, _, _) = vec![];
+ | ^ expected expression
+
error: expected one of `,` or `>`, found `=`
--> $DIR/issue-34334.rs:2:29
|
LL | let sr: Vec<(u32, _, _) = vec![];
- | -- ^ expected one of `,` or `>` here
- | |
+ | --- ^ expected one of `,` or `>` here
+ | | |
+ | | help: use `=` if you meant to assign
| while parsing the type for `sr`
-error: aborting due to previous error
+error[E0423]: expected value, found struct `Vec`
+ --> $DIR/issue-34334.rs:2:13
+ |
+LL | let sr: Vec<(u32, _, _) = vec![];
+ | ^^^ did you mean `Vec { /* fields */ }`?
+error[E0308]: mismatched types
+ --> $DIR/issue-34334.rs:2:31
+ |
+LL | let sr: Vec<(u32, _, _) = vec![];
+ | ^^^^^^ expected bool, found struct `std::vec::Vec`
+ |
+ = note: expected type `bool`
+ found type `std::vec::Vec<_>`
+ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0070]: invalid left-hand side expression
+ --> $DIR/issue-34334.rs:2:13
+ |
+LL | let sr: Vec<(u32, _, _) = vec![];
+ | ^^^^^^^^^^^^^^^^^^^^^^^^ left-hand of expression not valid
+
+error[E0599]: no method named `iter` found for type `()` in the current scope
+ --> $DIR/issue-34334.rs:8:36
+ |
+LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
+ | ^^^^
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0070, E0308, E0423, E0599.
+For more information about an error, try `rustc --explain E0070`.
diff --git a/src/test/ui/parser/pat-tuple-1.rs b/src/test/ui/parser/pat-tuple-1.rs
index 213fbe371d4..d76096c2598 100644
--- a/src/test/ui/parser/pat-tuple-1.rs
+++ b/src/test/ui/parser/pat-tuple-1.rs
@@ -1,5 +1,6 @@
fn main() {
- match 0 {
- (, ..) => {} //~ ERROR expected pattern, found `,`
+ match (0, 1) {
+ (, ..) => {}
+ //~^ ERROR expected pattern, found `,`
}
}
diff --git a/src/test/ui/parser/pat-tuple-5.rs b/src/test/ui/parser/pat-tuple-5.rs
index 03176abaf49..d4f05a5eb52 100644
--- a/src/test/ui/parser/pat-tuple-5.rs
+++ b/src/test/ui/parser/pat-tuple-5.rs
@@ -1,5 +1,5 @@
fn main() {
- match 0 {
+ match (0, 1) {
(pat ..) => {} //~ ERROR unexpected token: `)`
}
}
diff --git a/src/test/ui/parser/recover-from-bad-variant.rs b/src/test/ui/parser/recover-from-bad-variant.rs
new file mode 100644
index 00000000000..35088fb3068
--- /dev/null
+++ b/src/test/ui/parser/recover-from-bad-variant.rs
@@ -0,0 +1,14 @@
+enum Enum {
+ Foo { a: usize, b: usize },
+ Bar(usize, usize),
+}
+
+fn main() {
+ let x = Enum::Foo(a: 3, b: 4);
+ //~^ ERROR expected type, found `3`
+ match x {
+ Enum::Foo(a, b) => {}
+ //~^ ERROR expected tuple struct/variant, found struct variant `Enum::Foo`
+ Enum::Bar(a, b) => {}
+ }
+}
diff --git a/src/test/ui/parser/recover-from-bad-variant.stderr b/src/test/ui/parser/recover-from-bad-variant.stderr
new file mode 100644
index 00000000000..bd4a562d72d
--- /dev/null
+++ b/src/test/ui/parser/recover-from-bad-variant.stderr
@@ -0,0 +1,15 @@
+error: expected type, found `3`
+ --> $DIR/recover-from-bad-variant.rs:7:26
+ |
+LL | let x = Enum::Foo(a: 3, b: 4);
+ | ^ expecting a type here because of type ascription
+
+error[E0532]: expected tuple struct/variant, found struct variant `Enum::Foo`
+ --> $DIR/recover-from-bad-variant.rs:10:9
+ |
+LL | Enum::Foo(a, b) => {}
+ | ^^^^^^^^^ did you mean `Enum::Foo { /* fields */ }`?
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0532`.
diff --git a/src/test/ui/parser/recover-tuple-pat.rs b/src/test/ui/parser/recover-tuple-pat.rs
new file mode 100644
index 00000000000..488e8db6b87
--- /dev/null
+++ b/src/test/ui/parser/recover-tuple-pat.rs
@@ -0,0 +1,12 @@
+fn main() {
+ let x = (1, 2, 3, 4);
+ match x {
+ (1, .., 4) => {}
+ (1, .=., 4) => { let _: usize = ""; }
+ //~^ ERROR expected pattern, found `.`
+ //~| ERROR mismatched types
+ (.=., 4) => {}
+ //~^ ERROR expected pattern, found `.`
+ (1, 2, 3, 4) => {}
+ }
+}
diff --git a/src/test/ui/parser/recover-tuple-pat.stderr b/src/test/ui/parser/recover-tuple-pat.stderr
new file mode 100644
index 00000000000..5919aa72355
--- /dev/null
+++ b/src/test/ui/parser/recover-tuple-pat.stderr
@@ -0,0 +1,24 @@
+error: expected pattern, found `.`
+ --> $DIR/recover-tuple-pat.rs:5:13
+ |
+LL | (1, .=., 4) => { let _: usize = ""; }
+ | ^ expected pattern
+
+error: expected pattern, found `.`
+ --> $DIR/recover-tuple-pat.rs:8:10
+ |
+LL | (.=., 4) => {}
+ | ^ expected pattern
+
+error[E0308]: mismatched types
+ --> $DIR/recover-tuple-pat.rs:5:41
+ |
+LL | (1, .=., 4) => { let _: usize = ""; }
+ | ^^ expected usize, found reference
+ |
+ = note: expected type `usize`
+ found type `&'static str`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/recover-tuple.rs b/src/test/ui/parser/recover-tuple.rs
new file mode 100644
index 00000000000..59e2695dec6
--- /dev/null
+++ b/src/test/ui/parser/recover-tuple.rs
@@ -0,0 +1,11 @@
+fn main() {
+ // no complaints about the tuple not matching the expected type
+ let x: (usize, usize, usize) = (3, .=.);
+ //~^ ERROR expected expression, found `.`
+ // verify that the parser recovers:
+ let y: usize = ""; //~ ERROR mismatched types
+ // no complaints about the type
+ foo(x);
+}
+
+fn foo(_: (usize, usize, usize)) {}
diff --git a/src/test/ui/parser/recover-tuple.stderr b/src/test/ui/parser/recover-tuple.stderr
new file mode 100644
index 00000000000..4252fc1fd1e
--- /dev/null
+++ b/src/test/ui/parser/recover-tuple.stderr
@@ -0,0 +1,18 @@
+error: expected expression, found `.`
+ --> $DIR/recover-tuple.rs:3:40
+ |
+LL | let x: (usize, usize, usize) = (3, .=.);
+ | ^ expected expression
+
+error[E0308]: mismatched types
+ --> $DIR/recover-tuple.rs:6:20
+ |
+LL | let y: usize = "";
+ | ^^ expected usize, found reference
+ |
+ = note: expected type `usize`
+ found type `&'static str`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/trait-object-lifetime-parens.rs b/src/test/ui/parser/trait-object-lifetime-parens.rs
index b188e14778b..43f6497f7e7 100644
--- a/src/test/ui/parser/trait-object-lifetime-parens.rs
+++ b/src/test/ui/parser/trait-object-lifetime-parens.rs
@@ -6,7 +6,10 @@ fn f<'a, T: Trait + ('a)>() {} //~ ERROR parenthesized lifetime bounds are not s
fn check<'a>() {
let _: Box; //~ ERROR parenthesized lifetime bounds are not supported
- let _: Box<('a) + Trait>; //~ ERROR expected type, found `'a`
+ let _: Box<('a) + Trait>;
+ //~^ ERROR expected type, found `'a`
+ //~| ERROR expected `:`, found `)`
+ //~| ERROR chained comparison operators require parentheses
}
fn main() {}
diff --git a/src/test/ui/parser/trait-object-lifetime-parens.stderr b/src/test/ui/parser/trait-object-lifetime-parens.stderr
index 084e6d5b11f..a31b7aea8fe 100644
--- a/src/test/ui/parser/trait-object-lifetime-parens.stderr
+++ b/src/test/ui/parser/trait-object-lifetime-parens.stderr
@@ -10,6 +10,21 @@ error: parenthesized lifetime bounds are not supported
LL | let _: Box;
| ^^^^ help: remove the parentheses
+error: expected `:`, found `)`
+ --> $DIR/trait-object-lifetime-parens.rs:9:19
+ |
+LL | let _: Box<('a) + Trait>;
+ | ^ expected `:`
+
+error: chained comparison operators require parentheses
+ --> $DIR/trait-object-lifetime-parens.rs:9:15
+ |
+LL | let _: Box<('a) + Trait>;
+ | ^^^^^^^^^^^^^^^
+ |
+ = help: use `::<...>` instead of `<...>` if you meant to specify type arguments
+ = help: or use `(...)` if you meant to specify fn arguments
+
error: expected type, found `'a`
--> $DIR/trait-object-lifetime-parens.rs:9:17
|
@@ -18,5 +33,5 @@ LL | let _: Box<('a) + Trait>;
| |
| while parsing the type for `_`
-error: aborting due to 3 previous errors
+error: aborting due to 5 previous errors