diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-08-19 02:40:24 +0200 |
|---|---|---|
| committer | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-08-24 21:53:55 +0200 |
| commit | b205055c7bc92c0f873755996e6fac3e694c7e72 (patch) | |
| tree | d08790b43bae6854a53e82b90f47fa7df1ba413c | |
| parent | 1ffea18ddbe9ebaba4ff301a3c42e44a55741355 (diff) | |
| download | rust-b205055c7bc92c0f873755996e6fac3e694c7e72.tar.gz rust-b205055c7bc92c0f873755996e6fac3e694c7e72.zip | |
parser: better recovery for || in inner pats.
| -rw-r--r-- | src/libsyntax/parse/parser/pat.rs | 27 | ||||
| -rw-r--r-- | src/test/ui/or-patterns/or-patterns-syntactic-fail.rs | 39 | ||||
| -rw-r--r-- | src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr | 77 |
3 files changed, 96 insertions, 47 deletions
diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index e77d9120bce..b9871be229c 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -155,6 +155,25 @@ impl<'a> Parser<'a> { Ok(()) } + /// Recursive possibly-or-pattern parser with recovery for an erroneous leading `|`. + /// See `parse_pat_with_or` for details on parsing or-patterns. + fn parse_pat_with_or_inner(&mut self, expected: Expected) -> PResult<'a, P<Pat>> { + // Recover if `|` or `||` is here. + // The user is thinking that a leading `|` is allowed in this position. + if let token::BinOp(token::Or) | token::OrOr = self.token.kind { + let span = self.token.span; + let rm_msg = format!("remove the `{}`", pprust::token_to_string(&self.token)); + + self.struct_span_err(span, "a leading `|` is only allowed in a top-level pattern") + .span_suggestion(span, &rm_msg, String::new(), Applicability::MachineApplicable) + .emit(); + + self.bump(); + } + + self.parse_pat_with_or(expected, true, false) + } + /// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are /// allowed). fn parse_pat_with_range_pat( @@ -173,7 +192,7 @@ impl<'a> Parser<'a> { // Parse `[pat, pat,...]` as a slice pattern. let (pats, _) = self.parse_delim_comma_seq( token::Bracket, - |p| p.parse_pat_with_or(None, true, false), + |p| p.parse_pat_with_or_inner(None), )?; PatKind::Slice(pats) } @@ -303,7 +322,7 @@ impl<'a> Parser<'a> { /// 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(None, true, false) + p.parse_pat_with_or_inner(None) })?; // Here, `(pat,)` is a tuple pattern. @@ -547,7 +566,7 @@ impl<'a> Parser<'a> { err.span_label(self.token.span, msg); return Err(err); } - let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat_with_or(None, true, false))?; + let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat_with_or_inner(None))?; Ok(PatKind::TupleStruct(path, fields)) } @@ -691,7 +710,7 @@ impl<'a> Parser<'a> { // Parsing a pattern of the form "fieldname: pat" let fieldname = self.parse_field_name()?; self.bump(); - let pat = self.parse_pat_with_or(None, true, false)?; + let pat = self.parse_pat_with_or_inner(None)?; hi = pat.span; (pat, fieldname, false) } else { diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs b/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs index 43c9214bd98..7959812f5b3 100644 --- a/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs +++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs @@ -30,27 +30,20 @@ fn no_top_level_or_patterns() { // We also do not allow a leading `|` when not in a top level position: -#[cfg(FALSE)] -fn no_leading_parens() { - let ( | A | B); //~ ERROR expected pattern, found `|` -} - -#[cfg(FALSE)] -fn no_leading_tuple() { - let ( | A | B,); //~ ERROR expected pattern, found `|` -} - -#[cfg(FALSE)] -fn no_leading_slice() { - let [ | A | B ]; //~ ERROR expected pattern, found `|` -} - -#[cfg(FALSE)] -fn no_leading_tuple_struct() { - let TS( | A | B ); //~ ERROR expected pattern, found `|` -} - -#[cfg(FALSE)] -fn no_leading_struct() { - let NS { f: | A | B }; //~ ERROR expected pattern, found `|` +fn no_leading_inner() { + struct TS(E); + struct NS { f: E } + + let ( | A | B) = E::A; //~ ERROR a leading `|` is only allowed in a top-level pattern + let ( | A | B,) = (E::B,); //~ ERROR a leading `|` is only allowed in a top-level pattern + let [ | A | B ] = [E::A]; //~ ERROR a leading `|` is only allowed in a top-level pattern + let TS( | A | B ); //~ ERROR a leading `|` is only allowed in a top-level pattern + let NS { f: | A | B }; //~ ERROR a leading `|` is only allowed in a top-level pattern + + let ( || A | B) = E::A; //~ ERROR a leading `|` is only allowed in a top-level pattern + let [ || A | B ] = [E::A]; //~ ERROR a leading `|` is only allowed in a top-level pattern + let TS( || A | B ); //~ ERROR a leading `|` is only allowed in a top-level pattern + let NS { f: || A | B }; //~ ERROR a leading `|` is only allowed in a top-level pattern + + let recovery_witness: String = 0; //~ ERROR mismatched types } diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr index 809ff272f62..dd4c309ce85 100644 --- a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr +++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr @@ -4,35 +4,59 @@ error: expected one of `:` or `@`, found `|` LL | fn fun(A | B: E) {} | ^ expected one of `:` or `@` here -error: expected pattern, found `|` - --> $DIR/or-patterns-syntactic-fail.rs:35:11 +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:37:11 | -LL | let ( | A | B); - | ^ expected pattern +LL | let ( | A | B) = E::A; + | ^ help: remove the `|` -error: expected pattern, found `|` - --> $DIR/or-patterns-syntactic-fail.rs:40:11 +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:38:11 | -LL | let ( | A | B,); - | ^ expected pattern +LL | let ( | A | B,) = (E::B,); + | ^ help: remove the `|` -error: expected pattern, found `|` - --> $DIR/or-patterns-syntactic-fail.rs:45:11 +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:39:11 | -LL | let [ | A | B ]; - | ^ expected pattern +LL | let [ | A | B ] = [E::A]; + | ^ help: remove the `|` -error: expected pattern, found `|` - --> $DIR/or-patterns-syntactic-fail.rs:50:13 +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:40:13 | LL | let TS( | A | B ); - | ^ expected pattern + | ^ help: remove the `|` -error: expected pattern, found `|` - --> $DIR/or-patterns-syntactic-fail.rs:55:17 +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:41:17 | LL | let NS { f: | A | B }; - | ^ expected pattern + | ^ help: remove the `|` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:43:11 + | +LL | let ( || A | B) = E::A; + | ^^ help: remove the `||` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:44:11 + | +LL | let [ || A | B ] = [E::A]; + | ^^ help: remove the `||` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:45:13 + | +LL | let TS( || A | B ); + | ^^ help: remove the `||` + +error: a leading `|` is only allowed in a top-level pattern + --> $DIR/or-patterns-syntactic-fail.rs:46:17 + | +LL | let NS { f: || A | B }; + | ^^ help: remove the `||` error: no rules expected the token `|` --> $DIR/or-patterns-syntactic-fail.rs:14:15 @@ -70,6 +94,19 @@ LL | let _ = |A | B: E| (); | = note: an implementation of `std::ops::BitOr` might be missing for `E` -error: aborting due to 9 previous errors +error[E0308]: mismatched types + --> $DIR/or-patterns-syntactic-fail.rs:48:36 + | +LL | let recovery_witness: String = 0; + | ^ + | | + | expected struct `std::string::String`, found integer + | help: try using a conversion method: `0.to_string()` + | + = note: expected type `std::string::String` + found type `{integer}` + +error: aborting due to 14 previous errors -For more information about this error, try `rustc --explain E0369`. +Some errors have detailed explanations: E0308, E0369. +For more information about an error, try `rustc --explain E0308`. |
