diff options
| author | bors <bors@rust-lang.org> | 2017-09-14 00:28:27 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-09-14 00:28:27 +0000 |
| commit | d1ca653b170c235ad01a83d89fcb18b1f8b6a3b0 (patch) | |
| tree | 8164bdb3d77369f108c1f02b997ae656cfb1e9a9 /src/libsyntax/parse/parser.rs | |
| parent | 94211416bcde4d1049f241b6c95594e28c8865e6 (diff) | |
| parent | 31cf11a157242184a11cc2a05f3eef9bf5c74309 (diff) | |
| download | rust-d1ca653b170c235ad01a83d89fcb18b1f8b6a3b0.tar.gz rust-d1ca653b170c235ad01a83d89fcb18b1f8b6a3b0.zip | |
Auto merge of #44484 - tirr-c:issue-44332, r=petrochenkov
Parse nested closure with two consecutive parameter lists properly
This is a followup of #44332.
---
Currently, in nightly, this does not compile:
```rust
fn main() {
let f = |_||x, y| x+y;
println!("{}", f(())(1, 2)); // should print 3
}
```
`|_||x, y| x+y` should be parsed as `|_| (|x, y| x+y)`, but the parser didn't accept `||` between `_` and `x`. This patch fixes the problem.
r? @petrochenkov
Diffstat (limited to 'src/libsyntax/parse/parser.rs')
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 44 |
1 files changed, 38 insertions, 6 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 3301a7388c5..cd1a7e7b794 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -481,6 +481,12 @@ fn dummy_arg(span: Span) -> Arg { Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID } } +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +enum TokenExpectType { + Expect, + NoExpect, +} + impl<'a> Parser<'a> { pub fn new(sess: &'a ParseSess, tokens: TokenStream, @@ -797,6 +803,23 @@ impl<'a> Parser<'a> { } } + /// Expect and consume an `|`. If `||` is seen, replace it with a single + /// `|` and continue. If an `|` is not seen, signal an error. + fn expect_or(&mut self) -> PResult<'a, ()> { + self.expected_tokens.push(TokenType::Token(token::BinOp(token::Or))); + match self.token { + token::BinOp(token::Or) => { + self.bump(); + Ok(()) + } + token::OrOr => { + let span = self.span.with_lo(self.span.lo() + BytePos(1)); + Ok(self.bump_with(token::BinOp(token::Or), span)) + } + _ => self.unexpected() + } + } + pub fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option<ast::Name>) { match suffix { None => {/* everything ok */} @@ -946,6 +969,7 @@ impl<'a> Parser<'a> { self.parse_seq_to_before_tokens(kets, SeqSep::none(), + TokenExpectType::Expect, |p| Ok(p.parse_token_tree()), |mut e| handler.cancel(&mut e)); } @@ -975,13 +999,14 @@ impl<'a> Parser<'a> { -> Vec<T> where F: FnMut(&mut Parser<'a>) -> PResult<'a, T> { - self.parse_seq_to_before_tokens(&[ket], sep, f, |mut e| e.emit()) + self.parse_seq_to_before_tokens(&[ket], sep, TokenExpectType::Expect, f, |mut e| e.emit()) } // `fe` is an error handler. fn parse_seq_to_before_tokens<T, F, Fe>(&mut self, kets: &[&token::Token], sep: SeqSep, + expect: TokenExpectType, mut f: F, mut fe: Fe) -> Vec<T> @@ -1005,7 +1030,12 @@ impl<'a> Parser<'a> { } } } - if sep.trailing_sep_allowed && kets.iter().any(|k| self.check(k)) { + if sep.trailing_sep_allowed && kets.iter().any(|k| { + match expect { + TokenExpectType::Expect => self.check(k), + TokenExpectType::NoExpect => self.token == **k, + } + }) { break; } @@ -4694,12 +4724,14 @@ impl<'a> Parser<'a> { Vec::new() } else { self.expect(&token::BinOp(token::Or))?; - let args = self.parse_seq_to_before_end( - &token::BinOp(token::Or), + let args = self.parse_seq_to_before_tokens( + &[&token::BinOp(token::Or), &token::OrOr], SeqSep::trailing_allowed(token::Comma), - |p| p.parse_fn_block_arg() + TokenExpectType::NoExpect, + |p| p.parse_fn_block_arg(), + |mut e| e.emit() ); - self.expect(&token::BinOp(token::Or))?; + self.expect_or()?; args } }; |
