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
This commit is contained in:
commit
35785712cd
50 changed files with 873 additions and 297 deletions
|
@ -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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue