]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/parse/parser/pat.rs
parser: `parse_pats` -> `parse_top_pat{_unpack}`.
[rust.git] / src / libsyntax / parse / parser / pat.rs
1 use super::{Parser, PResult, PathStyle};
2
3 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
4 use crate::ptr::P;
5 use crate::ast::{self, Attribute, Pat, PatKind, FieldPat, RangeEnd, RangeSyntax, Mac};
6 use crate::ast::{BindingMode, Ident, Mutability, Path, QSelf, Expr, ExprKind};
7 use crate::parse::token::{self};
8 use crate::print::pprust;
9 use crate::source_map::{respan, Span, Spanned};
10 use crate::symbol::kw;
11 use crate::ThinVec;
12
13 use errors::{Applicability, DiagnosticBuilder};
14
15 type Expected = Option<&'static str>;
16
17 impl<'a> Parser<'a> {
18     /// Parses a pattern.
19     pub fn parse_pat(&mut self, expected: Expected) -> PResult<'a, P<Pat>> {
20         self.parse_pat_with_range_pat(true, expected)
21     }
22
23     // FIXME(or_patterns, Centril | dlrobertson):
24     // remove this and use `parse_top_pat` everywhere it is used instead.
25     pub(super) fn parse_top_pat_unpack(&mut self, gate_or: bool) -> PResult<'a, Vec<P<Pat>>> {
26         self.parse_top_pat(gate_or)
27             .map(|pat| pat.and_then(|pat| match pat.node {
28                 PatKind::Or(pats) => pats,
29                 node => vec![self.mk_pat(pat.span, node)],
30             }))
31     }
32
33     /// Entry point to the main pattern parser.
34     /// Corresponds to `top_pat` in RFC 2535 and allows or-pattern at the top level.
35     pub(super) fn parse_top_pat(&mut self, gate_or: bool) -> PResult<'a, P<Pat>> {
36         // Allow a '|' before the pats (RFCs 1925, 2530, and 2535).
37         if self.eat_or_separator() && gate_or {
38             self.sess.gated_spans.or_patterns.borrow_mut().push(self.prev_span);
39         }
40
41         self.parse_pat_with_or(None, gate_or, true)
42     }
43
44     pub(super) fn parse_top_level_pat(&mut self) -> PResult<'a, P<Pat>> {
45         let pat = self.parse_pat(None)?;
46         self.maybe_recover_unexpected_comma(pat.span, true)?;
47         Ok(pat)
48     }
49
50     /// Parses a pattern, that may be a or-pattern (e.g. `Foo | Bar` in `Some(Foo | Bar)`).
51     /// Corresponds to `pat<allow_top_alt>` in RFC 2535.
52     fn parse_pat_with_or(
53         &mut self,
54         expected: Expected,
55         gate_or: bool,
56         top_level: bool
57     ) -> PResult<'a, P<Pat>> {
58         // Parse the first pattern.
59         let first_pat = self.parse_pat(expected)?;
60         self.maybe_recover_unexpected_comma(first_pat.span, top_level)?;
61
62         // If the next token is not a `|`,
63         // this is not an or-pattern and we should exit here.
64         if !self.check(&token::BinOp(token::Or)) && self.token != token::OrOr {
65             return Ok(first_pat)
66         }
67
68         let lo = first_pat.span;
69         let mut pats = vec![first_pat];
70         while self.eat_or_separator() {
71             let pat = self.parse_pat(expected)?;
72             self.maybe_recover_unexpected_comma(pat.span, top_level)?;
73             pats.push(pat);
74         }
75         let or_pattern_span = lo.to(self.prev_span);
76
77         // Feature gate the or-pattern if instructed:
78         if gate_or {
79             self.sess.gated_spans.or_patterns.borrow_mut().push(or_pattern_span);
80         }
81
82         Ok(self.mk_pat(or_pattern_span, PatKind::Or(pats)))
83     }
84
85     /// Eat the or-pattern `|` separator.
86     /// If instead a `||` token is encountered, recover and pretend we parsed `|`.
87     fn eat_or_separator(&mut self) -> bool {
88         match self.token.kind {
89             token::OrOr => {
90                 // Found `||`; Recover and pretend we parsed `|`.
91                 self.ban_unexpected_or_or();
92                 self.bump();
93                 true
94             }
95             _ => self.eat(&token::BinOp(token::Or)),
96         }
97     }
98
99     /// We have parsed `||` instead of `|`. Error and suggest `|` instead.
100     fn ban_unexpected_or_or(&mut self) {
101         self.struct_span_err(self.token.span, "unexpected token `||` after pattern")
102             .span_suggestion(
103                 self.token.span,
104                 "use a single `|` to specify multiple patterns",
105                 "|".to_owned(),
106                 Applicability::MachineApplicable
107             )
108             .emit();
109     }
110
111     /// Some special error handling for the "top-level" patterns in a match arm,
112     /// `for` loop, `let`, &c. (in contrast to subpatterns within such).
113     fn maybe_recover_unexpected_comma(&mut self, lo: Span, top_level: bool) -> PResult<'a, ()> {
114         if !top_level || self.token != token::Comma {
115             return Ok(());
116         }
117
118         // An unexpected comma after a top-level pattern is a clue that the
119         // user (perhaps more accustomed to some other language) forgot the
120         // parentheses in what should have been a tuple pattern; return a
121         // suggestion-enhanced error here rather than choking on the comma later.
122         let comma_span = self.token.span;
123         self.bump();
124         if let Err(mut err) = self.skip_pat_list() {
125             // We didn't expect this to work anyway; we just wanted to advance to the
126             // end of the comma-sequence so we know the span to suggest parenthesizing.
127             err.cancel();
128         }
129         let seq_span = lo.to(self.prev_span);
130         let mut err = self.struct_span_err(comma_span, "unexpected `,` in pattern");
131         if let Ok(seq_snippet) = self.span_to_snippet(seq_span) {
132             err.span_suggestion(
133                 seq_span,
134                 "try adding parentheses to match on a tuple..",
135                 format!("({})", seq_snippet),
136                 Applicability::MachineApplicable
137             )
138             .span_suggestion(
139                 seq_span,
140                 "..or a vertical bar to match on multiple alternatives",
141                 format!("{}", seq_snippet.replace(",", " |")),
142                 Applicability::MachineApplicable
143             );
144         }
145         Err(err)
146     }
147
148     /// Parse and throw away a parentesized comma separated
149     /// sequence of patterns until `)` is reached.
150     fn skip_pat_list(&mut self) -> PResult<'a, ()> {
151         while !self.check(&token::CloseDelim(token::Paren)) {
152             self.parse_pat(None)?;
153             if !self.eat(&token::Comma) {
154                 return Ok(())
155             }
156         }
157         Ok(())
158     }
159
160     /// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are
161     /// allowed).
162     fn parse_pat_with_range_pat(
163         &mut self,
164         allow_range_pat: bool,
165         expected: Expected,
166     ) -> PResult<'a, P<Pat>> {
167         maybe_recover_from_interpolated_ty_qpath!(self, true);
168         maybe_whole!(self, NtPat, |x| x);
169
170         let lo = self.token.span;
171         let pat = match self.token.kind {
172             token::BinOp(token::And) | token::AndAnd => self.parse_pat_deref(expected)?,
173             token::OpenDelim(token::Paren) => self.parse_pat_tuple_or_parens()?,
174             token::OpenDelim(token::Bracket) => {
175                 // Parse `[pat, pat,...]` as a slice pattern.
176                 let (pats, _) = self.parse_delim_comma_seq(
177                     token::Bracket,
178                     |p| p.parse_pat_with_or(None, true, false),
179                 )?;
180                 PatKind::Slice(pats)
181             }
182             token::DotDot => {
183                 self.bump();
184                 if self.is_pat_range_end_start() {
185                     // Parse `..42` for recovery.
186                     self.parse_pat_range_to(RangeEnd::Excluded, "..")?
187                 } else {
188                     // A rest pattern `..`.
189                     PatKind::Rest
190                 }
191             }
192             token::DotDotEq => {
193                 // Parse `..=42` for recovery.
194                 self.bump();
195                 self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotEq), "..=")?
196             }
197             token::DotDotDot => {
198                 // Parse `...42` for recovery.
199                 self.bump();
200                 self.parse_pat_range_to(RangeEnd::Included(RangeSyntax::DotDotDot), "...")?
201             }
202             // At this point, token != &, &&, (, [
203             _ => if self.eat_keyword(kw::Underscore) {
204                 // Parse _
205                 PatKind::Wild
206             } else if self.eat_keyword(kw::Mut) {
207                 self.recover_pat_ident_mut_first()?
208             } else if self.eat_keyword(kw::Ref) {
209                 // Parse ref ident @ pat / ref mut ident @ pat
210                 let mutbl = self.parse_mutability();
211                 self.parse_pat_ident(BindingMode::ByRef(mutbl))?
212             } else if self.eat_keyword(kw::Box) {
213                 // Parse `box pat`
214                 PatKind::Box(self.parse_pat_with_range_pat(false, None)?)
215             } else if self.token.is_ident() && !self.token.is_reserved_ident() &&
216                       self.parse_as_ident() {
217                 // Parse `ident @ pat`
218                 // This can give false positives and parse nullary enums,
219                 // they are dealt with later in resolve.
220                 self.parse_pat_ident(BindingMode::ByValue(Mutability::Immutable))?
221             } else if self.token.is_path_start() {
222                 // Parse pattern starting with a path
223                 let (qself, path) = if self.eat_lt() {
224                     // Parse a qualified path
225                     let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
226                     (Some(qself), path)
227                 } else {
228                     // Parse an unqualified path
229                     (None, self.parse_path(PathStyle::Expr)?)
230                 };
231                 match self.token.kind {
232                     token::Not if qself.is_none() => self.parse_pat_mac_invoc(lo, path)?,
233                     token::DotDotDot | token::DotDotEq | token::DotDot => {
234                         self.parse_pat_range_starting_with_path(lo, qself, path)?
235                     }
236                     token::OpenDelim(token::Brace) => self.parse_pat_struct(qself, path)?,
237                     token::OpenDelim(token::Paren) => self.parse_pat_tuple_struct(qself, path)?,
238                     _ => PatKind::Path(qself, path),
239                 }
240             } else {
241                 // Try to parse everything else as literal with optional minus
242                 match self.parse_literal_maybe_minus() {
243                     Ok(begin)
244                         if self.check(&token::DotDot)
245                             || self.check(&token::DotDotEq)
246                             || self.check(&token::DotDotDot) =>
247                     {
248                         self.parse_pat_range_starting_with_lit(begin)?
249                     }
250                     Ok(begin) => PatKind::Lit(begin),
251                     Err(err) => return self.fatal_unexpected_non_pat(err, expected),
252                 }
253             }
254         };
255
256         let pat = self.mk_pat(lo.to(self.prev_span), pat);
257         let pat = self.maybe_recover_from_bad_qpath(pat, true)?;
258
259         if !allow_range_pat {
260             self.ban_pat_range_if_ambiguous(&pat)?
261         }
262
263         Ok(pat)
264     }
265
266     /// Ban a range pattern if it has an ambiguous interpretation.
267     fn ban_pat_range_if_ambiguous(&self, pat: &Pat) -> PResult<'a, ()> {
268         match pat.node {
269             PatKind::Range(
270                 .., Spanned { node: RangeEnd::Included(RangeSyntax::DotDotDot), .. }
271             ) => return Ok(()),
272             PatKind::Range(..) => {}
273             _ => return Ok(()),
274         }
275
276         let mut err = self.struct_span_err(
277             pat.span,
278             "the range pattern here has ambiguous interpretation",
279         );
280         err.span_suggestion(
281             pat.span,
282             "add parentheses to clarify the precedence",
283             format!("({})", pprust::pat_to_string(&pat)),
284             // "ambiguous interpretation" implies that we have to be guessing
285             Applicability::MaybeIncorrect
286         );
287         Err(err)
288     }
289
290     /// Parse `&pat` / `&mut pat`.
291     fn parse_pat_deref(&mut self, expected: Expected) -> PResult<'a, PatKind> {
292         self.expect_and()?;
293         let mutbl = self.parse_mutability();
294
295         if let token::Lifetime(name) = self.token.kind {
296             let mut err = self.fatal(&format!("unexpected lifetime `{}` in pattern", name));
297             err.span_label(self.token.span, "unexpected lifetime");
298             return Err(err);
299         }
300
301         let subpat = self.parse_pat_with_range_pat(false, expected)?;
302         Ok(PatKind::Ref(subpat, mutbl))
303     }
304
305     /// Parse a tuple or parenthesis pattern.
306     fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> {
307         let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| {
308             p.parse_pat_with_or(None, true, false)
309         })?;
310
311         // Here, `(pat,)` is a tuple pattern.
312         // For backward compatibility, `(..)` is a tuple pattern as well.
313         Ok(if fields.len() == 1 && !(trailing_comma || fields[0].is_rest()) {
314             PatKind::Paren(fields.into_iter().nth(0).unwrap())
315         } else {
316             PatKind::Tuple(fields)
317         })
318     }
319
320     /// Recover on `mut ref? ident @ pat` and suggest
321     /// that the order of `mut` and `ref` is incorrect.
322     fn recover_pat_ident_mut_first(&mut self) -> PResult<'a, PatKind> {
323         let mutref_span = self.prev_span.to(self.token.span);
324         let binding_mode = if self.eat_keyword(kw::Ref) {
325             self.struct_span_err(mutref_span, "the order of `mut` and `ref` is incorrect")
326                 .span_suggestion(
327                     mutref_span,
328                     "try switching the order",
329                     "ref mut".into(),
330                     Applicability::MachineApplicable
331                 )
332                 .emit();
333             BindingMode::ByRef(Mutability::Mutable)
334         } else {
335             BindingMode::ByValue(Mutability::Mutable)
336         };
337         self.parse_pat_ident(binding_mode)
338     }
339
340     /// Parse macro invocation
341     fn parse_pat_mac_invoc(&mut self, lo: Span, path: Path) -> PResult<'a, PatKind> {
342         self.bump();
343         let (delim, tts) = self.expect_delimited_token_tree()?;
344         let mac = Mac {
345             path,
346             tts,
347             delim,
348             span: lo.to(self.prev_span),
349             prior_type_ascription: self.last_type_ascription,
350         };
351         Ok(PatKind::Mac(mac))
352     }
353
354     /// Parse a range pattern `$path $form $end?` where `$form = ".." | "..." | "..=" ;`.
355     /// The `$path` has already been parsed and the next token is the `$form`.
356     fn parse_pat_range_starting_with_path(
357         &mut self,
358         lo: Span,
359         qself: Option<QSelf>,
360         path: Path
361     ) -> PResult<'a, PatKind> {
362         let (end_kind, form) = match self.token.kind {
363             token::DotDot => (RangeEnd::Excluded, ".."),
364             token::DotDotDot => (RangeEnd::Included(RangeSyntax::DotDotDot), "..."),
365             token::DotDotEq => (RangeEnd::Included(RangeSyntax::DotDotEq), "..="),
366             _ => panic!("can only parse `..`/`...`/`..=` for ranges (checked above)"),
367         };
368         let op_span = self.token.span;
369         // Parse range
370         let span = lo.to(self.prev_span);
371         let begin = self.mk_expr(span, ExprKind::Path(qself, path), ThinVec::new());
372         self.bump();
373         let end = self.parse_pat_range_end_opt(&begin, form)?;
374         Ok(PatKind::Range(begin, end, respan(op_span, end_kind)))
375     }
376
377     /// Parse a range pattern `$literal $form $end?` where `$form = ".." | "..." | "..=" ;`.
378     /// The `$path` has already been parsed and the next token is the `$form`.
379     fn parse_pat_range_starting_with_lit(&mut self, begin: P<Expr>) -> PResult<'a, PatKind> {
380         let op_span = self.token.span;
381         let (end_kind, form) = if self.eat(&token::DotDotDot) {
382             (RangeEnd::Included(RangeSyntax::DotDotDot), "...")
383         } else if self.eat(&token::DotDotEq) {
384             (RangeEnd::Included(RangeSyntax::DotDotEq), "..=")
385         } else if self.eat(&token::DotDot) {
386             (RangeEnd::Excluded, "..")
387         } else {
388             panic!("impossible case: we already matched on a range-operator token")
389         };
390         let end = self.parse_pat_range_end_opt(&begin, form)?;
391         Ok(PatKind::Range(begin, end, respan(op_span, end_kind)))
392     }
393
394     fn fatal_unexpected_non_pat(
395         &mut self,
396         mut err: DiagnosticBuilder<'a>,
397         expected: Expected,
398     ) -> PResult<'a, P<Pat>> {
399         self.cancel(&mut err);
400
401         let expected = expected.unwrap_or("pattern");
402         let msg = format!("expected {}, found {}", expected, self.this_token_descr());
403
404         let mut err = self.fatal(&msg);
405         err.span_label(self.token.span, format!("expected {}", expected));
406
407         let sp = self.sess.source_map().start_point(self.token.span);
408         if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) {
409             self.sess.expr_parentheses_needed(&mut err, *sp, None);
410         }
411
412         Err(err)
413     }
414
415     // Helper function to decide whether to parse as ident binding
416     // or to try to do something more complex like range patterns.
417     fn parse_as_ident(&mut self) -> bool {
418         self.look_ahead(1, |t| match t.kind {
419             token::OpenDelim(token::Paren) | token::OpenDelim(token::Brace) |
420             token::DotDotDot | token::DotDotEq | token::DotDot |
421             token::ModSep | token::Not => false,
422             _ => true,
423         })
424     }
425
426     /// Is the current token suitable as the start of a range patterns end?
427     fn is_pat_range_end_start(&self) -> bool {
428         self.token.is_path_start() // e.g. `MY_CONST`;
429             || self.token == token::Dot // e.g. `.5` for recovery;
430             || self.token.can_begin_literal_or_bool() // e.g. `42`.
431             || self.token.is_whole_expr()
432     }
433
434     /// Parse a range-to pattern, e.g. `..X` and `..=X` for recovery.
435     fn parse_pat_range_to(&mut self, re: RangeEnd, form: &str) -> PResult<'a, PatKind> {
436         let lo = self.prev_span;
437         let end = self.parse_pat_range_end()?;
438         let range_span = lo.to(end.span);
439         let begin = self.mk_expr(range_span, ExprKind::Err, ThinVec::new());
440
441         self.diagnostic()
442             .struct_span_err(range_span, &format!("`{}X` range patterns are not supported", form))
443             .span_suggestion(
444                 range_span,
445                 "try using the minimum value for the type",
446                 format!("MIN{}{}", form, pprust::expr_to_string(&end)),
447                 Applicability::HasPlaceholders,
448             )
449             .emit();
450
451         Ok(PatKind::Range(begin, end, respan(lo, re)))
452     }
453
454     /// Parse the end of a `X..Y`, `X..=Y`, or `X...Y` range pattern  or recover
455     /// if that end is missing treating it as `X..`, `X..=`, or `X...` respectively.
456     fn parse_pat_range_end_opt(&mut self, begin: &Expr, form: &str) -> PResult<'a, P<Expr>> {
457         if self.is_pat_range_end_start() {
458             // Parsing e.g. `X..=Y`.
459             self.parse_pat_range_end()
460         } else {
461             // Parsing e.g. `X..`.
462             let range_span = begin.span.to(self.prev_span);
463
464             self.diagnostic()
465                 .struct_span_err(
466                     range_span,
467                     &format!("`X{}` range patterns are not supported", form),
468                 )
469                 .span_suggestion(
470                     range_span,
471                     "try using the maximum value for the type",
472                     format!("{}{}MAX", pprust::expr_to_string(&begin), form),
473                     Applicability::HasPlaceholders,
474                 )
475                 .emit();
476
477             Ok(self.mk_expr(range_span, ExprKind::Err, ThinVec::new()))
478         }
479     }
480
481     fn parse_pat_range_end(&mut self) -> PResult<'a, P<Expr>> {
482         if self.token.is_path_start() {
483             let lo = self.token.span;
484             let (qself, path) = if self.eat_lt() {
485                 // Parse a qualified path
486                 let (qself, path) = self.parse_qpath(PathStyle::Expr)?;
487                 (Some(qself), path)
488             } else {
489                 // Parse an unqualified path
490                 (None, self.parse_path(PathStyle::Expr)?)
491             };
492             let hi = self.prev_span;
493             Ok(self.mk_expr(lo.to(hi), ExprKind::Path(qself, path), ThinVec::new()))
494         } else {
495             self.parse_literal_maybe_minus()
496         }
497     }
498
499     /// Parses `ident` or `ident @ pat`.
500     /// Used by the copy foo and ref foo patterns to give a good
501     /// error message when parsing mistakes like `ref foo(a, b)`.
502     fn parse_pat_ident(&mut self, binding_mode: BindingMode) -> PResult<'a, PatKind> {
503         let ident = self.parse_ident()?;
504         let sub = if self.eat(&token::At) {
505             Some(self.parse_pat(Some("binding pattern"))?)
506         } else {
507             None
508         };
509
510         // Just to be friendly, if they write something like `ref Some(i)`,
511         // we end up here with `(` as the current token.
512         // This shortly leads to a parse error. Note that if there is no explicit
513         // binding mode then we do not end up here, because the lookahead
514         // will direct us over to `parse_enum_variant()`.
515         if self.token == token::OpenDelim(token::Paren) {
516             return Err(self.span_fatal(
517                 self.prev_span,
518                 "expected identifier, found enum pattern",
519             ))
520         }
521
522         Ok(PatKind::Ident(binding_mode, ident, sub))
523     }
524
525     /// Parse a struct ("record") pattern (e.g. `Foo { ... }` or `Foo::Bar { ... }`).
526     fn parse_pat_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> {
527         if qself.is_some() {
528             let msg = "unexpected `{` after qualified path";
529             let mut err = self.fatal(msg);
530             err.span_label(self.token.span, msg);
531             return Err(err);
532         }
533
534         self.bump();
535         let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| {
536             e.emit();
537             self.recover_stmt();
538             (vec![], true)
539         });
540         self.bump();
541         Ok(PatKind::Struct(path, fields, etc))
542     }
543
544     /// Parse tuple struct or tuple variant pattern (e.g. `Foo(...)` or `Foo::Bar(...)`).
545     fn parse_pat_tuple_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> {
546         if qself.is_some() {
547             let msg = "unexpected `(` after qualified path";
548             let mut err = self.fatal(msg);
549             err.span_label(self.token.span, msg);
550             return Err(err);
551         }
552         let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat_with_or(None, true, false))?;
553         Ok(PatKind::TupleStruct(path, fields))
554     }
555
556     /// Parses the fields of a struct-like pattern.
557     fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<FieldPat>, bool)> {
558         let mut fields = Vec::new();
559         let mut etc = false;
560         let mut ate_comma = true;
561         let mut delayed_err: Option<DiagnosticBuilder<'a>> = None;
562         let mut etc_span = None;
563
564         while self.token != token::CloseDelim(token::Brace) {
565             let attrs = match self.parse_outer_attributes() {
566                 Ok(attrs) => attrs,
567                 Err(err) => {
568                     if let Some(mut delayed) = delayed_err {
569                         delayed.emit();
570                     }
571                     return Err(err);
572                 },
573             };
574             let lo = self.token.span;
575
576             // check that a comma comes after every field
577             if !ate_comma {
578                 let err = self.struct_span_err(self.prev_span, "expected `,`");
579                 if let Some(mut delayed) = delayed_err {
580                     delayed.emit();
581                 }
582                 return Err(err);
583             }
584             ate_comma = false;
585
586             if self.check(&token::DotDot) || self.token == token::DotDotDot {
587                 etc = true;
588                 let mut etc_sp = self.token.span;
589
590                 self.recover_one_fewer_dotdot();
591                 self.bump();  // `..` || `...`
592
593                 if self.token == token::CloseDelim(token::Brace) {
594                     etc_span = Some(etc_sp);
595                     break;
596                 }
597                 let token_str = self.this_token_descr();
598                 let mut err = self.fatal(&format!("expected `}}`, found {}", token_str));
599
600                 err.span_label(self.token.span, "expected `}`");
601                 let mut comma_sp = None;
602                 if self.token == token::Comma { // Issue #49257
603                     let nw_span = self.sess.source_map().span_until_non_whitespace(self.token.span);
604                     etc_sp = etc_sp.to(nw_span);
605                     err.span_label(etc_sp,
606                                    "`..` must be at the end and cannot have a trailing comma");
607                     comma_sp = Some(self.token.span);
608                     self.bump();
609                     ate_comma = true;
610                 }
611
612                 etc_span = Some(etc_sp.until(self.token.span));
613                 if self.token == token::CloseDelim(token::Brace) {
614                     // If the struct looks otherwise well formed, recover and continue.
615                     if let Some(sp) = comma_sp {
616                         err.span_suggestion_short(
617                             sp,
618                             "remove this comma",
619                             String::new(),
620                             Applicability::MachineApplicable,
621                         );
622                     }
623                     err.emit();
624                     break;
625                 } else if self.token.is_ident() && ate_comma {
626                     // Accept fields coming after `..,`.
627                     // This way we avoid "pattern missing fields" errors afterwards.
628                     // We delay this error until the end in order to have a span for a
629                     // suggested fix.
630                     if let Some(mut delayed_err) = delayed_err {
631                         delayed_err.emit();
632                         return Err(err);
633                     } else {
634                         delayed_err = Some(err);
635                     }
636                 } else {
637                     if let Some(mut err) = delayed_err {
638                         err.emit();
639                     }
640                     return Err(err);
641                 }
642             }
643
644             fields.push(match self.parse_pat_field(lo, attrs) {
645                 Ok(field) => field,
646                 Err(err) => {
647                     if let Some(mut delayed_err) = delayed_err {
648                         delayed_err.emit();
649                     }
650                     return Err(err);
651                 }
652             });
653             ate_comma = self.eat(&token::Comma);
654         }
655
656         if let Some(mut err) = delayed_err {
657             if let Some(etc_span) = etc_span {
658                 err.multipart_suggestion(
659                     "move the `..` to the end of the field list",
660                     vec![
661                         (etc_span, String::new()),
662                         (self.token.span, format!("{}.. }}", if ate_comma { "" } else { ", " })),
663                     ],
664                     Applicability::MachineApplicable,
665                 );
666             }
667             err.emit();
668         }
669         return Ok((fields, etc));
670     }
671
672     /// Recover on `...` as if it were `..` to avoid further errors.
673     /// See issue #46718.
674     fn recover_one_fewer_dotdot(&self) {
675         if self.token != token::DotDotDot {
676             return;
677         }
678
679         self.struct_span_err(self.token.span, "expected field pattern, found `...`")
680             .span_suggestion(
681                 self.token.span,
682                 "to omit remaining fields, use one fewer `.`",
683                 "..".to_owned(),
684                 Applicability::MachineApplicable
685             )
686             .emit();
687     }
688
689     fn parse_pat_field(&mut self, lo: Span, attrs: Vec<Attribute>) -> PResult<'a, FieldPat> {
690         // Check if a colon exists one ahead. This means we're parsing a fieldname.
691         let hi;
692         let (subpat, fieldname, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) {
693             // Parsing a pattern of the form "fieldname: pat"
694             let fieldname = self.parse_field_name()?;
695             self.bump();
696             let pat = self.parse_pat_with_or(None, true, false)?;
697             hi = pat.span;
698             (pat, fieldname, false)
699         } else {
700             // Parsing a pattern of the form "(box) (ref) (mut) fieldname"
701             let is_box = self.eat_keyword(kw::Box);
702             let boxed_span = self.token.span;
703             let is_ref = self.eat_keyword(kw::Ref);
704             let is_mut = self.eat_keyword(kw::Mut);
705             let fieldname = self.parse_ident()?;
706             hi = self.prev_span;
707
708             let bind_type = match (is_ref, is_mut) {
709                 (true, true) => BindingMode::ByRef(Mutability::Mutable),
710                 (true, false) => BindingMode::ByRef(Mutability::Immutable),
711                 (false, true) => BindingMode::ByValue(Mutability::Mutable),
712                 (false, false) => BindingMode::ByValue(Mutability::Immutable),
713             };
714
715             let fieldpat = self.mk_pat_ident(boxed_span.to(hi), bind_type, fieldname);
716             let subpat = if is_box {
717                 self.mk_pat(lo.to(hi), PatKind::Box(fieldpat))
718             } else {
719                 fieldpat
720             };
721             (subpat, fieldname, true)
722         };
723
724         Ok(FieldPat {
725             ident: fieldname,
726             pat: subpat,
727             is_shorthand,
728             attrs: attrs.into(),
729             id: ast::DUMMY_NODE_ID,
730             span: lo.to(hi),
731         })
732     }
733
734     pub(super) fn mk_pat_ident(&self, span: Span, bm: BindingMode, ident: Ident) -> P<Pat> {
735         self.mk_pat(span, PatKind::Ident(bm, ident, None))
736     }
737
738     fn mk_pat(&self, span: Span, node: PatKind) -> P<Pat> {
739         P(Pat { node, span, id: ast::DUMMY_NODE_ID })
740     }
741 }