From 45c1e381473b39e7fece2663638d09288370a821 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 13 Dec 2019 00:59:33 +0100 Subject: [PATCH] parser: recover on `&'lifetime mut $pat`. --- src/librustc_parse/parser/pat.rs | 24 +++++++++++++------ .../ui/parser/lifetime-in-pattern-recover.rs | 6 +++++ .../parser/lifetime-in-pattern-recover.stderr | 23 ++++++++++++++++++ src/test/ui/parser/lifetime-in-pattern.rs | 1 + src/test/ui/parser/lifetime-in-pattern.stderr | 10 ++++++-- .../ui/self/self-vs-path-ambiguity.stderr | 2 +- 6 files changed, 56 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/parser/lifetime-in-pattern-recover.rs create mode 100644 src/test/ui/parser/lifetime-in-pattern-recover.stderr diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs index 42ece96adb9..117b92dc9a5 100644 --- a/src/librustc_parse/parser/pat.rs +++ b/src/librustc_parse/parser/pat.rs @@ -459,18 +459,28 @@ impl<'a> Parser<'a> { /// Parse `&pat` / `&mut pat`. fn parse_pat_deref(&mut self, expected: Expected) -> PResult<'a, PatKind> { self.expect_and()?; + self.recover_lifetime_in_deref_pat(); let mutbl = self.parse_mutability(); - - if let token::Lifetime(name) = self.token.kind { - let mut err = self.fatal(&format!("unexpected lifetime `{}` in pattern", name)); - err.span_label(self.token.span, "unexpected lifetime"); - return Err(err); - } - let subpat = self.parse_pat_with_range_pat(false, expected)?; Ok(PatKind::Ref(subpat, mutbl)) } + fn recover_lifetime_in_deref_pat(&mut self) { + if let token::Lifetime(name) = self.token.kind { + self.bump(); // `'a` + + let span = self.prev_span; + self.struct_span_err(span, &format!("unexpected lifetime `{}` in pattern", name)) + .span_suggestion( + span, + "remove the lifetime", + String::new(), + Applicability::MachineApplicable, + ) + .emit(); + } + } + /// Parse a tuple or parenthesis pattern. fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> { let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| p.parse_pat_with_or_inner())?; diff --git a/src/test/ui/parser/lifetime-in-pattern-recover.rs b/src/test/ui/parser/lifetime-in-pattern-recover.rs new file mode 100644 index 00000000000..7fb14b80076 --- /dev/null +++ b/src/test/ui/parser/lifetime-in-pattern-recover.rs @@ -0,0 +1,6 @@ +fn main() { + let &'a x = &0; //~ ERROR unexpected lifetime `'a` in pattern + let &'a mut y = &mut 0; //~ ERROR unexpected lifetime `'a` in pattern + + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/src/test/ui/parser/lifetime-in-pattern-recover.stderr b/src/test/ui/parser/lifetime-in-pattern-recover.stderr new file mode 100644 index 00000000000..4bf7f57bfb5 --- /dev/null +++ b/src/test/ui/parser/lifetime-in-pattern-recover.stderr @@ -0,0 +1,23 @@ +error: unexpected lifetime `'a` in pattern + --> $DIR/lifetime-in-pattern-recover.rs:2:10 + | +LL | let &'a x = &0; + | ^^ help: remove the lifetime + +error: unexpected lifetime `'a` in pattern + --> $DIR/lifetime-in-pattern-recover.rs:3:10 + | +LL | let &'a mut y = &mut 0; + | ^^ help: remove the lifetime + +error[E0308]: mismatched types + --> $DIR/lifetime-in-pattern-recover.rs:5:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/lifetime-in-pattern.rs b/src/test/ui/parser/lifetime-in-pattern.rs index afee685cd05..d3c638d0cd7 100644 --- a/src/test/ui/parser/lifetime-in-pattern.rs +++ b/src/test/ui/parser/lifetime-in-pattern.rs @@ -1,5 +1,6 @@ fn test(&'a str) { //~^ ERROR unexpected lifetime `'a` in pattern + //~| ERROR expected one of `:`, `@`, or `|`, found `)` } fn main() { diff --git a/src/test/ui/parser/lifetime-in-pattern.stderr b/src/test/ui/parser/lifetime-in-pattern.stderr index e525c7b6d68..71fd3cdf723 100644 --- a/src/test/ui/parser/lifetime-in-pattern.stderr +++ b/src/test/ui/parser/lifetime-in-pattern.stderr @@ -2,7 +2,13 @@ error: unexpected lifetime `'a` in pattern --> $DIR/lifetime-in-pattern.rs:1:10 | LL | fn test(&'a str) { - | ^^ unexpected lifetime + | ^^ help: remove the lifetime -error: aborting due to previous error +error: expected one of `:`, `@`, or `|`, found `)` + --> $DIR/lifetime-in-pattern.rs:1:16 + | +LL | fn test(&'a str) { + | ^ expected one of `:`, `@`, or `|` + +error: aborting due to 2 previous errors diff --git a/src/test/ui/self/self-vs-path-ambiguity.stderr b/src/test/ui/self/self-vs-path-ambiguity.stderr index 5ce6a81bfcf..2beef50cdb5 100644 --- a/src/test/ui/self/self-vs-path-ambiguity.stderr +++ b/src/test/ui/self/self-vs-path-ambiguity.stderr @@ -2,7 +2,7 @@ error: unexpected lifetime `'a` in pattern --> $DIR/self-vs-path-ambiguity.rs:9:11 | LL | fn i(&'a self::S: &S) {} - | ^^ unexpected lifetime + | ^^ help: remove the lifetime error: aborting due to previous error