diff options
| author | Manish Goregaokar <manishsmail@gmail.com> | 2016-05-27 09:57:00 +0530 |
|---|---|---|
| committer | Manish Goregaokar <manishsmail@gmail.com> | 2016-05-27 09:57:00 +0530 |
| commit | 35785712cd5e1acbfebd168c045b2e184ae979cc (patch) | |
| tree | 2a26d66185c4570f3ab6055860c7f8ce1efad57a /src/libsyntax/parse/parser.rs | |
| parent | a70880fea967715e964f459746a77aa9e93dc35f (diff) | |
| parent | 0ca9bf394006fe635a4a76ca6fa78a70633666f0 (diff) | |
| download | rust-35785712cd5e1acbfebd168c045b2e184ae979cc.tar.gz rust-35785712cd5e1acbfebd168c045b2e184ae979cc.zip | |
Rollup merge of #33639 - petrochenkov:dotdot, r=nmatsakis
cc https://github.com/rust-lang/rust/issues/33627 r? @nikomatsakis plugin-[breaking-change] cc https://github.com/rust-lang/rust/issues/31645 @Manishearth
Diffstat (limited to 'src/libsyntax/parse/parser.rs')
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 69 |
1 files changed, 26 insertions, 43 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index b616b9db9c3..e23c211e687 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -954,25 +954,6 @@ impl<'a> Parser<'a> { Ok(result) } - /// Parse a sequence parameter of enum variant. For consistency purposes, - /// these should not be empty. - pub fn parse_enum_variant_seq<T, F>(&mut self, - bra: &token::Token, - ket: &token::Token, - sep: SeqSep, - f: F) - -> PResult<'a, Vec<T>> where - F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, - { - let result = self.parse_unspanned_seq(bra, ket, sep, f)?; - if result.is_empty() { - let last_span = self.last_span; - self.span_err(last_span, - "nullary enum variants are written with no trailing `( )`"); - } - Ok(result) - } - // NB: Do not use this function unless you actually plan to place the // spanned list in the AST. pub fn parse_seq<T, F>(&mut self, @@ -3434,21 +3415,33 @@ impl<'a> Parser<'a> { }; } - fn parse_pat_tuple_elements(&mut self) -> PResult<'a, Vec<P<Pat>>> { + fn parse_pat_tuple_elements(&mut self, unary_needs_comma: bool) + -> PResult<'a, (Vec<P<Pat>>, Option<usize>)> { let mut fields = vec![]; - if !self.check(&token::CloseDelim(token::Paren)) { - fields.push(self.parse_pat()?); - if self.look_ahead(1, |t| *t != token::CloseDelim(token::Paren)) { - while self.eat(&token::Comma) && - !self.check(&token::CloseDelim(token::Paren)) { + let mut ddpos = None; + + while !self.check(&token::CloseDelim(token::Paren)) { + if ddpos.is_none() && self.eat(&token::DotDot) { + ddpos = Some(fields.len()); + if self.eat(&token::Comma) { + // `..` needs to be followed by `)` or `, pat`, `..,)` is disallowed. fields.push(self.parse_pat()?); } + } else if ddpos.is_some() && self.eat(&token::DotDot) { + // Emit a friendly error, ignore `..` and continue parsing + self.span_err(self.last_span, "`..` can only be used once per \ + tuple or tuple struct pattern"); + } else { + fields.push(self.parse_pat()?); } - if fields.len() == 1 { + + if !self.check(&token::CloseDelim(token::Paren)) || + (unary_needs_comma && fields.len() == 1 && ddpos.is_none()) { self.expect(&token::Comma)?; } } - Ok(fields) + + Ok((fields, ddpos)) } fn parse_pat_vec_elements( @@ -3627,9 +3620,9 @@ impl<'a> Parser<'a> { token::OpenDelim(token::Paren) => { // Parse (pat,pat,pat,...) as tuple pattern self.bump(); - let fields = self.parse_pat_tuple_elements()?; + let (fields, ddpos) = self.parse_pat_tuple_elements(true)?; self.expect(&token::CloseDelim(token::Paren))?; - pat = PatKind::Tup(fields); + pat = PatKind::Tuple(fields, ddpos); } token::OpenDelim(token::Bracket) => { // Parse [pat,pat,...] as slice pattern @@ -3714,20 +3707,10 @@ impl<'a> Parser<'a> { return Err(self.fatal("unexpected `(` after qualified path")); } // Parse tuple struct or enum pattern - if self.look_ahead(1, |t| *t == token::DotDot) { - // This is a "top constructor only" pat - self.bump(); - self.bump(); - self.expect(&token::CloseDelim(token::Paren))?; - pat = PatKind::TupleStruct(path, None); - } else { - let args = self.parse_enum_variant_seq( - &token::OpenDelim(token::Paren), - &token::CloseDelim(token::Paren), - SeqSep::trailing_allowed(token::Comma), - |p| p.parse_pat())?; - pat = PatKind::TupleStruct(path, Some(args)); - } + self.bump(); + let (fields, ddpos) = self.parse_pat_tuple_elements(false)?; + self.expect(&token::CloseDelim(token::Paren))?; + pat = PatKind::TupleStruct(path, fields, ddpos) } _ => { pat = match qself { |
