about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-03-30 07:51:36 +0100
committerGitHub <noreply@github.com>2019-03-30 07:51:36 +0100
commitc28704c2a89219dd84cefa042d4e809cafee8402 (patch)
tree7fd79aa52e375195c4dcb3d59ef5c3346733579a /src
parentd050a157a83d3957a2b0ca96c24a1f61809348a8 (diff)
parent3592079765d4d76f19b3a9501de5f8cc47f11a04 (diff)
downloadrust-c28704c2a89219dd84cefa042d4e809cafee8402.tar.gz
rust-c28704c2a89219dd84cefa042d4e809cafee8402.zip
Rollup merge of #59453 - estebank:recover-tuple-parse, r=petrochenkov
Recover from parse error in tuple syntax
Diffstat (limited to 'src')
-rw-r--r--src/libsyntax/parse/parser.rs83
-rw-r--r--src/test/ui/issues/issue-34334.rs8
-rw-r--r--src/test/ui/issues/issue-34334.stderr43
-rw-r--r--src/test/ui/parser/pat-tuple-1.rs2
-rw-r--r--src/test/ui/parser/pat-tuple-5.rs2
-rw-r--r--src/test/ui/parser/recover-from-bad-variant.rs14
-rw-r--r--src/test/ui/parser/recover-from-bad-variant.stderr23
-rw-r--r--src/test/ui/parser/recover-tuple-pat.rs12
-rw-r--r--src/test/ui/parser/recover-tuple-pat.stderr24
-rw-r--r--src/test/ui/parser/recover-tuple.rs11
-rw-r--r--src/test/ui/parser/recover-tuple.stderr18
-rw-r--r--src/test/ui/parser/trait-object-lifetime-parens.rs5
-rw-r--r--src/test/ui/parser/trait-object-lifetime-parens.stderr17
13 files changed, 228 insertions, 34 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 79c1f0cb4cc..ae8e57d54de 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -2626,7 +2626,13 @@ 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(err) => {
+                            // recover from parse error in tuple list
+                            return Ok(self.recover_seq_parse_error(token::Paren, lo, Err(err)));
+                        }
+                    });
                     recovered = self.expect_one_of(
                         &[],
                         &[token::Comma, token::CloseDelim(token::Paren)],
@@ -3237,36 +3243,54 @@ impl<'a> Parser<'a> {
             }
             if self.expr_is_complete(&e) { break; }
             match self.token {
-              // expr(...)
-              token::OpenDelim(token::Paren) => {
-                let es = 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());
-              }
+                // expr(...)
+                token::OpenDelim(token::Paren) => {
+                    let seq = self.parse_unspanned_seq(
+                        &token::OpenDelim(token::Paren),
+                        &token::CloseDelim(token::Paren),
+                        SeqSep::trailing_allowed(token::Comma),
+                        |p| Ok(p.parse_expr()?)
+                    ).map(|es| {
+                        let nd = self.mk_call(e, es);
+                        let hi = self.prev_span;
+                        self.mk_expr(lo.to(hi), nd, ThinVec::new())
+                    });
+                    e = self.recover_seq_parse_error(token::Paren, lo, seq);
+                }
 
-              // expr[...]
-              // Could be either an index expression or a slicing expression.
-              token::OpenDelim(token::Bracket) => {
-                self.bump();
-                let ix = self.parse_expr()?;
-                hi = self.span;
-                self.expect(&token::CloseDelim(token::Bracket))?;
-                let index = self.mk_index(e, ix);
-                e = self.mk_expr(lo.to(hi), index, ThinVec::new())
-              }
-              _ => return Ok(e)
+                // expr[...]
+                // Could be either an index expression or a slicing expression.
+                token::OpenDelim(token::Bracket) => {
+                    self.bump();
+                    let ix = self.parse_expr()?;
+                    hi = self.span;
+                    self.expect(&token::CloseDelim(token::Bracket))?;
+                    let index = self.mk_index(e, ix);
+                    e = self.mk_expr(lo.to(hi), index, ThinVec::new())
+                }
+                _ => return Ok(e)
             }
         }
         return Ok(e);
     }
 
+    fn recover_seq_parse_error(
+        &mut self,
+        delim: token::DelimToken,
+        lo: Span,
+        result: PResult<'a, P<Expr>>,
+    ) -> P<Expr> {
+        match result {
+            Ok(x) => x,
+            Err(mut err) => {
+                err.emit();
+                // recover from parse error
+                self.consume_block(delim);
+                self.mk_expr(lo.to(self.prev_span), ExprKind::Err, ThinVec::new())
+            }
+        }
+    }
+
     crate fn process_potential_macro_variable(&mut self) {
         let (token, span) = match self.token {
             token::Dollar if self.span.ctxt() != syntax_pos::hygiene::SyntaxContext::empty() &&
@@ -4253,7 +4277,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<P<Pat>>, Option<usize>, 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..0e49b547f7d 100644
--- a/src/test/ui/parser/pat-tuple-1.rs
+++ b/src/test/ui/parser/pat-tuple-1.rs
@@ -1,5 +1,5 @@
 fn main() {
-    match 0 {
+    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..1eba6d7d528
--- /dev/null
+++ b/src/test/ui/parser/recover-from-bad-variant.stderr
@@ -0,0 +1,23 @@
+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
+   |
+   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+note: this expression expects an ascribed type after the colon
+  --> $DIR/recover-from-bad-variant.rs:7:23
+   |
+LL |     let x = Enum::Foo(a: 3, b: 4);
+   |                       ^
+   = help: this might be indicative of a syntax error elsewhere
+
+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<Trait + ('a)>; //~ 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<Trait + ('a)>;
    |                        ^^^^ 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