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 /src/libsyntax/parse | |
| parent | 1ffea18ddbe9ebaba4ff301a3c42e44a55741355 (diff) | |
| download | rust-b205055c7bc92c0f873755996e6fac3e694c7e72.tar.gz rust-b205055c7bc92c0f873755996e6fac3e694c7e72.zip | |
parser: better recovery for || in inner pats.
Diffstat (limited to 'src/libsyntax/parse')
| -rw-r--r-- | src/libsyntax/parse/parser/pat.rs | 27 |
1 files changed, 23 insertions, 4 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 { |
