Skip to content

Commit c8fc4c1

Browse files
committed
extract parse_pat_{tuple_}struct + recover_one_fewer_dotdot
1 parent ddf734d commit c8fc4c1

File tree

1 file changed

+51
-39
lines changed
  • src/libsyntax/parse/parser

1 file changed

+51
-39
lines changed

src/libsyntax/parse/parser/pat.rs

+51-39
Original file line numberDiff line numberDiff line change
@@ -169,34 +169,8 @@ impl<'a> Parser<'a> {
169169
token::DotDotDot | token::DotDotEq | token::DotDot => {
170170
self.parse_pat_range_starting_with_path(lo, qself, path)?
171171
}
172-
token::OpenDelim(token::Brace) => {
173-
if qself.is_some() {
174-
let msg = "unexpected `{` after qualified path";
175-
let mut err = self.fatal(msg);
176-
err.span_label(self.token.span, msg);
177-
return Err(err);
178-
}
179-
// Parse struct pattern
180-
self.bump();
181-
let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| {
182-
e.emit();
183-
self.recover_stmt();
184-
(vec![], true)
185-
});
186-
self.bump();
187-
PatKind::Struct(path, fields, etc)
188-
}
189-
token::OpenDelim(token::Paren) => {
190-
if qself.is_some() {
191-
let msg = "unexpected `(` after qualified path";
192-
let mut err = self.fatal(msg);
193-
err.span_label(self.token.span, msg);
194-
return Err(err);
195-
}
196-
// Parse tuple struct or enum pattern
197-
let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?;
198-
PatKind::TupleStruct(path, fields)
199-
}
172+
token::OpenDelim(token::Brace) => self.parse_pat_struct(qself, path)?,
173+
token::OpenDelim(token::Paren) => self.parse_pat_tuple_struct(qself, path)?,
200174
_ => PatKind::Path(qself, path),
201175
}
202176
} else {
@@ -481,6 +455,37 @@ impl<'a> Parser<'a> {
481455
Ok(PatKind::Ident(binding_mode, ident, sub))
482456
}
483457

458+
/// Parse a struct ("record") pattern (e.g. `Foo { ... }` or `Foo::Bar { ... }`).
459+
fn parse_pat_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> {
460+
if qself.is_some() {
461+
let msg = "unexpected `{` after qualified path";
462+
let mut err = self.fatal(msg);
463+
err.span_label(self.token.span, msg);
464+
return Err(err);
465+
}
466+
467+
self.bump();
468+
let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| {
469+
e.emit();
470+
self.recover_stmt();
471+
(vec![], true)
472+
});
473+
self.bump();
474+
Ok(PatKind::Struct(path, fields, etc))
475+
}
476+
477+
/// Parse tuple struct or tuple variant pattern (e.g. `Foo(...)` or `Foo::Bar(...)`).
478+
fn parse_pat_tuple_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> {
479+
if qself.is_some() {
480+
let msg = "unexpected `(` after qualified path";
481+
let mut err = self.fatal(msg);
482+
err.span_label(self.token.span, msg);
483+
return Err(err);
484+
}
485+
let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?;
486+
Ok(PatKind::TupleStruct(path, fields))
487+
}
488+
484489
/// Parses the fields of a struct-like pattern.
485490
fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<Spanned<FieldPat>>, bool)> {
486491
let mut fields = Vec::new();
@@ -515,17 +520,7 @@ impl<'a> Parser<'a> {
515520
etc = true;
516521
let mut etc_sp = self.token.span;
517522

518-
if self.token == token::DotDotDot { // Issue #46718
519-
// Accept `...` as if it were `..` to avoid further errors
520-
self.struct_span_err(self.token.span, "expected field pattern, found `...`")
521-
.span_suggestion(
522-
self.token.span,
523-
"to omit remaining fields, use one fewer `.`",
524-
"..".to_owned(),
525-
Applicability::MachineApplicable
526-
)
527-
.emit();
528-
}
523+
self.recover_one_fewer_dotdot();
529524
self.bump(); // `..` || `...`
530525

531526
if self.token == token::CloseDelim(token::Brace) {
@@ -607,6 +602,23 @@ impl<'a> Parser<'a> {
607602
return Ok((fields, etc));
608603
}
609604

605+
/// Recover on `...` as if it were `..` to avoid further errors.
606+
/// See issue #46718.
607+
fn recover_one_fewer_dotdot(&self) {
608+
if self.token != token::DotDotDot {
609+
return;
610+
}
611+
612+
self.struct_span_err(self.token.span, "expected field pattern, found `...`")
613+
.span_suggestion(
614+
self.token.span,
615+
"to omit remaining fields, use one fewer `.`",
616+
"..".to_owned(),
617+
Applicability::MachineApplicable
618+
)
619+
.emit();
620+
}
621+
610622
fn parse_pat_field(
611623
&mut self,
612624
lo: Span,

0 commit comments

Comments
 (0)