• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 mod atom;
2 
3 use crate::grammar::attributes::ATTRIBUTE_FIRST;
4 
5 use super::*;
6 
7 pub(crate) use atom::{block_expr, match_arm_list};
8 pub(super) use atom::{literal, LITERAL_FIRST};
9 
10 #[derive(PartialEq, Eq)]
11 pub(super) enum Semicolon {
12     Required,
13     Optional,
14     Forbidden,
15 }
16 
17 const EXPR_FIRST: TokenSet = LHS_FIRST;
18 
expr(p: &mut Parser<'_>) -> Option<CompletedMarker>19 pub(super) fn expr(p: &mut Parser<'_>) -> Option<CompletedMarker> {
20     let r = Restrictions { forbid_structs: false, prefer_stmt: false };
21     expr_bp(p, None, r, 1).map(|(m, _)| m)
22 }
23 
expr_stmt( p: &mut Parser<'_>, m: Option<Marker>, ) -> Option<(CompletedMarker, BlockLike)>24 pub(super) fn expr_stmt(
25     p: &mut Parser<'_>,
26     m: Option<Marker>,
27 ) -> Option<(CompletedMarker, BlockLike)> {
28     let r = Restrictions { forbid_structs: false, prefer_stmt: true };
29     expr_bp(p, m, r, 1)
30 }
31 
expr_no_struct(p: &mut Parser<'_>)32 fn expr_no_struct(p: &mut Parser<'_>) {
33     let r = Restrictions { forbid_structs: true, prefer_stmt: false };
34     expr_bp(p, None, r, 1);
35 }
36 
37 /// Parses the expression in `let pattern = expression`.
38 /// It needs to be parsed with lower precedence than `&&`, so that
39 /// `if let true = true && false` is parsed as `if (let true = true) && (true)`
40 /// and not `if let true = (true && true)`.
expr_let(p: &mut Parser<'_>)41 fn expr_let(p: &mut Parser<'_>) {
42     let r = Restrictions { forbid_structs: true, prefer_stmt: false };
43     expr_bp(p, None, r, 5);
44 }
45 
stmt(p: &mut Parser<'_>, semicolon: Semicolon)46 pub(super) fn stmt(p: &mut Parser<'_>, semicolon: Semicolon) {
47     if p.eat(T![;]) {
48         return;
49     }
50 
51     let m = p.start();
52     // test attr_on_expr_stmt
53     // fn foo() {
54     //     #[A] foo();
55     //     #[B] bar!{}
56     //     #[C] #[D] {}
57     //     #[D] return ();
58     // }
59     attributes::outer_attrs(p);
60 
61     if p.at(T![let]) {
62         let_stmt(p, m, semicolon);
63         return;
64     }
65 
66     // test block_items
67     // fn a() { fn b() {} }
68     let m = match items::opt_item(p, m) {
69         Ok(()) => return,
70         Err(m) => m,
71     };
72 
73     if !p.at_ts(EXPR_FIRST) {
74         p.err_and_bump("expected expression, item or let statement");
75         m.abandon(p);
76         return;
77     }
78 
79     if let Some((cm, blocklike)) = expr_stmt(p, Some(m)) {
80         if !(p.at(T!['}']) || (semicolon != Semicolon::Required && p.at(EOF))) {
81             // test no_semi_after_block
82             // fn foo() {
83             //     if true {}
84             //     loop {}
85             //     match () {}
86             //     while true {}
87             //     for _ in () {}
88             //     {}
89             //     {}
90             //     macro_rules! test {
91             //          () => {}
92             //     }
93             //     test!{}
94             // }
95             let m = cm.precede(p);
96             match semicolon {
97                 Semicolon::Required => {
98                     if blocklike.is_block() {
99                         p.eat(T![;]);
100                     } else {
101                         p.expect(T![;]);
102                     }
103                 }
104                 Semicolon::Optional => {
105                     p.eat(T![;]);
106                 }
107                 Semicolon::Forbidden => (),
108             }
109             m.complete(p, EXPR_STMT);
110         }
111     }
112 
113     // test let_stmt
114     // fn f() { let x: i32 = 92; }
115     fn let_stmt(p: &mut Parser<'_>, m: Marker, with_semi: Semicolon) {
116         p.bump(T![let]);
117         patterns::pattern(p);
118         if p.at(T![:]) {
119             // test let_stmt_ascription
120             // fn f() { let x: i32; }
121             types::ascription(p);
122         }
123 
124         let mut expr_after_eq: Option<CompletedMarker> = None;
125         if p.eat(T![=]) {
126             // test let_stmt_init
127             // fn f() { let x = 92; }
128             expr_after_eq = expressions::expr(p);
129         }
130 
131         if p.at(T![else]) {
132             // test_err let_else_right_curly_brace
133             // fn func() { let Some(_) = {Some(1)} else { panic!("h") };}
134             if let Some(expr) = expr_after_eq {
135                 if BlockLike::is_blocklike(expr.kind()) {
136                     p.error(
137                         "right curly brace `}` before `else` in a `let...else` statement not allowed",
138                     )
139                 }
140             }
141 
142             // test let_else
143             // fn f() { let Some(x) = opt else { return }; }
144             let m = p.start();
145             p.bump(T![else]);
146             block_expr(p);
147             m.complete(p, LET_ELSE);
148         }
149 
150         match with_semi {
151             Semicolon::Forbidden => (),
152             Semicolon::Optional => {
153                 p.eat(T![;]);
154             }
155             Semicolon::Required => {
156                 p.expect(T![;]);
157             }
158         }
159         m.complete(p, LET_STMT);
160     }
161 }
162 
expr_block_contents(p: &mut Parser<'_>)163 pub(super) fn expr_block_contents(p: &mut Parser<'_>) {
164     attributes::inner_attrs(p);
165 
166     while !p.at(EOF) && !p.at(T!['}']) {
167         // test nocontentexpr
168         // fn foo(){
169         //     ;;;some_expr();;;;{;;;};;;;Ok(())
170         // }
171 
172         // test nocontentexpr_after_item
173         // fn simple_function() {
174         //     enum LocalEnum {
175         //         One,
176         //         Two,
177         //     };
178         //     fn f() {};
179         //     struct S {};
180         // }
181         stmt(p, Semicolon::Required);
182     }
183 }
184 
185 #[derive(Clone, Copy)]
186 struct Restrictions {
187     forbid_structs: bool,
188     prefer_stmt: bool,
189 }
190 
191 enum Associativity {
192     Left,
193     Right,
194 }
195 
196 /// Binding powers of operators for a Pratt parser.
197 ///
198 /// See <https://matklad.github.io/2020/04/13/simple-but-powerful-pratt-parsing.html>
199 ///
200 /// Note that Rust doesn't define associativity for some infix operators (e.g. `==` and `..`) and
201 /// requires parentheses to disambiguate. We just treat them as left associative.
202 #[rustfmt::skip]
current_op(p: &Parser<'_>) -> (u8, SyntaxKind, Associativity)203 fn current_op(p: &Parser<'_>) -> (u8, SyntaxKind, Associativity) {
204     use Associativity::*;
205     const NOT_AN_OP: (u8, SyntaxKind, Associativity) = (0, T![@], Left);
206     match p.current() {
207         T![|] if p.at(T![||])  => (3,  T![||],  Left),
208         T![|] if p.at(T![|=])  => (1,  T![|=],  Right),
209         T![|]                  => (6,  T![|],   Left),
210         T![>] if p.at(T![>>=]) => (1,  T![>>=], Right),
211         T![>] if p.at(T![>>])  => (9,  T![>>],  Left),
212         T![>] if p.at(T![>=])  => (5,  T![>=],  Left),
213         T![>]                  => (5,  T![>],   Left),
214         T![=] if p.at(T![=>])  => NOT_AN_OP,
215         T![=] if p.at(T![==])  => (5,  T![==],  Left),
216         T![=]                  => (1,  T![=],   Right),
217         T![<] if p.at(T![<=])  => (5,  T![<=],  Left),
218         T![<] if p.at(T![<<=]) => (1,  T![<<=], Right),
219         T![<] if p.at(T![<<])  => (9,  T![<<],  Left),
220         T![<]                  => (5,  T![<],   Left),
221         T![+] if p.at(T![+=])  => (1,  T![+=],  Right),
222         T![+]                  => (10, T![+],   Left),
223         T![^] if p.at(T![^=])  => (1,  T![^=],  Right),
224         T![^]                  => (7,  T![^],   Left),
225         T![%] if p.at(T![%=])  => (1,  T![%=],  Right),
226         T![%]                  => (11, T![%],   Left),
227         T![&] if p.at(T![&=])  => (1,  T![&=],  Right),
228         // If you update this, remember to update `expr_let()` too.
229         T![&] if p.at(T![&&])  => (4,  T![&&],  Left),
230         T![&]                  => (8,  T![&],   Left),
231         T![/] if p.at(T![/=])  => (1,  T![/=],  Right),
232         T![/]                  => (11, T![/],   Left),
233         T![*] if p.at(T![*=])  => (1,  T![*=],  Right),
234         T![*]                  => (11, T![*],   Left),
235         T![.] if p.at(T![..=]) => (2,  T![..=], Left),
236         T![.] if p.at(T![..])  => (2,  T![..],  Left),
237         T![!] if p.at(T![!=])  => (5,  T![!=],  Left),
238         T![-] if p.at(T![-=])  => (1,  T![-=],  Right),
239         T![-]                  => (10, T![-],   Left),
240         T![as]                 => (12, T![as],  Left),
241 
242         _                      => NOT_AN_OP
243     }
244 }
245 
246 // Parses expression with binding power of at least bp.
expr_bp( p: &mut Parser<'_>, m: Option<Marker>, mut r: Restrictions, bp: u8, ) -> Option<(CompletedMarker, BlockLike)>247 fn expr_bp(
248     p: &mut Parser<'_>,
249     m: Option<Marker>,
250     mut r: Restrictions,
251     bp: u8,
252 ) -> Option<(CompletedMarker, BlockLike)> {
253     let m = m.unwrap_or_else(|| {
254         let m = p.start();
255         attributes::outer_attrs(p);
256         m
257     });
258 
259     if !p.at_ts(EXPR_FIRST) {
260         p.err_recover("expected expression", atom::EXPR_RECOVERY_SET);
261         m.abandon(p);
262         return None;
263     }
264     let mut lhs = match lhs(p, r) {
265         Some((lhs, blocklike)) => {
266             let lhs = lhs.extend_to(p, m);
267             if r.prefer_stmt && blocklike.is_block() {
268                 // test stmt_bin_expr_ambiguity
269                 // fn f() {
270                 //     let _ = {1} & 2;
271                 //     {1} &2;
272                 // }
273                 return Some((lhs, BlockLike::Block));
274             }
275             lhs
276         }
277         None => {
278             m.abandon(p);
279             return None;
280         }
281     };
282 
283     loop {
284         let is_range = p.at(T![..]) || p.at(T![..=]);
285         let (op_bp, op, associativity) = current_op(p);
286         if op_bp < bp {
287             break;
288         }
289         // test as_precedence
290         // fn f() { let _ = &1 as *const i32; }
291         if p.at(T![as]) {
292             lhs = cast_expr(p, lhs);
293             continue;
294         }
295         let m = lhs.precede(p);
296         p.bump(op);
297 
298         // test binop_resets_statementness
299         // fn f() { v = {1}&2; }
300         r = Restrictions { prefer_stmt: false, ..r };
301 
302         if is_range {
303             // test postfix_range
304             // fn foo() {
305             //     let x = 1..;
306             //     match 1.. { _ => () };
307             //     match a.b()..S { _ => () };
308             // }
309             let has_trailing_expression =
310                 p.at_ts(EXPR_FIRST) && !(r.forbid_structs && p.at(T!['{']));
311             if !has_trailing_expression {
312                 // no RHS
313                 lhs = m.complete(p, RANGE_EXPR);
314                 break;
315             }
316         }
317 
318         let op_bp = match associativity {
319             Associativity::Left => op_bp + 1,
320             Associativity::Right => op_bp,
321         };
322         expr_bp(p, None, Restrictions { prefer_stmt: false, ..r }, op_bp);
323         lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR });
324     }
325     Some((lhs, BlockLike::NotBlock))
326 }
327 
328 const LHS_FIRST: TokenSet =
329     atom::ATOM_EXPR_FIRST.union(TokenSet::new(&[T![&], T![*], T![!], T![.], T![-], T![_]]));
330 
lhs(p: &mut Parser<'_>, r: Restrictions) -> Option<(CompletedMarker, BlockLike)>331 fn lhs(p: &mut Parser<'_>, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> {
332     let m;
333     let kind = match p.current() {
334         // test ref_expr
335         // fn foo() {
336         //     // reference operator
337         //     let _ = &1;
338         //     let _ = &mut &f();
339         //     let _ = &raw;
340         //     let _ = &raw.0;
341         //     // raw reference operator
342         //     let _ = &raw mut foo;
343         //     let _ = &raw const foo;
344         // }
345         T![&] => {
346             m = p.start();
347             p.bump(T![&]);
348             if p.at_contextual_kw(T![raw]) && (p.nth_at(1, T![mut]) || p.nth_at(1, T![const])) {
349                 p.bump_remap(T![raw]);
350                 p.bump_any();
351             } else {
352                 p.eat(T![mut]);
353             }
354             REF_EXPR
355         }
356         // test unary_expr
357         // fn foo() {
358         //     **&1;
359         //     !!true;
360         //     --1;
361         // }
362         T![*] | T![!] | T![-] => {
363             m = p.start();
364             p.bump_any();
365             PREFIX_EXPR
366         }
367         _ => {
368             // test full_range_expr
369             // fn foo() { xs[..]; }
370             for op in [T![..=], T![..]] {
371                 if p.at(op) {
372                     m = p.start();
373                     p.bump(op);
374                     if p.at_ts(EXPR_FIRST) && !(r.forbid_structs && p.at(T!['{'])) {
375                         expr_bp(p, None, r, 2);
376                     }
377                     let cm = m.complete(p, RANGE_EXPR);
378                     return Some((cm, BlockLike::NotBlock));
379                 }
380             }
381 
382             // test expression_after_block
383             // fn foo() {
384             //    let mut p = F{x: 5};
385             //    {p}.x = 10;
386             // }
387             let (lhs, blocklike) = atom::atom_expr(p, r)?;
388             let (cm, block_like) =
389                 postfix_expr(p, lhs, blocklike, !(r.prefer_stmt && blocklike.is_block()));
390             return Some((cm, block_like));
391         }
392     };
393     // parse the interior of the unary expression
394     expr_bp(p, None, r, 255);
395     let cm = m.complete(p, kind);
396     Some((cm, BlockLike::NotBlock))
397 }
398 
postfix_expr( p: &mut Parser<'_>, mut lhs: CompletedMarker, mut block_like: BlockLike, mut allow_calls: bool, ) -> (CompletedMarker, BlockLike)399 fn postfix_expr(
400     p: &mut Parser<'_>,
401     mut lhs: CompletedMarker,
402     // Calls are disallowed if the type is a block and we prefer statements because the call cannot be disambiguated from a tuple
403     // E.g. `while true {break}();` is parsed as
404     // `while true {break}; ();`
405     mut block_like: BlockLike,
406     mut allow_calls: bool,
407 ) -> (CompletedMarker, BlockLike) {
408     loop {
409         lhs = match p.current() {
410             // test stmt_postfix_expr_ambiguity
411             // fn foo() {
412             //     match () {
413             //         _ => {}
414             //         () => {}
415             //         [] => {}
416             //     }
417             // }
418             T!['('] if allow_calls => call_expr(p, lhs),
419             T!['['] if allow_calls => index_expr(p, lhs),
420             T![.] => match postfix_dot_expr::<false>(p, lhs) {
421                 Ok(it) => it,
422                 Err(it) => {
423                     lhs = it;
424                     break;
425                 }
426             },
427             T![?] => try_expr(p, lhs),
428             _ => break,
429         };
430         allow_calls = true;
431         block_like = BlockLike::NotBlock;
432     }
433     (lhs, block_like)
434 }
435 
postfix_dot_expr<const FLOAT_RECOVERY: bool>( p: &mut Parser<'_>, lhs: CompletedMarker, ) -> Result<CompletedMarker, CompletedMarker>436 fn postfix_dot_expr<const FLOAT_RECOVERY: bool>(
437     p: &mut Parser<'_>,
438     lhs: CompletedMarker,
439 ) -> Result<CompletedMarker, CompletedMarker> {
440     if !FLOAT_RECOVERY {
441         assert!(p.at(T![.]));
442     }
443     let nth1 = if FLOAT_RECOVERY { 0 } else { 1 };
444     let nth2 = if FLOAT_RECOVERY { 1 } else { 2 };
445 
446     if p.nth(nth1) == IDENT && (p.nth(nth2) == T!['('] || p.nth_at(nth2, T![::])) {
447         return Ok(method_call_expr::<FLOAT_RECOVERY>(p, lhs));
448     }
449 
450     // test await_expr
451     // fn foo() {
452     //     x.await;
453     //     x.0.await;
454     //     x.0().await?.hello();
455     //     x.0.0.await;
456     //     x.0. await;
457     // }
458     if p.nth(nth1) == T![await] {
459         let m = lhs.precede(p);
460         if !FLOAT_RECOVERY {
461             p.bump(T![.]);
462         }
463         p.bump(T![await]);
464         return Ok(m.complete(p, AWAIT_EXPR));
465     }
466 
467     if p.at(T![..=]) || p.at(T![..]) {
468         return Err(lhs);
469     }
470 
471     field_expr::<FLOAT_RECOVERY>(p, lhs)
472 }
473 
474 // test call_expr
475 // fn foo() {
476 //     let _ = f();
477 //     let _ = f()(1)(1, 2,);
478 //     let _ = f(<Foo>::func());
479 //     f(<Foo as Trait>::func());
480 // }
call_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker481 fn call_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker {
482     assert!(p.at(T!['(']));
483     let m = lhs.precede(p);
484     arg_list(p);
485     m.complete(p, CALL_EXPR)
486 }
487 
488 // test index_expr
489 // fn foo() {
490 //     x[1][2];
491 // }
index_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker492 fn index_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker {
493     assert!(p.at(T!['[']));
494     let m = lhs.precede(p);
495     p.bump(T!['[']);
496     expr(p);
497     p.expect(T![']']);
498     m.complete(p, INDEX_EXPR)
499 }
500 
501 // test method_call_expr
502 // fn foo() {
503 //     x.foo();
504 //     y.bar::<T>(1, 2,);
505 //     x.0.0.call();
506 //     x.0. call();
507 // }
method_call_expr<const FLOAT_RECOVERY: bool>( p: &mut Parser<'_>, lhs: CompletedMarker, ) -> CompletedMarker508 fn method_call_expr<const FLOAT_RECOVERY: bool>(
509     p: &mut Parser<'_>,
510     lhs: CompletedMarker,
511 ) -> CompletedMarker {
512     if FLOAT_RECOVERY {
513         assert!(p.nth(0) == IDENT && (p.nth(1) == T!['('] || p.nth_at(1, T![::])));
514     } else {
515         assert!(p.at(T![.]) && p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth_at(2, T![::])));
516     }
517     let m = lhs.precede(p);
518     if !FLOAT_RECOVERY {
519         p.bump(T![.]);
520     }
521     name_ref(p);
522     generic_args::opt_generic_arg_list(p, true);
523     if p.at(T!['(']) {
524         arg_list(p);
525     }
526     m.complete(p, METHOD_CALL_EXPR)
527 }
528 
529 // test field_expr
530 // fn foo() {
531 //     x.foo;
532 //     x.0.bar;
533 //     x.0.1;
534 //     x.0. bar;
535 //     x.0();
536 // }
field_expr<const FLOAT_RECOVERY: bool>( p: &mut Parser<'_>, lhs: CompletedMarker, ) -> Result<CompletedMarker, CompletedMarker>537 fn field_expr<const FLOAT_RECOVERY: bool>(
538     p: &mut Parser<'_>,
539     lhs: CompletedMarker,
540 ) -> Result<CompletedMarker, CompletedMarker> {
541     if !FLOAT_RECOVERY {
542         assert!(p.at(T![.]));
543     }
544     let m = lhs.precede(p);
545     if !FLOAT_RECOVERY {
546         p.bump(T![.]);
547     }
548     if p.at(IDENT) || p.at(INT_NUMBER) {
549         name_ref_or_index(p);
550     } else if p.at(FLOAT_NUMBER) {
551         return match p.split_float(m) {
552             (true, m) => {
553                 let lhs = m.complete(p, FIELD_EXPR);
554                 postfix_dot_expr::<true>(p, lhs)
555             }
556             (false, m) => Ok(m.complete(p, FIELD_EXPR)),
557         };
558     } else {
559         p.error("expected field name or number");
560     }
561     Ok(m.complete(p, FIELD_EXPR))
562 }
563 
564 // test try_expr
565 // fn foo() {
566 //     x?;
567 // }
try_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker568 fn try_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker {
569     assert!(p.at(T![?]));
570     let m = lhs.precede(p);
571     p.bump(T![?]);
572     m.complete(p, TRY_EXPR)
573 }
574 
575 // test cast_expr
576 // fn foo() {
577 //     82 as i32;
578 //     81 as i8 + 1;
579 //     79 as i16 - 1;
580 //     0x36 as u8 <= 0x37;
581 // }
cast_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker582 fn cast_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker {
583     assert!(p.at(T![as]));
584     let m = lhs.precede(p);
585     p.bump(T![as]);
586     // Use type_no_bounds(), because cast expressions are not
587     // allowed to have bounds.
588     types::type_no_bounds(p);
589     m.complete(p, CAST_EXPR)
590 }
591 
592 // test_err arg_list_recovery
593 // fn main() {
594 //     foo(bar::);
595 //     foo(bar:);
596 //     foo(bar+);
597 // }
arg_list(p: &mut Parser<'_>)598 fn arg_list(p: &mut Parser<'_>) {
599     assert!(p.at(T!['(']));
600     let m = p.start();
601     // test arg_with_attr
602     // fn main() {
603     //     foo(#[attr] 92)
604     // }
605     delimited(
606         p,
607         T!['('],
608         T![')'],
609         T![,],
610         EXPR_FIRST.union(ATTRIBUTE_FIRST),
611         |p: &mut Parser<'_>| expr(p).is_some(),
612     );
613     m.complete(p, ARG_LIST);
614 }
615 
616 // test path_expr
617 // fn foo() {
618 //     let _ = a;
619 //     let _ = a::b;
620 //     let _ = ::a::<b>;
621 //     let _ = format!();
622 // }
path_expr(p: &mut Parser<'_>, r: Restrictions) -> (CompletedMarker, BlockLike)623 fn path_expr(p: &mut Parser<'_>, r: Restrictions) -> (CompletedMarker, BlockLike) {
624     assert!(paths::is_path_start(p));
625     let m = p.start();
626     paths::expr_path(p);
627     match p.current() {
628         T!['{'] if !r.forbid_structs => {
629             record_expr_field_list(p);
630             (m.complete(p, RECORD_EXPR), BlockLike::NotBlock)
631         }
632         T![!] if !p.at(T![!=]) => {
633             let block_like = items::macro_call_after_excl(p);
634             (m.complete(p, MACRO_CALL).precede(p).complete(p, MACRO_EXPR), block_like)
635         }
636         _ => (m.complete(p, PATH_EXPR), BlockLike::NotBlock),
637     }
638 }
639 
640 // test record_lit
641 // fn foo() {
642 //     S {};
643 //     S { x };
644 //     S { x, y: 32, };
645 //     S { x, y: 32, ..Default::default() };
646 //     S { x: ::default() };
647 //     TupleStruct { 0: 1 };
648 // }
record_expr_field_list(p: &mut Parser<'_>)649 pub(crate) fn record_expr_field_list(p: &mut Parser<'_>) {
650     assert!(p.at(T!['{']));
651     let m = p.start();
652     p.bump(T!['{']);
653     while !p.at(EOF) && !p.at(T!['}']) {
654         let m = p.start();
655         // test record_literal_field_with_attr
656         // fn main() {
657         //     S { #[cfg(test)] field: 1 }
658         // }
659         attributes::outer_attrs(p);
660 
661         match p.current() {
662             IDENT | INT_NUMBER => {
663                 // test_err record_literal_missing_ellipsis_recovery
664                 // fn main() {
665                 //     S { S::default() }
666                 // }
667                 if p.nth_at(1, T![::]) {
668                     m.abandon(p);
669                     p.expect(T![..]);
670                     expr(p);
671                 } else {
672                     // test_err record_literal_before_ellipsis_recovery
673                     // fn main() {
674                     //     S { field ..S::default() }
675                     // }
676                     if p.nth_at(1, T![:]) || p.nth_at(1, T![..]) {
677                         name_ref_or_index(p);
678                         p.expect(T![:]);
679                     }
680                     expr(p);
681                     m.complete(p, RECORD_EXPR_FIELD);
682                 }
683             }
684             T![.] if p.at(T![..]) => {
685                 m.abandon(p);
686                 p.bump(T![..]);
687 
688                 // test destructuring_assignment_struct_rest_pattern
689                 // fn foo() {
690                 //     S { .. } = S {};
691                 // }
692 
693                 // We permit `.. }` on the left-hand side of a destructuring assignment.
694                 if !p.at(T!['}']) {
695                     expr(p);
696                 }
697             }
698             T!['{'] => {
699                 error_block(p, "expected a field");
700                 m.abandon(p);
701             }
702             _ => {
703                 p.err_and_bump("expected identifier");
704                 m.abandon(p);
705             }
706         }
707         if !p.at(T!['}']) {
708             p.expect(T![,]);
709         }
710     }
711     p.expect(T!['}']);
712     m.complete(p, RECORD_EXPR_FIELD_LIST);
713 }
714