parser/grammar/
expressions.rs

1mod atom;
2
3use crate::grammar::attributes::ATTRIBUTE_FIRST;
4
5use super::*;
6
7pub(super) use atom::{EXPR_RECOVERY_SET, LITERAL_FIRST, literal, parse_asm_expr};
8pub(crate) use atom::{block_expr, match_arm_list};
9
10#[derive(PartialEq, Eq)]
11pub(super) enum Semicolon {
12    Required,
13    Optional,
14    Forbidden,
15}
16
17const EXPR_FIRST: TokenSet = LHS_FIRST;
18
19pub(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
24pub(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
32fn 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)`.
41fn expr_let(p: &mut Parser<'_>) {
42    let r = Restrictions { forbid_structs: true, prefer_stmt: false };
43    expr_bp(p, None, r, 5);
44}
45
46pub(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]) || (p.at(T![super]) && p.nth_at(1, T![let])) {
62        let_stmt(p, semicolon);
63        m.complete(p, LET_STMT);
64        return;
65    }
66
67    // test block_items
68    // fn a() { fn b() {} }
69    let m = match items::opt_item(p, m, false) {
70        Ok(()) => return,
71        Err(m) => m,
72    };
73
74    if !p.at_ts(EXPR_FIRST) {
75        p.err_and_bump("expected expression, item or let statement");
76        m.abandon(p);
77        return;
78    }
79
80    if let Some((cm, blocklike)) = expr_stmt(p, Some(m))
81        && !(p.at(T!['}']) || (semicolon != Semicolon::Required && p.at(EOF)))
82    {
83        // test no_semi_after_block
84        // fn foo() {
85        //     if true {}
86        //     loop {}
87        //     match () {}
88        //     while true {}
89        //     for _ in () {}
90        //     {}
91        //     {}
92        //     macro_rules! test {
93        //          () => {}
94        //     }
95        //     test!{}
96        // }
97        let m = cm.precede(p);
98        match semicolon {
99            Semicolon::Required => {
100                if blocklike.is_block() {
101                    p.eat(T![;]);
102                } else {
103                    p.expect(T![;]);
104                }
105            }
106            Semicolon::Optional => {
107                p.eat(T![;]);
108            }
109            Semicolon::Forbidden => (),
110        }
111        m.complete(p, EXPR_STMT);
112    }
113}
114
115// test let_stmt
116// fn f() { let x: i32 = 92; super let y; super::foo; }
117pub(super) fn let_stmt(p: &mut Parser<'_>, with_semi: Semicolon) {
118    p.eat(T![super]);
119    p.bump(T![let]);
120    patterns::pattern(p);
121    if p.at(T![:]) {
122        // test let_stmt_ascription
123        // fn f() { let x: i32; }
124        types::ascription(p);
125    }
126
127    let mut expr_after_eq: Option<CompletedMarker> = None;
128    if p.eat(T![=]) {
129        // test let_stmt_init
130        // fn f() { let x = 92; }
131        expr_after_eq = expressions::expr(p);
132    }
133
134    if p.at(T![else]) {
135        // test_err let_else_right_curly_brace
136        // fn func() { let Some(_) = {Some(1)} else { panic!("h") };}
137        if let Some(expr) = expr_after_eq
138            && let Some(token) = expr.last_token(p)
139            && token == T!['}']
140        {
141            p.error("right curly brace `}` before `else` in a `let...else` statement not allowed")
142        }
143
144        // test let_else
145        // fn f() { let Some(x) = opt else { return }; }
146        let m = p.start();
147        p.bump(T![else]);
148        block_expr(p);
149        m.complete(p, LET_ELSE);
150    }
151
152    match with_semi {
153        Semicolon::Forbidden => (),
154        Semicolon::Optional => {
155            p.eat(T![;]);
156        }
157        Semicolon::Required => {
158            p.expect(T![;]);
159        }
160    }
161}
162
163pub(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)]
186struct Restrictions {
187    forbid_structs: bool,
188    prefer_stmt: bool,
189}
190
191enum 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]
203fn 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![==])  => (5,  T![==],  Left),
215        T![=] if !p.at(T![=>]) => (1,  T![=],   Right),
216        T![<] if p.at(T![<=])  => (5,  T![<=],  Left),
217        T![<] if p.at(T![<<=]) => (1,  T![<<=], Right),
218        T![<] if p.at(T![<<])  => (9,  T![<<],  Left),
219        T![<]                  => (5,  T![<],   Left),
220        T![+] if p.at(T![+=])  => (1,  T![+=],  Right),
221        T![+]                  => (10, T![+],   Left),
222        T![^] if p.at(T![^=])  => (1,  T![^=],  Right),
223        T![^]                  => (7,  T![^],   Left),
224        T![%] if p.at(T![%=])  => (1,  T![%=],  Right),
225        T![%]                  => (11, T![%],   Left),
226        T![&] if p.at(T![&=])  => (1,  T![&=],  Right),
227        // If you update this, remember to update `expr_let()` too.
228        T![&] if p.at(T![&&])  => (4,  T![&&],  Left),
229        T![&]                  => (8,  T![&],   Left),
230        T![/] if p.at(T![/=])  => (1,  T![/=],  Right),
231        T![/]                  => (11, T![/],   Left),
232        T![*] if p.at(T![*=])  => (1,  T![*=],  Right),
233        T![*]                  => (11, T![*],   Left),
234        T![.] if p.at(T![..=]) => (2,  T![..=], Left),
235        T![.] if p.at(T![..])  => (2,  T![..],  Left),
236        T![!] if p.at(T![!=])  => (5,  T![!=],  Left),
237        T![-] if p.at(T![-=])  => (1,  T![-=],  Right),
238        T![-]                  => (10, T![-],   Left),
239        T![as]                 => (12, T![as],  Left),
240
241        _                      => NOT_AN_OP
242    }
243}
244
245// Parses expression with binding power of at least bp.
246fn expr_bp(
247    p: &mut Parser<'_>,
248    m: Option<Marker>,
249    r: Restrictions,
250    bp: u8,
251) -> Option<(CompletedMarker, BlockLike)> {
252    let m = m.unwrap_or_else(|| {
253        let m = p.start();
254        attributes::outer_attrs(p);
255        m
256    });
257
258    if !p.at_ts(EXPR_FIRST) {
259        p.err_recover("expected expression", atom::EXPR_RECOVERY_SET);
260        m.abandon(p);
261        return None;
262    }
263    let mut lhs = match lhs(p, r) {
264        Some((lhs, blocklike)) => {
265            let lhs = lhs.extend_to(p, m);
266            if r.prefer_stmt && blocklike.is_block() {
267                // test stmt_bin_expr_ambiguity
268                // fn f() {
269                //     let _ = {1} & 2;
270                //     {1} &2;
271                // }
272                return Some((lhs, BlockLike::Block));
273            }
274            lhs
275        }
276        None => {
277            m.abandon(p);
278            return None;
279        }
280    };
281
282    loop {
283        let is_range = p.at(T![..]) || p.at(T![..=]);
284        let (op_bp, op, associativity) = current_op(p);
285        if op_bp < bp {
286            break;
287        }
288        // test as_precedence
289        // fn f() { let _ = &1 as *const i32; }
290        if p.at(T![as]) {
291            lhs = cast_expr(p, lhs);
292            continue;
293        }
294        let m = lhs.precede(p);
295        p.bump(op);
296
297        if is_range {
298            // test postfix_range
299            // fn foo() {
300            //     let x = 1..;
301            //     match 1.. { _ => () };
302            //     match a.b()..S { _ => () };
303            // }
304            let has_trailing_expression =
305                p.at_ts(EXPR_FIRST) && !(r.forbid_structs && p.at(T!['{']));
306            if !has_trailing_expression {
307                // no RHS
308                lhs = m.complete(p, RANGE_EXPR);
309                break;
310            }
311        }
312
313        let op_bp = match associativity {
314            Associativity::Left => op_bp + 1,
315            Associativity::Right => op_bp,
316        };
317
318        // test binop_resets_statementness
319        // fn f() { v = {1}&2; }
320        expr_bp(p, None, Restrictions { prefer_stmt: false, ..r }, op_bp);
321        lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR });
322    }
323    Some((lhs, BlockLike::NotBlock))
324}
325
326const LHS_FIRST: TokenSet =
327    atom::ATOM_EXPR_FIRST.union(TokenSet::new(&[T![&], T![*], T![!], T![.], T![-], T![_]]));
328
329fn lhs(p: &mut Parser<'_>, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> {
330    let m;
331    let kind = match p.current() {
332        // test ref_expr
333        // fn foo() {
334        //     // reference operator
335        //     let _ = &1;
336        //     let _ = &mut &f();
337        //     let _ = &raw;
338        //     let _ = &raw.0;
339        //     // raw reference operator
340        //     let _ = &raw mut foo;
341        //     let _ = &raw const foo;
342        //     let _ = &raw foo;
343        // }
344        T![&] => {
345            m = p.start();
346            p.bump(T![&]);
347            if p.at_contextual_kw(T![raw]) {
348                if [T![mut], T![const]].contains(&p.nth(1)) {
349                    p.bump_remap(T![raw]);
350                    p.bump_any();
351                } else if p.nth_at(1, SyntaxKind::IDENT) {
352                    // we treat raw as keyword in this case
353                    // &raw foo;
354                    p.bump_remap(T![raw]);
355                }
356            } else {
357                p.eat(T![mut]);
358            }
359            REF_EXPR
360        }
361        // test unary_expr
362        // fn foo() {
363        //     **&1;
364        //     !!true;
365        //     --1;
366        // }
367        T![*] | T![!] | T![-] => {
368            m = p.start();
369            p.bump_any();
370            PREFIX_EXPR
371        }
372        _ => {
373            // test full_range_expr
374            // fn foo() { xs[..]; }
375            for op in [T![..=], T![..]] {
376                if p.at(op) {
377                    m = p.start();
378                    p.bump(op);
379
380                    // test closure_range_method_call
381                    // fn foo() {
382                    //     || .. .method();
383                    //     || .. .field;
384                    // }
385                    let has_access_after = p.at(T![.]) && p.nth_at(1, SyntaxKind::IDENT);
386                    let struct_forbidden = r.forbid_structs && p.at(T!['{']);
387                    if p.at_ts(EXPR_FIRST) && !has_access_after && !struct_forbidden {
388                        expr_bp(p, None, r, 2);
389                    }
390                    let cm = m.complete(p, RANGE_EXPR);
391                    return Some((cm, BlockLike::NotBlock));
392                }
393            }
394
395            // test expression_after_block
396            // fn foo() {
397            //    let mut p = F{x: 5};
398            //    {p}.x = 10;
399            // }
400            let (lhs, blocklike) = atom::atom_expr(p, r)?;
401            let (cm, block_like) =
402                postfix_expr(p, lhs, blocklike, !(r.prefer_stmt && blocklike.is_block()));
403            return Some((cm, block_like));
404        }
405    };
406    // parse the interior of the unary expression
407    expr_bp(p, None, r, 255);
408    let cm = m.complete(p, kind);
409    Some((cm, BlockLike::NotBlock))
410}
411
412fn postfix_expr(
413    p: &mut Parser<'_>,
414    mut lhs: CompletedMarker,
415    // Calls are disallowed if the type is a block and we prefer statements because the call cannot be disambiguated from a tuple
416    // E.g. `while true {break}();` is parsed as
417    // `while true {break}; ();`
418    mut block_like: BlockLike,
419    mut allow_calls: bool,
420) -> (CompletedMarker, BlockLike) {
421    loop {
422        lhs = match p.current() {
423            // test stmt_postfix_expr_ambiguity
424            // fn foo() {
425            //     match () {
426            //         _ => {}
427            //         () => {}
428            //         [] => {}
429            //     }
430            // }
431            T!['('] if allow_calls => call_expr(p, lhs),
432            T!['['] if allow_calls => index_expr(p, lhs),
433            // test_err postfix_dot_expr_ambiguity
434            // fn foo() {
435            //     x.
436            //     ()
437            // }
438            T![.] => match postfix_dot_expr::<false>(p, lhs) {
439                Ok(it) => it,
440                Err(it) => {
441                    lhs = it;
442                    break;
443                }
444            },
445            T![?] => try_expr(p, lhs),
446            _ => break,
447        };
448        allow_calls = true;
449        block_like = BlockLike::NotBlock;
450    }
451    (lhs, block_like)
452}
453
454fn postfix_dot_expr<const FLOAT_RECOVERY: bool>(
455    p: &mut Parser<'_>,
456    lhs: CompletedMarker,
457) -> Result<CompletedMarker, CompletedMarker> {
458    if !FLOAT_RECOVERY {
459        assert!(p.at(T![.]));
460    }
461    let nth1 = if FLOAT_RECOVERY { 0 } else { 1 };
462    let nth2 = if FLOAT_RECOVERY { 1 } else { 2 };
463
464    if PATH_NAME_REF_KINDS.contains(p.nth(nth1))
465        && (p.nth(nth2) == T!['('] || p.nth_at(nth2, T![::]))
466        || p.nth(nth1) == T!['(']
467    {
468        return Ok(method_call_expr::<FLOAT_RECOVERY>(p, lhs));
469    }
470
471    // test await_expr
472    // fn foo() {
473    //     x.await;
474    //     x.0.await;
475    //     x.0().await?.hello();
476    //     x.0.0.await;
477    //     x.0. await;
478    // }
479    if p.nth(nth1) == T![await] {
480        let m = lhs.precede(p);
481        if !FLOAT_RECOVERY {
482            p.bump(T![.]);
483        }
484        p.bump(T![await]);
485        return Ok(m.complete(p, AWAIT_EXPR));
486    }
487
488    if p.at(T![..=]) || p.at(T![..]) {
489        return Err(lhs);
490    }
491
492    field_expr::<FLOAT_RECOVERY>(p, lhs)
493}
494
495// test call_expr
496// fn foo() {
497//     let _ = f();
498//     let _ = f()(1)(1, 2,);
499//     let _ = f(<Foo>::func());
500//     f(<Foo as Trait>::func());
501// }
502fn call_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker {
503    assert!(p.at(T!['(']));
504    let m = lhs.precede(p);
505    arg_list(p);
506    m.complete(p, CALL_EXPR)
507}
508
509// test index_expr
510// fn foo() {
511//     x[1][2];
512// }
513fn index_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker {
514    assert!(p.at(T!['[']));
515    let m = lhs.precede(p);
516    p.bump(T!['[']);
517    expr(p);
518    p.expect(T![']']);
519    m.complete(p, INDEX_EXPR)
520}
521
522// test method_call_expr
523// fn foo() {
524//     x.foo();
525//     y.bar::<T>(1, 2,);
526//     x.0.0.call();
527//     x.0. call();
528//     x.0()
529// }
530fn method_call_expr<const FLOAT_RECOVERY: bool>(
531    p: &mut Parser<'_>,
532    lhs: CompletedMarker,
533) -> CompletedMarker {
534    if FLOAT_RECOVERY {
535        assert!(
536            p.at_ts(PATH_NAME_REF_KINDS) && (p.nth(1) == T!['('] || p.nth_at(1, T![::]))
537                || p.current() == T!['(']
538        );
539    } else {
540        assert!(p.at(T![.]));
541        assert!(
542            PATH_NAME_REF_KINDS.contains(p.nth(1)) && (p.nth(2) == T!['('] || p.nth_at(2, T![::]))
543                || p.nth(1) == T!['(']
544        );
545    }
546    let m = lhs.precede(p);
547    if !FLOAT_RECOVERY {
548        p.bump(T![.]);
549    }
550    if p.at_ts(PATH_NAME_REF_KINDS) {
551        name_ref_mod_path(p);
552    } else {
553        p.error("expected method name, field name or number");
554    }
555    generic_args::opt_generic_arg_list_expr(p);
556    if p.at(T!['(']) {
557        arg_list(p);
558    } else {
559        // emit an error when argument list is missing
560
561        // test_err method_call_missing_argument_list
562        // fn func() {
563        //     foo.bar::<>
564        //     foo.bar::<i32>;
565        // }
566        p.error("expected argument list");
567    }
568    m.complete(p, METHOD_CALL_EXPR)
569}
570
571// test field_expr
572// fn foo() {
573//     x.self;
574//     x.Self;
575//     x.foo;
576//     x.0.bar;
577//     x.0.1;
578//     x.0. bar;
579//     x.0();
580// }
581fn field_expr<const FLOAT_RECOVERY: bool>(
582    p: &mut Parser<'_>,
583    lhs: CompletedMarker,
584) -> Result<CompletedMarker, CompletedMarker> {
585    if !FLOAT_RECOVERY {
586        assert!(p.at(T![.]));
587    }
588    let m = lhs.precede(p);
589    if !FLOAT_RECOVERY {
590        p.bump(T![.]);
591    }
592    if p.at_ts(PATH_NAME_REF_OR_INDEX_KINDS) {
593        name_ref_mod_path_or_index(p);
594    } else if p.at(FLOAT_NUMBER) {
595        return match p.split_float(m) {
596            (true, m) => {
597                let lhs = m.complete(p, FIELD_EXPR);
598                postfix_dot_expr::<true>(p, lhs)
599            }
600            (false, m) => Ok(m.complete(p, FIELD_EXPR)),
601        };
602    } else {
603        p.error("expected field name or number");
604    }
605    Ok(m.complete(p, FIELD_EXPR))
606}
607
608// test try_expr
609// fn foo() {
610//     x?;
611// }
612fn try_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker {
613    assert!(p.at(T![?]));
614    let m = lhs.precede(p);
615    p.bump(T![?]);
616    m.complete(p, TRY_EXPR)
617}
618
619// test cast_expr
620// fn foo() {
621//     82 as i32;
622//     81 as i8 + 1;
623//     79 as i16 - 1;
624//     0x36 as u8 <= 0x37;
625// }
626fn cast_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker {
627    assert!(p.at(T![as]));
628    let m = lhs.precede(p);
629    p.bump(T![as]);
630    // Use type_no_bounds(), because cast expressions are not
631    // allowed to have bounds.
632    types::type_no_bounds(p);
633    m.complete(p, CAST_EXPR)
634}
635
636// test_err arg_list_recovery
637// fn main() {
638//     foo(bar::);
639//     foo(bar:);
640//     foo(bar+);
641//     foo(a, , b);
642// }
643fn arg_list(p: &mut Parser<'_>) {
644    assert!(p.at(T!['(']));
645    let m = p.start();
646    // test arg_with_attr
647    // fn main() {
648    //     foo(#[attr] 92)
649    // }
650    delimited(
651        p,
652        T!['('],
653        T![')'],
654        T![,],
655        || "expected expression".into(),
656        EXPR_FIRST.union(ATTRIBUTE_FIRST),
657        |p| expr(p).is_some(),
658    );
659    m.complete(p, ARG_LIST);
660}
661
662// test path_expr
663// fn foo() {
664//     let _ = a;
665//     let _ = a::b;
666//     let _ = ::a::<b>;
667//     let _ = format!();
668// }
669fn path_expr(p: &mut Parser<'_>, r: Restrictions) -> (CompletedMarker, BlockLike) {
670    assert!(paths::is_path_start(p));
671    let m = p.start();
672    paths::expr_path(p);
673    match p.current() {
674        T!['{'] if !r.forbid_structs => {
675            record_expr_field_list(p);
676            (m.complete(p, RECORD_EXPR), BlockLike::NotBlock)
677        }
678        T![!] if !p.at(T![!=]) => {
679            let block_like = items::macro_call_after_excl(p);
680            (m.complete(p, MACRO_CALL).precede(p).complete(p, MACRO_EXPR), block_like)
681        }
682        _ => (m.complete(p, PATH_EXPR), BlockLike::NotBlock),
683    }
684}
685
686// test record_lit
687// fn foo() {
688//     S {};
689//     S { x };
690//     S { x, y: 32, };
691//     S { x, y: 32, ..Default::default() };
692//     S { x, y: 32, .. };
693//     S { .. };
694//     S { x: ::default() };
695//     TupleStruct { 0: 1 };
696// }
697pub(crate) fn record_expr_field_list(p: &mut Parser<'_>) {
698    assert!(p.at(T!['{']));
699    let m = p.start();
700    p.bump(T!['{']);
701    while !p.at(EOF) && !p.at(T!['}']) {
702        let m = p.start();
703        // test record_literal_field_with_attr
704        // fn main() {
705        //     S { #[cfg(test)] field: 1 }
706        // }
707        attributes::outer_attrs(p);
708
709        match p.current() {
710            IDENT | INT_NUMBER if p.nth_at(1, T![::]) => {
711                // test_err record_literal_missing_ellipsis_recovery
712                // fn main() {
713                //     S { S::default() };
714                //     S { 0::default() };
715                // }
716                m.abandon(p);
717                p.expect(T![..]);
718                expr(p);
719            }
720            IDENT | INT_NUMBER if p.nth_at(1, T![..]) => {
721                // test_err record_literal_before_ellipsis_recovery
722                // fn main() {
723                //     S { field ..S::default() }
724                //     S { 0 ..S::default() }
725                //     S { field .. }
726                //     S { 0 .. }
727                // }
728                name_ref_or_index(p);
729                p.error("expected `:`");
730                m.complete(p, RECORD_EXPR_FIELD);
731            }
732            IDENT | INT_NUMBER => {
733                // test_err record_literal_field_eq_recovery
734                // fn main() {
735                //     S { field = foo }
736                //     S { 0 = foo }
737                // }
738                if p.nth_at(1, T![:]) {
739                    name_ref_or_index(p);
740                    p.bump(T![:]);
741                } else if p.nth_at(1, T![=]) {
742                    name_ref_or_index(p);
743                    p.err_and_bump("expected `:`");
744                }
745                expr(p);
746                m.complete(p, RECORD_EXPR_FIELD);
747            }
748            T![.] if p.at(T![..]) => {
749                m.abandon(p);
750                p.bump(T![..]);
751
752                // test destructuring_assignment_struct_rest_pattern
753                // fn foo() {
754                //     S { .. } = S {};
755                // }
756
757                // test struct_initializer_with_defaults
758                // fn foo() {
759                //     let _s = S { .. };
760                // }
761
762                // We permit `.. }` on the left-hand side of a destructuring assignment
763                // or defaults values.
764                if !p.at(T!['}']) {
765                    expr(p);
766
767                    if p.at(T![,]) {
768                        // test_err comma_after_functional_update_syntax
769                        // fn foo() {
770                        //     S { ..x, };
771                        //     S { ..x, a: 0 }
772                        // }
773
774                        // test_err comma_after_default_values_syntax
775                        // fn foo() {
776                        //     S { .., };
777                        //     S { .., a: 0 }
778                        // }
779
780                        // Do not bump, so we can support additional fields after this comma.
781                        p.error("cannot use a comma after the base struct");
782                    }
783                }
784            }
785            T!['{'] => {
786                error_block(p, "expected a field");
787                m.abandon(p);
788            }
789            _ => {
790                p.err_and_bump("expected identifier");
791                m.abandon(p);
792            }
793        }
794        if !p.at(T!['}']) {
795            p.expect(T![,]);
796        }
797    }
798    p.expect(T!['}']);
799    m.complete(p, RECORD_EXPR_FIELD_LIST);
800}