1
Fork 0

extract parse_pat_{tuple_}struct + recover_one_fewer_dotdot

This commit is contained in:
Mazdak Farrokhzad 2019-08-12 12:27:43 +02:00
parent ddf734deb2
commit c8fc4c106c

View file

@ -169,34 +169,8 @@ impl<'a> Parser<'a> {
token::DotDotDot | token::DotDotEq | token::DotDot => {
self.parse_pat_range_starting_with_path(lo, qself, path)?
}
token::OpenDelim(token::Brace) => {
if qself.is_some() {
let msg = "unexpected `{` after qualified path";
let mut err = self.fatal(msg);
err.span_label(self.token.span, msg);
return Err(err);
}
// Parse struct pattern
self.bump();
let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| {
e.emit();
self.recover_stmt();
(vec![], true)
});
self.bump();
PatKind::Struct(path, fields, etc)
}
token::OpenDelim(token::Paren) => {
if qself.is_some() {
let msg = "unexpected `(` after qualified path";
let mut err = self.fatal(msg);
err.span_label(self.token.span, msg);
return Err(err);
}
// Parse tuple struct or enum pattern
let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?;
PatKind::TupleStruct(path, fields)
}
token::OpenDelim(token::Brace) => self.parse_pat_struct(qself, path)?,
token::OpenDelim(token::Paren) => self.parse_pat_tuple_struct(qself, path)?,
_ => PatKind::Path(qself, path),
}
} else {
@ -481,6 +455,37 @@ impl<'a> Parser<'a> {
Ok(PatKind::Ident(binding_mode, ident, sub))
}
/// Parse a struct ("record") pattern (e.g. `Foo { ... }` or `Foo::Bar { ... }`).
fn parse_pat_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> {
if qself.is_some() {
let msg = "unexpected `{` after qualified path";
let mut err = self.fatal(msg);
err.span_label(self.token.span, msg);
return Err(err);
}
self.bump();
let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| {
e.emit();
self.recover_stmt();
(vec![], true)
});
self.bump();
Ok(PatKind::Struct(path, fields, etc))
}
/// Parse tuple struct or tuple variant pattern (e.g. `Foo(...)` or `Foo::Bar(...)`).
fn parse_pat_tuple_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> {
if qself.is_some() {
let msg = "unexpected `(` after qualified path";
let mut err = self.fatal(msg);
err.span_label(self.token.span, msg);
return Err(err);
}
let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?;
Ok(PatKind::TupleStruct(path, fields))
}
/// Parses the fields of a struct-like pattern.
fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<Spanned<FieldPat>>, bool)> {
let mut fields = Vec::new();
@ -515,17 +520,7 @@ impl<'a> Parser<'a> {
etc = true;
let mut etc_sp = self.token.span;
if self.token == token::DotDotDot { // Issue #46718
// Accept `...` as if it were `..` to avoid further errors
self.struct_span_err(self.token.span, "expected field pattern, found `...`")
.span_suggestion(
self.token.span,
"to omit remaining fields, use one fewer `.`",
"..".to_owned(),
Applicability::MachineApplicable
)
.emit();
}
self.recover_one_fewer_dotdot();
self.bump(); // `..` || `...`
if self.token == token::CloseDelim(token::Brace) {
@ -607,6 +602,23 @@ impl<'a> Parser<'a> {
return Ok((fields, etc));
}
/// Recover on `...` as if it were `..` to avoid further errors.
/// See issue #46718.
fn recover_one_fewer_dotdot(&self) {
if self.token != token::DotDotDot {
return;
}
self.struct_span_err(self.token.span, "expected field pattern, found `...`")
.span_suggestion(
self.token.span,
"to omit remaining fields, use one fewer `.`",
"..".to_owned(),
Applicability::MachineApplicable
)
.emit();
}
fn parse_pat_field(
&mut self,
lo: Span,