Skip to main content

syn/
expr.rs

1use crate::attr::Attribute;
2#[cfg(feature = "full")]
3use crate::generics::BoundLifetimes;
4use crate::ident::Ident;
5#[cfg(feature = "full")]
6use crate::lifetime::Lifetime;
7use crate::lit::Lit;
8use crate::mac::Macro;
9use crate::op::{BinOp, UnOp};
10#[cfg(feature = "full")]
11use crate::pat::Pat;
12use crate::path::{AngleBracketedGenericArguments, Path, QSelf};
13use crate::punctuated::Punctuated;
14#[cfg(feature = "full")]
15use crate::stmt::Block;
16use crate::token;
17#[cfg(feature = "full")]
18use crate::ty::ReturnType;
19use crate::ty::Type;
20use proc_macro2::{Span, TokenStream};
21#[cfg(feature = "printing")]
22use quote::IdentFragment;
23#[cfg(feature = "printing")]
24use std::fmt::{self, Display};
25use std::hash::{Hash, Hasher};
26#[cfg(all(feature = "parsing", feature = "full"))]
27use std::mem;
28
29ast_enum_of_structs! {
30    /// A Rust expression.
31    ///
32    /// *This type is available only if Syn is built with the `"derive"` or `"full"`
33    /// feature, but most of the variants are not available unless "full" is enabled.*
34    ///
35    /// # Syntax tree enums
36    ///
37    /// This type is a syntax tree enum. In Syn this and other syntax tree enums
38    /// are designed to be traversed using the following rebinding idiom.
39    ///
40    /// ```
41    /// # use syn::Expr;
42    /// #
43    /// # fn example(expr: Expr) {
44    /// # const IGNORE: &str = stringify! {
45    /// let expr: Expr = /* ... */;
46    /// # };
47    /// match expr {
48    ///     Expr::MethodCall(expr) => {
49    ///         /* ... */
50    ///     }
51    ///     Expr::Cast(expr) => {
52    ///         /* ... */
53    ///     }
54    ///     Expr::If(expr) => {
55    ///         /* ... */
56    ///     }
57    ///
58    ///     /* ... */
59    ///     # _ => {}
60    /// # }
61    /// # }
62    /// ```
63    ///
64    /// We begin with a variable `expr` of type `Expr` that has no fields
65    /// (because it is an enum), and by matching on it and rebinding a variable
66    /// with the same name `expr` we effectively imbue our variable with all of
67    /// the data fields provided by the variant that it turned out to be. So for
68    /// example above if we ended up in the `MethodCall` case then we get to use
69    /// `expr.receiver`, `expr.args` etc; if we ended up in the `If` case we get
70    /// to use `expr.cond`, `expr.then_branch`, `expr.else_branch`.
71    ///
72    /// This approach avoids repeating the variant names twice on every line.
73    ///
74    /// ```
75    /// # use syn::{Expr, ExprMethodCall};
76    /// #
77    /// # fn example(expr: Expr) {
78    /// // Repetitive; recommend not doing this.
79    /// match expr {
80    ///     Expr::MethodCall(ExprMethodCall { method, args, .. }) => {
81    /// # }
82    /// # _ => {}
83    /// # }
84    /// # }
85    /// ```
86    ///
87    /// In general, the name to which a syntax tree enum variant is bound should
88    /// be a suitable name for the complete syntax tree enum type.
89    ///
90    /// ```
91    /// # use syn::{Expr, ExprField};
92    /// #
93    /// # fn example(discriminant: ExprField) {
94    /// // Binding is called `base` which is the name I would use if I were
95    /// // assigning `*discriminant.base` without an `if let`.
96    /// if let Expr::Tuple(base) = *discriminant.base {
97    /// # }
98    /// # }
99    /// ```
100    ///
101    /// A sign that you may not be choosing the right variable names is if you
102    /// see names getting repeated in your code, like accessing
103    /// `receiver.receiver` or `pat.pat` or `cond.cond`.
104    #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
105    #[non_exhaustive]
106    pub enum Expr {
107        /// A slice literal expression: `[a, b, c, d]`.
108        Array(ExprArray),
109
110        /// An assignment expression: `a = compute()`.
111        Assign(ExprAssign),
112
113        /// An async block: `async { ... }`.
114        Async(ExprAsync),
115
116        /// An await expression: `fut.await`.
117        Await(ExprAwait),
118
119        /// A binary operation: `a + b`, `a += b`.
120        Binary(ExprBinary),
121
122        /// A blocked scope: `{ ... }`.
123        Block(ExprBlock),
124
125        /// A `break`, with an optional label to break and an optional
126        /// expression.
127        Break(ExprBreak),
128
129        /// A function call expression: `invoke(a, b)`.
130        Call(ExprCall),
131
132        /// A cast expression: `foo as f64`.
133        Cast(ExprCast),
134
135        /// A closure expression: `|a, b| a + b`.
136        Closure(ExprClosure),
137
138        /// A const block: `const { ... }`.
139        Const(ExprConst),
140
141        /// A `continue`, with an optional label.
142        Continue(ExprContinue),
143
144        /// Access of a named struct field (`obj.k`) or unnamed tuple struct
145        /// field (`obj.0`).
146        Field(ExprField),
147
148        /// A for loop: `for pat in expr { ... }`.
149        ForLoop(ExprForLoop),
150
151        /// An expression contained within invisible delimiters.
152        ///
153        /// This variant is important for faithfully representing the precedence
154        /// of expressions and is related to `None`-delimited spans in a
155        /// `TokenStream`.
156        Group(ExprGroup),
157
158        /// An `if` expression with an optional `else` block: `if expr { ... }
159        /// else { ... }`.
160        ///
161        /// The `else` branch expression may only be an `If` or `Block`
162        /// expression, not any of the other types of expression.
163        If(ExprIf),
164
165        /// A square bracketed indexing expression: `vector[2]`.
166        Index(ExprIndex),
167
168        /// The inferred value of a const generic argument, denoted `_`.
169        Infer(ExprInfer),
170
171        /// A `let` guard: `let Some(x) = opt`.
172        Let(ExprLet),
173
174        /// A literal in place of an expression: `1`, `"foo"`.
175        Lit(ExprLit),
176
177        /// Conditionless loop: `loop { ... }`.
178        Loop(ExprLoop),
179
180        /// A macro invocation expression: `format!("{}", q)`.
181        Macro(ExprMacro),
182
183        /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
184        Match(ExprMatch),
185
186        /// A method call expression: `x.foo::<T>(a, b)`.
187        MethodCall(ExprMethodCall),
188
189        /// A parenthesized expression: `(a + b)`.
190        Paren(ExprParen),
191
192        /// A path like `std::mem::replace` possibly containing generic
193        /// parameters and a qualified self-type.
194        ///
195        /// A plain identifier like `x` is a path of length 1.
196        Path(ExprPath),
197
198        /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
199        Range(ExprRange),
200
201        /// A referencing operation: `&a` or `&mut a`.
202        Reference(ExprReference),
203
204        /// An array literal constructed from one repeated element: `[0u8; N]`.
205        Repeat(ExprRepeat),
206
207        /// A `return`, with an optional value to be returned.
208        Return(ExprReturn),
209
210        /// A struct literal expression: `Point { x: 1, y: 1 }`.
211        ///
212        /// The `rest` provides the value of the remaining fields as in `S { a:
213        /// 1, b: 1, ..rest }`.
214        Struct(ExprStruct),
215
216        /// A try-expression: `expr?`.
217        Try(ExprTry),
218
219        /// A try block: `try { ... }`.
220        TryBlock(ExprTryBlock),
221
222        /// A tuple expression: `(a, b, c, d)`.
223        Tuple(ExprTuple),
224
225        /// A unary operation: `!x`, `*x`.
226        Unary(ExprUnary),
227
228        /// An unsafe block: `unsafe { ... }`.
229        Unsafe(ExprUnsafe),
230
231        /// Tokens in expression position not interpreted by Syn.
232        Verbatim(TokenStream),
233
234        /// A while loop: `while expr { ... }`.
235        While(ExprWhile),
236
237        /// A yield expression: `yield expr`.
238        Yield(ExprYield),
239
240        // For testing exhaustiveness in downstream code, use the following idiom:
241        //
242        //     match expr {
243        //         #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
244        //
245        //         Expr::Array(expr) => {...}
246        //         Expr::Assign(expr) => {...}
247        //         ...
248        //         Expr::Yield(expr) => {...}
249        //
250        //         _ => { /* some sane fallback */ }
251        //     }
252        //
253        // This way we fail your tests but don't break your library when adding
254        // a variant. You will be notified by a test failure when a variant is
255        // added, so that you can add code to handle it, but your library will
256        // continue to compile and work for downstream users in the interim.
257    }
258}
259
260ast_struct! {
261    /// A slice literal expression: `[a, b, c, d]`.
262    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
263    pub struct ExprArray #full {
264        pub attrs: Vec<Attribute>,
265        pub bracket_token: token::Bracket,
266        pub elems: Punctuated<Expr, Token![,]>,
267    }
268}
269
270ast_struct! {
271    /// An assignment expression: `a = compute()`.
272    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
273    pub struct ExprAssign #full {
274        pub attrs: Vec<Attribute>,
275        pub left: Box<Expr>,
276        pub eq_token: Token![=],
277        pub right: Box<Expr>,
278    }
279}
280
281ast_struct! {
282    /// An async block: `async { ... }`.
283    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
284    pub struct ExprAsync #full {
285        pub attrs: Vec<Attribute>,
286        pub async_token: Token![async],
287        pub capture: Option<Token![move]>,
288        pub block: Block,
289    }
290}
291
292ast_struct! {
293    /// An await expression: `fut.await`.
294    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
295    pub struct ExprAwait #full {
296        pub attrs: Vec<Attribute>,
297        pub base: Box<Expr>,
298        pub dot_token: Token![.],
299        pub await_token: Token![await],
300    }
301}
302
303ast_struct! {
304    /// A binary operation: `a + b`, `a += b`.
305    #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
306    pub struct ExprBinary {
307        pub attrs: Vec<Attribute>,
308        pub left: Box<Expr>,
309        pub op: BinOp,
310        pub right: Box<Expr>,
311    }
312}
313
314ast_struct! {
315    /// A blocked scope: `{ ... }`.
316    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
317    pub struct ExprBlock #full {
318        pub attrs: Vec<Attribute>,
319        pub label: Option<Label>,
320        pub block: Block,
321    }
322}
323
324ast_struct! {
325    /// A `break`, with an optional label to break and an optional
326    /// expression.
327    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
328    pub struct ExprBreak #full {
329        pub attrs: Vec<Attribute>,
330        pub break_token: Token![break],
331        pub label: Option<Lifetime>,
332        pub expr: Option<Box<Expr>>,
333    }
334}
335
336ast_struct! {
337    /// A function call expression: `invoke(a, b)`.
338    #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
339    pub struct ExprCall {
340        pub attrs: Vec<Attribute>,
341        pub func: Box<Expr>,
342        pub paren_token: token::Paren,
343        pub args: Punctuated<Expr, Token![,]>,
344    }
345}
346
347ast_struct! {
348    /// A cast expression: `foo as f64`.
349    #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
350    pub struct ExprCast {
351        pub attrs: Vec<Attribute>,
352        pub expr: Box<Expr>,
353        pub as_token: Token![as],
354        pub ty: Box<Type>,
355    }
356}
357
358ast_struct! {
359    /// A closure expression: `|a, b| a + b`.
360    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
361    pub struct ExprClosure #full {
362        pub attrs: Vec<Attribute>,
363        pub lifetimes: Option<BoundLifetimes>,
364        pub constness: Option<Token![const]>,
365        pub movability: Option<Token![static]>,
366        pub asyncness: Option<Token![async]>,
367        pub capture: Option<Token![move]>,
368        pub or1_token: Token![|],
369        pub inputs: Punctuated<Pat, Token![,]>,
370        pub or2_token: Token![|],
371        pub output: ReturnType,
372        pub body: Box<Expr>,
373    }
374}
375
376ast_struct! {
377    /// A const block: `const { ... }`.
378    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
379    pub struct ExprConst #full {
380        pub attrs: Vec<Attribute>,
381        pub const_token: Token![const],
382        pub block: Block,
383    }
384}
385
386ast_struct! {
387    /// A `continue`, with an optional label.
388    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
389    pub struct ExprContinue #full {
390        pub attrs: Vec<Attribute>,
391        pub continue_token: Token![continue],
392        pub label: Option<Lifetime>,
393    }
394}
395
396ast_struct! {
397    /// Access of a named struct field (`obj.k`) or unnamed tuple struct
398    /// field (`obj.0`).
399    #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
400    pub struct ExprField {
401        pub attrs: Vec<Attribute>,
402        pub base: Box<Expr>,
403        pub dot_token: Token![.],
404        pub member: Member,
405    }
406}
407
408ast_struct! {
409    /// A for loop: `for pat in expr { ... }`.
410    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
411    pub struct ExprForLoop #full {
412        pub attrs: Vec<Attribute>,
413        pub label: Option<Label>,
414        pub for_token: Token![for],
415        pub pat: Box<Pat>,
416        pub in_token: Token![in],
417        pub expr: Box<Expr>,
418        pub body: Block,
419    }
420}
421
422ast_struct! {
423    /// An expression contained within invisible delimiters.
424    ///
425    /// This variant is important for faithfully representing the precedence
426    /// of expressions and is related to `None`-delimited spans in a
427    /// `TokenStream`.
428    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
429    pub struct ExprGroup {
430        pub attrs: Vec<Attribute>,
431        pub group_token: token::Group,
432        pub expr: Box<Expr>,
433    }
434}
435
436ast_struct! {
437    /// An `if` expression with an optional `else` block: `if expr { ... }
438    /// else { ... }`.
439    ///
440    /// The `else` branch expression may only be an `If` or `Block`
441    /// expression, not any of the other types of expression.
442    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
443    pub struct ExprIf #full {
444        pub attrs: Vec<Attribute>,
445        pub if_token: Token![if],
446        pub cond: Box<Expr>,
447        pub then_branch: Block,
448        pub else_branch: Option<(Token![else], Box<Expr>)>,
449    }
450}
451
452ast_struct! {
453    /// A square bracketed indexing expression: `vector[2]`.
454    #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
455    pub struct ExprIndex {
456        pub attrs: Vec<Attribute>,
457        pub expr: Box<Expr>,
458        pub bracket_token: token::Bracket,
459        pub index: Box<Expr>,
460    }
461}
462
463ast_struct! {
464    /// The inferred value of a const generic argument, denoted `_`.
465    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
466    pub struct ExprInfer #full {
467        pub attrs: Vec<Attribute>,
468        pub underscore_token: Token![_],
469    }
470}
471
472ast_struct! {
473    /// A `let` guard: `let Some(x) = opt`.
474    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
475    pub struct ExprLet #full {
476        pub attrs: Vec<Attribute>,
477        pub let_token: Token![let],
478        pub pat: Box<Pat>,
479        pub eq_token: Token![=],
480        pub expr: Box<Expr>,
481    }
482}
483
484ast_struct! {
485    /// A literal in place of an expression: `1`, `"foo"`.
486    #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
487    pub struct ExprLit {
488        pub attrs: Vec<Attribute>,
489        pub lit: Lit,
490    }
491}
492
493ast_struct! {
494    /// Conditionless loop: `loop { ... }`.
495    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
496    pub struct ExprLoop #full {
497        pub attrs: Vec<Attribute>,
498        pub label: Option<Label>,
499        pub loop_token: Token![loop],
500        pub body: Block,
501    }
502}
503
504ast_struct! {
505    /// A macro invocation expression: `format!("{}", q)`.
506    #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
507    pub struct ExprMacro {
508        pub attrs: Vec<Attribute>,
509        pub mac: Macro,
510    }
511}
512
513ast_struct! {
514    /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
515    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
516    pub struct ExprMatch #full {
517        pub attrs: Vec<Attribute>,
518        pub match_token: Token![match],
519        pub expr: Box<Expr>,
520        pub brace_token: token::Brace,
521        pub arms: Vec<Arm>,
522    }
523}
524
525ast_struct! {
526    /// A method call expression: `x.foo::<T>(a, b)`.
527    #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
528    pub struct ExprMethodCall {
529        pub attrs: Vec<Attribute>,
530        pub receiver: Box<Expr>,
531        pub dot_token: Token![.],
532        pub method: Ident,
533        pub turbofish: Option<AngleBracketedGenericArguments>,
534        pub paren_token: token::Paren,
535        pub args: Punctuated<Expr, Token![,]>,
536    }
537}
538
539ast_struct! {
540    /// A parenthesized expression: `(a + b)`.
541    #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
542    pub struct ExprParen {
543        pub attrs: Vec<Attribute>,
544        pub paren_token: token::Paren,
545        pub expr: Box<Expr>,
546    }
547}
548
549ast_struct! {
550    /// A path like `std::mem::replace` possibly containing generic
551    /// parameters and a qualified self-type.
552    ///
553    /// A plain identifier like `x` is a path of length 1.
554    #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
555    pub struct ExprPath {
556        pub attrs: Vec<Attribute>,
557        pub qself: Option<QSelf>,
558        pub path: Path,
559    }
560}
561
562ast_struct! {
563    /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
564    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
565    pub struct ExprRange #full {
566        pub attrs: Vec<Attribute>,
567        pub start: Option<Box<Expr>>,
568        pub limits: RangeLimits,
569        pub end: Option<Box<Expr>>,
570    }
571}
572
573ast_struct! {
574    /// A referencing operation: `&a` or `&mut a`.
575    #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
576    pub struct ExprReference {
577        pub attrs: Vec<Attribute>,
578        pub and_token: Token![&],
579        pub mutability: Option<Token![mut]>,
580        pub expr: Box<Expr>,
581    }
582}
583
584ast_struct! {
585    /// An array literal constructed from one repeated element: `[0u8; N]`.
586    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
587    pub struct ExprRepeat #full {
588        pub attrs: Vec<Attribute>,
589        pub bracket_token: token::Bracket,
590        pub expr: Box<Expr>,
591        pub semi_token: Token![;],
592        pub len: Box<Expr>,
593    }
594}
595
596ast_struct! {
597    /// A `return`, with an optional value to be returned.
598    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
599    pub struct ExprReturn #full {
600        pub attrs: Vec<Attribute>,
601        pub return_token: Token![return],
602        pub expr: Option<Box<Expr>>,
603    }
604}
605
606ast_struct! {
607    /// A struct literal expression: `Point { x: 1, y: 1 }`.
608    ///
609    /// The `rest` provides the value of the remaining fields as in `S { a:
610    /// 1, b: 1, ..rest }`.
611    #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
612    pub struct ExprStruct {
613        pub attrs: Vec<Attribute>,
614        pub qself: Option<QSelf>,
615        pub path: Path,
616        pub brace_token: token::Brace,
617        pub fields: Punctuated<FieldValue, Token![,]>,
618        pub dot2_token: Option<Token![..]>,
619        pub rest: Option<Box<Expr>>,
620    }
621}
622
623ast_struct! {
624    /// A try-expression: `expr?`.
625    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
626    pub struct ExprTry #full {
627        pub attrs: Vec<Attribute>,
628        pub expr: Box<Expr>,
629        pub question_token: Token![?],
630    }
631}
632
633ast_struct! {
634    /// A try block: `try { ... }`.
635    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
636    pub struct ExprTryBlock #full {
637        pub attrs: Vec<Attribute>,
638        pub try_token: Token![try],
639        pub block: Block,
640    }
641}
642
643ast_struct! {
644    /// A tuple expression: `(a, b, c, d)`.
645    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
646    pub struct ExprTuple #full {
647        pub attrs: Vec<Attribute>,
648        pub paren_token: token::Paren,
649        pub elems: Punctuated<Expr, Token![,]>,
650    }
651}
652
653ast_struct! {
654    /// A unary operation: `!x`, `*x`.
655    #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
656    pub struct ExprUnary {
657        pub attrs: Vec<Attribute>,
658        pub op: UnOp,
659        pub expr: Box<Expr>,
660    }
661}
662
663ast_struct! {
664    /// An unsafe block: `unsafe { ... }`.
665    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
666    pub struct ExprUnsafe #full {
667        pub attrs: Vec<Attribute>,
668        pub unsafe_token: Token![unsafe],
669        pub block: Block,
670    }
671}
672
673ast_struct! {
674    /// A while loop: `while expr { ... }`.
675    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
676    pub struct ExprWhile #full {
677        pub attrs: Vec<Attribute>,
678        pub label: Option<Label>,
679        pub while_token: Token![while],
680        pub cond: Box<Expr>,
681        pub body: Block,
682    }
683}
684
685ast_struct! {
686    /// A yield expression: `yield expr`.
687    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
688    pub struct ExprYield #full {
689        pub attrs: Vec<Attribute>,
690        pub yield_token: Token![yield],
691        pub expr: Option<Box<Expr>>,
692    }
693}
694
695impl Expr {
696    #[cfg(feature = "parsing")]
697    const DUMMY: Self = Expr::Path(ExprPath {
698        attrs: Vec::new(),
699        qself: None,
700        path: Path {
701            leading_colon: None,
702            segments: Punctuated::new(),
703        },
704    });
705
706    #[cfg(all(feature = "parsing", feature = "full"))]
707    pub(crate) fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
708        match self {
709            Expr::Array(ExprArray { attrs, .. })
710            | Expr::Assign(ExprAssign { attrs, .. })
711            | Expr::Async(ExprAsync { attrs, .. })
712            | Expr::Await(ExprAwait { attrs, .. })
713            | Expr::Binary(ExprBinary { attrs, .. })
714            | Expr::Block(ExprBlock { attrs, .. })
715            | Expr::Break(ExprBreak { attrs, .. })
716            | Expr::Call(ExprCall { attrs, .. })
717            | Expr::Cast(ExprCast { attrs, .. })
718            | Expr::Closure(ExprClosure { attrs, .. })
719            | Expr::Const(ExprConst { attrs, .. })
720            | Expr::Continue(ExprContinue { attrs, .. })
721            | Expr::Field(ExprField { attrs, .. })
722            | Expr::ForLoop(ExprForLoop { attrs, .. })
723            | Expr::Group(ExprGroup { attrs, .. })
724            | Expr::If(ExprIf { attrs, .. })
725            | Expr::Index(ExprIndex { attrs, .. })
726            | Expr::Infer(ExprInfer { attrs, .. })
727            | Expr::Let(ExprLet { attrs, .. })
728            | Expr::Lit(ExprLit { attrs, .. })
729            | Expr::Loop(ExprLoop { attrs, .. })
730            | Expr::Macro(ExprMacro { attrs, .. })
731            | Expr::Match(ExprMatch { attrs, .. })
732            | Expr::MethodCall(ExprMethodCall { attrs, .. })
733            | Expr::Paren(ExprParen { attrs, .. })
734            | Expr::Path(ExprPath { attrs, .. })
735            | Expr::Range(ExprRange { attrs, .. })
736            | Expr::Reference(ExprReference { attrs, .. })
737            | Expr::Repeat(ExprRepeat { attrs, .. })
738            | Expr::Return(ExprReturn { attrs, .. })
739            | Expr::Struct(ExprStruct { attrs, .. })
740            | Expr::Try(ExprTry { attrs, .. })
741            | Expr::TryBlock(ExprTryBlock { attrs, .. })
742            | Expr::Tuple(ExprTuple { attrs, .. })
743            | Expr::Unary(ExprUnary { attrs, .. })
744            | Expr::Unsafe(ExprUnsafe { attrs, .. })
745            | Expr::While(ExprWhile { attrs, .. })
746            | Expr::Yield(ExprYield { attrs, .. }) => mem::replace(attrs, new),
747            Expr::Verbatim(_) => Vec::new(),
748        }
749    }
750}
751
752ast_enum! {
753    /// A struct or tuple struct field accessed in a struct literal or field
754    /// expression.
755    #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
756    pub enum Member {
757        /// A named field like `self.x`.
758        Named(Ident),
759        /// An unnamed field like `self.0`.
760        Unnamed(Index),
761    }
762}
763
764impl From<Ident> for Member {
765    fn from(ident: Ident) -> Member {
766        Member::Named(ident)
767    }
768}
769
770impl From<Index> for Member {
771    fn from(index: Index) -> Member {
772        Member::Unnamed(index)
773    }
774}
775
776impl From<usize> for Member {
777    fn from(index: usize) -> Member {
778        Member::Unnamed(Index::from(index))
779    }
780}
781
782impl Eq for Member {}
783
784impl PartialEq for Member {
785    fn eq(&self, other: &Self) -> bool {
786        match (self, other) {
787            (Member::Named(this), Member::Named(other)) => this == other,
788            (Member::Unnamed(this), Member::Unnamed(other)) => this == other,
789            _ => false,
790        }
791    }
792}
793
794impl Hash for Member {
795    fn hash<H: Hasher>(&self, state: &mut H) {
796        match self {
797            Member::Named(m) => m.hash(state),
798            Member::Unnamed(m) => m.hash(state),
799        }
800    }
801}
802
803#[cfg(feature = "printing")]
804impl IdentFragment for Member {
805    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
806        match self {
807            Member::Named(m) => Display::fmt(m, formatter),
808            Member::Unnamed(m) => Display::fmt(&m.index, formatter),
809        }
810    }
811
812    fn span(&self) -> Option<Span> {
813        match self {
814            Member::Named(m) => Some(m.span()),
815            Member::Unnamed(m) => Some(m.span),
816        }
817    }
818}
819
820ast_struct! {
821    /// The index of an unnamed tuple struct field.
822    #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
823    pub struct Index {
824        pub index: u32,
825        pub span: Span,
826    }
827}
828
829impl From<usize> for Index {
830    fn from(index: usize) -> Index {
831        assert!(index < u32::max_value() as usize);
832        Index {
833            index: index as u32,
834            span: Span::call_site(),
835        }
836    }
837}
838
839impl Eq for Index {}
840
841impl PartialEq for Index {
842    fn eq(&self, other: &Self) -> bool {
843        self.index == other.index
844    }
845}
846
847impl Hash for Index {
848    fn hash<H: Hasher>(&self, state: &mut H) {
849        self.index.hash(state);
850    }
851}
852
853#[cfg(feature = "printing")]
854impl IdentFragment for Index {
855    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
856        Display::fmt(&self.index, formatter)
857    }
858
859    fn span(&self) -> Option<Span> {
860        Some(self.span)
861    }
862}
863
864ast_struct! {
865    /// A field-value pair in a struct literal.
866    #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
867    pub struct FieldValue {
868        pub attrs: Vec<Attribute>,
869        pub member: Member,
870
871        /// The colon in `Struct { x: x }`. If written in shorthand like
872        /// `Struct { x }`, there is no colon.
873        pub colon_token: Option<Token![:]>,
874
875        pub expr: Expr,
876    }
877}
878
879#[cfg(feature = "full")]
880ast_struct! {
881    /// A lifetime labeling a `for`, `while`, or `loop`.
882    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
883    pub struct Label {
884        pub name: Lifetime,
885        pub colon_token: Token![:],
886    }
887}
888
889#[cfg(feature = "full")]
890ast_struct! {
891    /// One arm of a `match` expression: `0..=10 => { return true; }`.
892    ///
893    /// As in:
894    ///
895    /// ```
896    /// # fn f() -> bool {
897    /// #     let n = 0;
898    /// match n {
899    ///     0..=10 => {
900    ///         return true;
901    ///     }
902    ///     // ...
903    ///     # _ => {}
904    /// }
905    /// #   false
906    /// # }
907    /// ```
908    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
909    pub struct Arm {
910        pub attrs: Vec<Attribute>,
911        pub pat: Pat,
912        pub guard: Option<(Token![if], Box<Expr>)>,
913        pub fat_arrow_token: Token![=>],
914        pub body: Box<Expr>,
915        pub comma: Option<Token![,]>,
916    }
917}
918
919#[cfg(feature = "full")]
920ast_enum! {
921    /// Limit types of a range, inclusive or exclusive.
922    #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
923    pub enum RangeLimits {
924        /// Inclusive at the beginning, exclusive at the end.
925        HalfOpen(Token![..]),
926        /// Inclusive at the beginning and end.
927        Closed(Token![..=]),
928    }
929}
930
931#[cfg(any(feature = "parsing", feature = "printing"))]
932#[cfg(feature = "full")]
933pub(crate) fn requires_terminator(expr: &Expr) -> bool {
934    // see https://github.com/rust-lang/rust/blob/9a19e7604/compiler/rustc_ast/src/util/classify.rs#L7-L26
935    match expr {
936        Expr::If(_)
937        | Expr::Match(_)
938        | Expr::Block(_) | Expr::Unsafe(_) // both under ExprKind::Block in rustc
939        | Expr::While(_)
940        | Expr::Loop(_)
941        | Expr::ForLoop(_)
942        | Expr::TryBlock(_)
943        | Expr::Const(_) => false,
944        Expr::Array(_)
945        | Expr::Assign(_)
946        | Expr::Async(_)
947        | Expr::Await(_)
948        | Expr::Binary(_)
949        | Expr::Break(_)
950        | Expr::Call(_)
951        | Expr::Cast(_)
952        | Expr::Closure(_)
953        | Expr::Continue(_)
954        | Expr::Field(_)
955        | Expr::Group(_)
956        | Expr::Index(_)
957        | Expr::Infer(_)
958        | Expr::Let(_)
959        | Expr::Lit(_)
960        | Expr::Macro(_)
961        | Expr::MethodCall(_)
962        | Expr::Paren(_)
963        | Expr::Path(_)
964        | Expr::Range(_)
965        | Expr::Reference(_)
966        | Expr::Repeat(_)
967        | Expr::Return(_)
968        | Expr::Struct(_)
969        | Expr::Try(_)
970        | Expr::Tuple(_)
971        | Expr::Unary(_)
972        | Expr::Yield(_)
973        | Expr::Verbatim(_) => true
974    }
975}
976
977#[cfg(feature = "parsing")]
978mod precedence {
979    use super::BinOp;
980
981    pub(crate) enum Precedence {
982        Any,
983        Assign,
984        Range,
985        Or,
986        And,
987        Compare,
988        BitOr,
989        BitXor,
990        BitAnd,
991        Shift,
992        Arithmetic,
993        Term,
994        Cast,
995    }
996
997    impl Precedence {
998        pub(crate) fn of(op: &BinOp) -> Self {
999            match op {
1000                BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic,
1001                BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term,
1002                BinOp::And(_) => Precedence::And,
1003                BinOp::Or(_) => Precedence::Or,
1004                BinOp::BitXor(_) => Precedence::BitXor,
1005                BinOp::BitAnd(_) => Precedence::BitAnd,
1006                BinOp::BitOr(_) => Precedence::BitOr,
1007                BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
1008                BinOp::Eq(_)
1009                | BinOp::Lt(_)
1010                | BinOp::Le(_)
1011                | BinOp::Ne(_)
1012                | BinOp::Ge(_)
1013                | BinOp::Gt(_) => Precedence::Compare,
1014                BinOp::AddAssign(_)
1015                | BinOp::SubAssign(_)
1016                | BinOp::MulAssign(_)
1017                | BinOp::DivAssign(_)
1018                | BinOp::RemAssign(_)
1019                | BinOp::BitXorAssign(_)
1020                | BinOp::BitAndAssign(_)
1021                | BinOp::BitOrAssign(_)
1022                | BinOp::ShlAssign(_)
1023                | BinOp::ShrAssign(_) => Precedence::Assign,
1024            }
1025        }
1026    }
1027}
1028
1029#[cfg(feature = "parsing")]
1030pub(crate) mod parsing {
1031    #[cfg(feature = "full")]
1032    use crate::attr;
1033    use crate::attr::Attribute;
1034    use crate::error::{Error, Result};
1035    use crate::expr::precedence::Precedence;
1036    #[cfg(feature = "full")]
1037    use crate::expr::{
1038        requires_terminator, Arm, ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock,
1039        ExprBreak, ExprClosure, ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer, ExprLet,
1040        ExprLoop, ExprMatch, ExprRange, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprTuple,
1041        ExprUnsafe, ExprWhile, ExprYield, Label, RangeLimits,
1042    };
1043    use crate::expr::{
1044        Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro,
1045        ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprUnary, FieldValue,
1046        Index, Member,
1047    };
1048    #[cfg(feature = "full")]
1049    use crate::ext::IdentExt as _;
1050    #[cfg(feature = "full")]
1051    use crate::generics::BoundLifetimes;
1052    use crate::ident::Ident;
1053    #[cfg(feature = "full")]
1054    use crate::lifetime::Lifetime;
1055    use crate::lit::{Lit, LitFloat, LitInt};
1056    use crate::mac::{self, Macro};
1057    use crate::op::BinOp;
1058    use crate::parse::discouraged::Speculative as _;
1059    #[cfg(feature = "full")]
1060    use crate::parse::ParseBuffer;
1061    use crate::parse::{Parse, ParseStream};
1062    #[cfg(feature = "full")]
1063    use crate::pat::{Pat, PatType};
1064    use crate::path::{self, AngleBracketedGenericArguments, Path, QSelf};
1065    use crate::punctuated::Punctuated;
1066    #[cfg(feature = "full")]
1067    use crate::stmt::Block;
1068    use crate::token;
1069    use crate::ty;
1070    #[cfg(feature = "full")]
1071    use crate::ty::{ReturnType, Type};
1072    use crate::verbatim;
1073    #[cfg(feature = "full")]
1074    use proc_macro2::TokenStream;
1075    use std::cmp::Ordering;
1076    use std::mem;
1077
1078    mod kw {
1079        crate::custom_keyword!(builtin);
1080        crate::custom_keyword!(raw);
1081    }
1082
1083    // When we're parsing expressions which occur before blocks, like in an if
1084    // statement's condition, we cannot parse a struct literal.
1085    //
1086    // Struct literals are ambiguous in certain positions
1087    // https://github.com/rust-lang/rfcs/pull/92
1088    #[cfg(feature = "full")]
1089    pub(crate) struct AllowStruct(bool);
1090
1091    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
1092    impl Parse for Expr {
1093        fn parse(input: ParseStream) -> Result<Self> {
1094            ambiguous_expr(
1095                input,
1096                #[cfg(feature = "full")]
1097                AllowStruct(true),
1098            )
1099        }
1100    }
1101
1102    impl Expr {
1103        /// An alternative to the primary `Expr::parse` parser (from the
1104        /// [`Parse`] trait) for ambiguous syntactic positions in which a
1105        /// trailing brace should not be taken as part of the expression.
1106        ///
1107        /// Rust grammar has an ambiguity where braces sometimes turn a path
1108        /// expression into a struct initialization and sometimes do not. In the
1109        /// following code, the expression `S {}` is one expression. Presumably
1110        /// there is an empty struct `struct S {}` defined somewhere which it is
1111        /// instantiating.
1112        ///
1113        /// ```
1114        /// # struct S;
1115        /// # impl std::ops::Deref for S {
1116        /// #     type Target = bool;
1117        /// #     fn deref(&self) -> &Self::Target {
1118        /// #         &true
1119        /// #     }
1120        /// # }
1121        /// let _ = *S {};
1122        ///
1123        /// // parsed by rustc as: `*(S {})`
1124        /// ```
1125        ///
1126        /// We would want to parse the above using `Expr::parse` after the `=`
1127        /// token.
1128        ///
1129        /// But in the following, `S {}` is *not* a struct init expression.
1130        ///
1131        /// ```
1132        /// # const S: &bool = &true;
1133        /// if *S {} {}
1134        ///
1135        /// // parsed by rustc as:
1136        /// //
1137        /// //    if (*S) {
1138        /// //        /* empty block */
1139        /// //    }
1140        /// //    {
1141        /// //        /* another empty block */
1142        /// //    }
1143        /// ```
1144        ///
1145        /// For that reason we would want to parse if-conditions using
1146        /// `Expr::parse_without_eager_brace` after the `if` token. Same for
1147        /// similar syntactic positions such as the condition expr after a
1148        /// `while` token or the expr at the top of a `match`.
1149        ///
1150        /// The Rust grammar's choices around which way this ambiguity is
1151        /// resolved at various syntactic positions is fairly arbitrary. Really
1152        /// either parse behavior could work in most positions, and language
1153        /// designers just decide each case based on which is more likely to be
1154        /// what the programmer had in mind most of the time.
1155        ///
1156        /// ```
1157        /// # struct S;
1158        /// # fn doc() -> S {
1159        /// if return S {} {}
1160        /// # unreachable!()
1161        /// # }
1162        ///
1163        /// // parsed by rustc as:
1164        /// //
1165        /// //    if (return (S {})) {
1166        /// //    }
1167        /// //
1168        /// // but could equally well have been this other arbitrary choice:
1169        /// //
1170        /// //    if (return S) {
1171        /// //    }
1172        /// //    {}
1173        /// ```
1174        ///
1175        /// Note the grammar ambiguity on trailing braces is distinct from
1176        /// precedence and is not captured by assigning a precedence level to
1177        /// the braced struct init expr in relation to other operators. This can
1178        /// be illustrated by `return 0..S {}` vs `match 0..S {}`. The former
1179        /// parses as `return (0..(S {}))` implying tighter precedence for
1180        /// struct init than `..`, while the latter parses as `match (0..S) {}`
1181        /// implying tighter precedence for `..` than struct init, a
1182        /// contradiction.
1183        #[cfg(feature = "full")]
1184        #[cfg_attr(doc_cfg, doc(cfg(all(feature = "full", feature = "parsing"))))]
1185        pub fn parse_without_eager_brace(input: ParseStream) -> Result<Expr> {
1186            ambiguous_expr(input, AllowStruct(false))
1187        }
1188
1189        /// An alternative to the primary `Expr::parse` parser (from the
1190        /// [`Parse`] trait) for syntactic positions in which expression
1191        /// boundaries are placed more eagerly than done by the typical
1192        /// expression grammar. This includes expressions at the head of a
1193        /// statement or in the right-hand side of a `match` arm.
1194        ///
1195        /// Compare the following cases:
1196        ///
1197        /// 1.
1198        ///   ```
1199        ///   # let result = ();
1200        ///   # let guard = false;
1201        ///   # let cond = true;
1202        ///   # let f = true;
1203        ///   # let g = f;
1204        ///   #
1205        ///   let _ = match result {
1206        ///       () if guard => if cond { f } else { g }
1207        ///       () => false,
1208        ///   };
1209        ///   ```
1210        ///
1211        /// 2.
1212        ///   ```
1213        ///   # let cond = true;
1214        ///   # let f = ();
1215        ///   # let g = f;
1216        ///   #
1217        ///   let _ = || {
1218        ///       if cond { f } else { g }
1219        ///       ()
1220        ///   };
1221        ///   ```
1222        ///
1223        /// 3.
1224        ///   ```
1225        ///   # let cond = true;
1226        ///   # let f = || ();
1227        ///   # let g = f;
1228        ///   #
1229        ///   let _ = [if cond { f } else { g } ()];
1230        ///   ```
1231        ///
1232        /// The same sequence of tokens `if cond { f } else { g } ()` appears in
1233        /// expression position 3 times. The first two syntactic positions use
1234        /// eager placement of expression boundaries, and parse as `Expr::If`,
1235        /// with the adjacent `()` becoming `Pat::Tuple` or `Expr::Tuple`. In
1236        /// contrast, the third case uses standard expression boundaries and
1237        /// parses as `Expr::Call`.
1238        ///
1239        /// As with [`parse_without_eager_brace`], this ambiguity in the Rust
1240        /// grammar is independent of precedence.
1241        ///
1242        /// [`parse_without_eager_brace`]: Self::parse_without_eager_brace
1243        #[cfg(feature = "full")]
1244        #[cfg_attr(doc_cfg, doc(cfg(all(feature = "full", feature = "parsing"))))]
1245        pub fn parse_with_earlier_boundary_rule(input: ParseStream) -> Result<Expr> {
1246            let mut attrs = input.call(expr_attrs)?;
1247            let mut expr = if input.peek(token::Group) {
1248                let allow_struct = AllowStruct(true);
1249                let atom = expr_group(input, allow_struct)?;
1250                if continue_parsing_early(&atom) {
1251                    trailer_helper(input, atom)?
1252                } else {
1253                    atom
1254                }
1255            } else if input.peek(Token![if]) {
1256                Expr::If(input.parse()?)
1257            } else if input.peek(Token![while]) {
1258                Expr::While(input.parse()?)
1259            } else if input.peek(Token![for])
1260                && !(input.peek2(Token![<]) && (input.peek3(Lifetime) || input.peek3(Token![>])))
1261            {
1262                Expr::ForLoop(input.parse()?)
1263            } else if input.peek(Token![loop]) {
1264                Expr::Loop(input.parse()?)
1265            } else if input.peek(Token![match]) {
1266                Expr::Match(input.parse()?)
1267            } else if input.peek(Token![try]) && input.peek2(token::Brace) {
1268                Expr::TryBlock(input.parse()?)
1269            } else if input.peek(Token![unsafe]) {
1270                Expr::Unsafe(input.parse()?)
1271            } else if input.peek(Token![const]) && input.peek2(token::Brace) {
1272                Expr::Const(input.parse()?)
1273            } else if input.peek(token::Brace) {
1274                Expr::Block(input.parse()?)
1275            } else if input.peek(Lifetime) {
1276                atom_labeled(input)?
1277            } else {
1278                let allow_struct = AllowStruct(true);
1279                unary_expr(input, allow_struct)?
1280            };
1281
1282            if continue_parsing_early(&expr) {
1283                attrs.extend(expr.replace_attrs(Vec::new()));
1284                expr.replace_attrs(attrs);
1285
1286                let allow_struct = AllowStruct(true);
1287                return parse_expr(input, expr, allow_struct, Precedence::Any);
1288            }
1289
1290            if input.peek(Token![.]) && !input.peek(Token![..]) || input.peek(Token![?]) {
1291                expr = trailer_helper(input, expr)?;
1292
1293                attrs.extend(expr.replace_attrs(Vec::new()));
1294                expr.replace_attrs(attrs);
1295
1296                let allow_struct = AllowStruct(true);
1297                return parse_expr(input, expr, allow_struct, Precedence::Any);
1298            }
1299
1300            attrs.extend(expr.replace_attrs(Vec::new()));
1301            expr.replace_attrs(attrs);
1302            Ok(expr)
1303        }
1304    }
1305
1306    #[cfg(feature = "full")]
1307    impl Copy for AllowStruct {}
1308
1309    #[cfg(feature = "full")]
1310    impl Clone for AllowStruct {
1311        fn clone(&self) -> Self {
1312            *self
1313        }
1314    }
1315
1316    impl Copy for Precedence {}
1317
1318    impl Clone for Precedence {
1319        fn clone(&self) -> Self {
1320            *self
1321        }
1322    }
1323
1324    impl PartialEq for Precedence {
1325        fn eq(&self, other: &Self) -> bool {
1326            *self as u8 == *other as u8
1327        }
1328    }
1329
1330    impl PartialOrd for Precedence {
1331        fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1332            let this = *self as u8;
1333            let other = *other as u8;
1334            Some(this.cmp(&other))
1335        }
1336    }
1337
1338    #[cfg(feature = "full")]
1339    fn can_begin_expr(input: ParseStream) -> bool {
1340        input.peek(Ident::peek_any) // value name or keyword
1341            || input.peek(token::Paren) // tuple
1342            || input.peek(token::Bracket) // array
1343            || input.peek(token::Brace) // block
1344            || input.peek(Lit) // literal
1345            || input.peek(Token![!]) && !input.peek(Token![!=]) // operator not
1346            || input.peek(Token![-]) && !input.peek(Token![-=]) && !input.peek(Token![->]) // unary minus
1347            || input.peek(Token![*]) && !input.peek(Token![*=]) // dereference
1348            || input.peek(Token![|]) && !input.peek(Token![|=]) // closure
1349            || input.peek(Token![&]) && !input.peek(Token![&=]) // reference
1350            || input.peek(Token![..]) // range notation
1351            || input.peek(Token![<]) && !input.peek(Token![<=]) && !input.peek(Token![<<=]) // associated path
1352            || input.peek(Token![::]) // global path
1353            || input.peek(Lifetime) // labeled loop
1354            || input.peek(Token![#]) // expression attributes
1355    }
1356
1357    #[cfg(feature = "full")]
1358    fn parse_expr(
1359        input: ParseStream,
1360        mut lhs: Expr,
1361        allow_struct: AllowStruct,
1362        base: Precedence,
1363    ) -> Result<Expr> {
1364        loop {
1365            let ahead = input.fork();
1366            if let Some(op) = match ahead.parse::<BinOp>() {
1367                Ok(op) if Precedence::of(&op) >= base => Some(op),
1368                _ => None,
1369            } {
1370                input.advance_to(&ahead);
1371                let precedence = Precedence::of(&op);
1372                let mut rhs = unary_expr(input, allow_struct)?;
1373                loop {
1374                    let next = peek_precedence(input);
1375                    if next > precedence || next == precedence && precedence == Precedence::Assign {
1376                        rhs = parse_expr(input, rhs, allow_struct, next)?;
1377                    } else {
1378                        break;
1379                    }
1380                }
1381                lhs = Expr::Binary(ExprBinary {
1382                    attrs: Vec::new(),
1383                    left: Box::new(lhs),
1384                    op,
1385                    right: Box::new(rhs),
1386                });
1387            } else if Precedence::Assign >= base
1388                && input.peek(Token![=])
1389                && !input.peek(Token![==])
1390                && !input.peek(Token![=>])
1391            {
1392                let eq_token: Token![=] = input.parse()?;
1393                let mut rhs = unary_expr(input, allow_struct)?;
1394                loop {
1395                    let next = peek_precedence(input);
1396                    if next >= Precedence::Assign {
1397                        rhs = parse_expr(input, rhs, allow_struct, next)?;
1398                    } else {
1399                        break;
1400                    }
1401                }
1402                lhs = Expr::Assign(ExprAssign {
1403                    attrs: Vec::new(),
1404                    left: Box::new(lhs),
1405                    eq_token,
1406                    right: Box::new(rhs),
1407                });
1408            } else if Precedence::Range >= base && input.peek(Token![..]) {
1409                let limits: RangeLimits = input.parse()?;
1410                let rhs = if matches!(limits, RangeLimits::HalfOpen(_))
1411                    && (input.is_empty()
1412                        || input.peek(Token![,])
1413                        || input.peek(Token![;])
1414                        || input.peek(Token![.]) && !input.peek(Token![..])
1415                        || !allow_struct.0 && input.peek(token::Brace))
1416                {
1417                    None
1418                } else {
1419                    let mut rhs = unary_expr(input, allow_struct)?;
1420                    loop {
1421                        let next = peek_precedence(input);
1422                        if next > Precedence::Range {
1423                            rhs = parse_expr(input, rhs, allow_struct, next)?;
1424                        } else {
1425                            break;
1426                        }
1427                    }
1428                    Some(rhs)
1429                };
1430                lhs = Expr::Range(ExprRange {
1431                    attrs: Vec::new(),
1432                    start: Some(Box::new(lhs)),
1433                    limits,
1434                    end: rhs.map(Box::new),
1435                });
1436            } else if Precedence::Cast >= base && input.peek(Token![as]) {
1437                let as_token: Token![as] = input.parse()?;
1438                let allow_plus = false;
1439                let allow_group_generic = false;
1440                let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
1441                check_cast(input)?;
1442                lhs = Expr::Cast(ExprCast {
1443                    attrs: Vec::new(),
1444                    expr: Box::new(lhs),
1445                    as_token,
1446                    ty: Box::new(ty),
1447                });
1448            } else {
1449                break;
1450            }
1451        }
1452        Ok(lhs)
1453    }
1454
1455    #[cfg(not(feature = "full"))]
1456    fn parse_expr(input: ParseStream, mut lhs: Expr, base: Precedence) -> Result<Expr> {
1457        loop {
1458            let ahead = input.fork();
1459            if let Some(op) = match ahead.parse::<BinOp>() {
1460                Ok(op) if Precedence::of(&op) >= base => Some(op),
1461                _ => None,
1462            } {
1463                input.advance_to(&ahead);
1464                let precedence = Precedence::of(&op);
1465                let mut rhs = unary_expr(input)?;
1466                loop {
1467                    let next = peek_precedence(input);
1468                    if next > precedence || next == precedence && precedence == Precedence::Assign {
1469                        rhs = parse_expr(input, rhs, next)?;
1470                    } else {
1471                        break;
1472                    }
1473                }
1474                lhs = Expr::Binary(ExprBinary {
1475                    attrs: Vec::new(),
1476                    left: Box::new(lhs),
1477                    op,
1478                    right: Box::new(rhs),
1479                });
1480            } else if Precedence::Cast >= base && input.peek(Token![as]) {
1481                let as_token: Token![as] = input.parse()?;
1482                let allow_plus = false;
1483                let allow_group_generic = false;
1484                let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
1485                check_cast(input)?;
1486                lhs = Expr::Cast(ExprCast {
1487                    attrs: Vec::new(),
1488                    expr: Box::new(lhs),
1489                    as_token,
1490                    ty: Box::new(ty),
1491                });
1492            } else {
1493                break;
1494            }
1495        }
1496        Ok(lhs)
1497    }
1498
1499    fn peek_precedence(input: ParseStream) -> Precedence {
1500        if let Ok(op) = input.fork().parse() {
1501            Precedence::of(&op)
1502        } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
1503            Precedence::Assign
1504        } else if input.peek(Token![..]) {
1505            Precedence::Range
1506        } else if input.peek(Token![as]) {
1507            Precedence::Cast
1508        } else {
1509            Precedence::Any
1510        }
1511    }
1512
1513    // Parse an arbitrary expression.
1514    fn ambiguous_expr(
1515        input: ParseStream,
1516        #[cfg(feature = "full")] allow_struct: AllowStruct,
1517    ) -> Result<Expr> {
1518        let lhs = unary_expr(
1519            input,
1520            #[cfg(feature = "full")]
1521            allow_struct,
1522        )?;
1523        parse_expr(
1524            input,
1525            lhs,
1526            #[cfg(feature = "full")]
1527            allow_struct,
1528            Precedence::Any,
1529        )
1530    }
1531
1532    #[cfg(feature = "full")]
1533    fn expr_attrs(input: ParseStream) -> Result<Vec<Attribute>> {
1534        let mut attrs = Vec::new();
1535        while !input.peek(token::Group) && input.peek(Token![#]) {
1536            attrs.push(input.call(attr::parsing::single_parse_outer)?);
1537        }
1538        Ok(attrs)
1539    }
1540
1541    // <UnOp> <trailer>
1542    // & <trailer>
1543    // &mut <trailer>
1544    // box <trailer>
1545    #[cfg(feature = "full")]
1546    fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1547        let begin = input.fork();
1548        let attrs = input.call(expr_attrs)?;
1549        if input.peek(token::Group) {
1550            return trailer_expr(begin, attrs, input, allow_struct);
1551        }
1552
1553        if input.peek(Token![&]) {
1554            let and_token: Token![&] = input.parse()?;
1555            let raw: Option<kw::raw> = if input.peek(kw::raw)
1556                && (input.peek2(Token![mut]) || input.peek2(Token![const]))
1557            {
1558                Some(input.parse()?)
1559            } else {
1560                None
1561            };
1562            let mutability: Option<Token![mut]> = input.parse()?;
1563            if raw.is_some() && mutability.is_none() {
1564                input.parse::<Token![const]>()?;
1565            }
1566            let expr = Box::new(unary_expr(input, allow_struct)?);
1567            if raw.is_some() {
1568                Ok(Expr::Verbatim(verbatim::between(&begin, input)))
1569            } else {
1570                Ok(Expr::Reference(ExprReference {
1571                    attrs,
1572                    and_token,
1573                    mutability,
1574                    expr,
1575                }))
1576            }
1577        } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
1578            expr_unary(input, attrs, allow_struct).map(Expr::Unary)
1579        } else {
1580            trailer_expr(begin, attrs, input, allow_struct)
1581        }
1582    }
1583
1584    #[cfg(not(feature = "full"))]
1585    fn unary_expr(input: ParseStream) -> Result<Expr> {
1586        if input.peek(Token![&]) {
1587            Ok(Expr::Reference(ExprReference {
1588                attrs: Vec::new(),
1589                and_token: input.parse()?,
1590                mutability: input.parse()?,
1591                expr: Box::new(unary_expr(input)?),
1592            }))
1593        } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
1594            Ok(Expr::Unary(ExprUnary {
1595                attrs: Vec::new(),
1596                op: input.parse()?,
1597                expr: Box::new(unary_expr(input)?),
1598            }))
1599        } else {
1600            trailer_expr(input)
1601        }
1602    }
1603
1604    // <atom> (..<args>) ...
1605    // <atom> . <ident> (..<args>) ...
1606    // <atom> . <ident> ...
1607    // <atom> . <lit> ...
1608    // <atom> [ <expr> ] ...
1609    // <atom> ? ...
1610    #[cfg(feature = "full")]
1611    fn trailer_expr(
1612        begin: ParseBuffer,
1613        mut attrs: Vec<Attribute>,
1614        input: ParseStream,
1615        allow_struct: AllowStruct,
1616    ) -> Result<Expr> {
1617        let atom = atom_expr(input, allow_struct)?;
1618        let mut e = trailer_helper(input, atom)?;
1619
1620        if let Expr::Verbatim(tokens) = &mut e {
1621            *tokens = verbatim::between(&begin, input);
1622        } else {
1623            let inner_attrs = e.replace_attrs(Vec::new());
1624            attrs.extend(inner_attrs);
1625            e.replace_attrs(attrs);
1626        }
1627
1628        Ok(e)
1629    }
1630
1631    #[cfg(feature = "full")]
1632    fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
1633        loop {
1634            if input.peek(token::Paren) {
1635                let content;
1636                e = Expr::Call(ExprCall {
1637                    attrs: Vec::new(),
1638                    func: Box::new(e),
1639                    paren_token: parenthesized!(content in input),
1640                    args: content.parse_terminated(Expr::parse, Token![,])?,
1641                });
1642            } else if input.peek(Token![.])
1643                && !input.peek(Token![..])
1644                && match e {
1645                    Expr::Range(_) => false,
1646                    _ => true,
1647                }
1648            {
1649                let mut dot_token: Token![.] = input.parse()?;
1650
1651                let float_token: Option<LitFloat> = input.parse()?;
1652                if let Some(float_token) = float_token {
1653                    if multi_index(&mut e, &mut dot_token, float_token)? {
1654                        continue;
1655                    }
1656                }
1657
1658                let await_token: Option<Token![await]> = input.parse()?;
1659                if let Some(await_token) = await_token {
1660                    e = Expr::Await(ExprAwait {
1661                        attrs: Vec::new(),
1662                        base: Box::new(e),
1663                        dot_token,
1664                        await_token,
1665                    });
1666                    continue;
1667                }
1668
1669                let member: Member = input.parse()?;
1670                let turbofish = if member.is_named() && input.peek(Token![::]) {
1671                    Some(AngleBracketedGenericArguments::parse_turbofish(input)?)
1672                } else {
1673                    None
1674                };
1675
1676                if turbofish.is_some() || input.peek(token::Paren) {
1677                    if let Member::Named(method) = member {
1678                        let content;
1679                        e = Expr::MethodCall(ExprMethodCall {
1680                            attrs: Vec::new(),
1681                            receiver: Box::new(e),
1682                            dot_token,
1683                            method,
1684                            turbofish,
1685                            paren_token: parenthesized!(content in input),
1686                            args: content.parse_terminated(Expr::parse, Token![,])?,
1687                        });
1688                        continue;
1689                    }
1690                }
1691
1692                e = Expr::Field(ExprField {
1693                    attrs: Vec::new(),
1694                    base: Box::new(e),
1695                    dot_token,
1696                    member,
1697                });
1698            } else if input.peek(token::Bracket) {
1699                let content;
1700                e = Expr::Index(ExprIndex {
1701                    attrs: Vec::new(),
1702                    expr: Box::new(e),
1703                    bracket_token: bracketed!(content in input),
1704                    index: content.parse()?,
1705                });
1706            } else if input.peek(Token![?]) {
1707                e = Expr::Try(ExprTry {
1708                    attrs: Vec::new(),
1709                    expr: Box::new(e),
1710                    question_token: input.parse()?,
1711                });
1712            } else {
1713                break;
1714            }
1715        }
1716        Ok(e)
1717    }
1718
1719    #[cfg(not(feature = "full"))]
1720    fn trailer_expr(input: ParseStream) -> Result<Expr> {
1721        let mut e = atom_expr(input)?;
1722
1723        loop {
1724            if input.peek(token::Paren) {
1725                let content;
1726                e = Expr::Call(ExprCall {
1727                    attrs: Vec::new(),
1728                    func: Box::new(e),
1729                    paren_token: parenthesized!(content in input),
1730                    args: content.parse_terminated(Expr::parse, Token![,])?,
1731                });
1732            } else if input.peek(Token![.])
1733                && !input.peek(Token![..])
1734                && !input.peek2(Token![await])
1735            {
1736                let mut dot_token: Token![.] = input.parse()?;
1737
1738                let float_token: Option<LitFloat> = input.parse()?;
1739                if let Some(float_token) = float_token {
1740                    if multi_index(&mut e, &mut dot_token, float_token)? {
1741                        continue;
1742                    }
1743                }
1744
1745                let member: Member = input.parse()?;
1746                let turbofish = if member.is_named() && input.peek(Token![::]) {
1747                    let colon2_token: Token![::] = input.parse()?;
1748                    let turbofish =
1749                        AngleBracketedGenericArguments::do_parse(Some(colon2_token), input)?;
1750                    Some(turbofish)
1751                } else {
1752                    None
1753                };
1754
1755                if turbofish.is_some() || input.peek(token::Paren) {
1756                    if let Member::Named(method) = member {
1757                        let content;
1758                        e = Expr::MethodCall(ExprMethodCall {
1759                            attrs: Vec::new(),
1760                            receiver: Box::new(e),
1761                            dot_token,
1762                            method,
1763                            turbofish,
1764                            paren_token: parenthesized!(content in input),
1765                            args: content.parse_terminated(Expr::parse, Token![,])?,
1766                        });
1767                        continue;
1768                    }
1769                }
1770
1771                e = Expr::Field(ExprField {
1772                    attrs: Vec::new(),
1773                    base: Box::new(e),
1774                    dot_token,
1775                    member,
1776                });
1777            } else if input.peek(token::Bracket) {
1778                let content;
1779                e = Expr::Index(ExprIndex {
1780                    attrs: Vec::new(),
1781                    expr: Box::new(e),
1782                    bracket_token: bracketed!(content in input),
1783                    index: content.parse()?,
1784                });
1785            } else {
1786                break;
1787            }
1788        }
1789
1790        Ok(e)
1791    }
1792
1793    // Parse all atomic expressions which don't have to worry about precedence
1794    // interactions, as they are fully contained.
1795    #[cfg(feature = "full")]
1796    fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1797        if input.peek(token::Group) {
1798            expr_group(input, allow_struct)
1799        } else if input.peek(Lit) {
1800            input.parse().map(Expr::Lit)
1801        } else if input.peek(Token![async])
1802            && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
1803        {
1804            input.parse().map(Expr::Async)
1805        } else if input.peek(Token![try]) && input.peek2(token::Brace) {
1806            input.parse().map(Expr::TryBlock)
1807        } else if input.peek(Token![|])
1808            || input.peek(Token![move])
1809            || input.peek(Token![for])
1810                && input.peek2(Token![<])
1811                && (input.peek3(Lifetime) || input.peek3(Token![>]))
1812            || input.peek(Token![const]) && !input.peek2(token::Brace)
1813            || input.peek(Token![static])
1814            || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1815        {
1816            expr_closure(input, allow_struct).map(Expr::Closure)
1817        } else if input.peek(kw::builtin) && input.peek2(Token![#]) {
1818            expr_builtin(input)
1819        } else if input.peek(Ident)
1820            || input.peek(Token![::])
1821            || input.peek(Token![<])
1822            || input.peek(Token![self])
1823            || input.peek(Token![Self])
1824            || input.peek(Token![super])
1825            || input.peek(Token![crate])
1826            || input.peek(Token![try]) && (input.peek2(Token![!]) || input.peek2(Token![::]))
1827        {
1828            path_or_macro_or_struct(input, allow_struct)
1829        } else if input.peek(token::Paren) {
1830            paren_or_tuple(input)
1831        } else if input.peek(Token![break]) {
1832            expr_break(input, allow_struct).map(Expr::Break)
1833        } else if input.peek(Token![continue]) {
1834            input.parse().map(Expr::Continue)
1835        } else if input.peek(Token![return]) {
1836            expr_return(input, allow_struct).map(Expr::Return)
1837        } else if input.peek(token::Bracket) {
1838            array_or_repeat(input)
1839        } else if input.peek(Token![let]) {
1840            input.parse().map(Expr::Let)
1841        } else if input.peek(Token![if]) {
1842            input.parse().map(Expr::If)
1843        } else if input.peek(Token![while]) {
1844            input.parse().map(Expr::While)
1845        } else if input.peek(Token![for]) {
1846            input.parse().map(Expr::ForLoop)
1847        } else if input.peek(Token![loop]) {
1848            input.parse().map(Expr::Loop)
1849        } else if input.peek(Token![match]) {
1850            input.parse().map(Expr::Match)
1851        } else if input.peek(Token![yield]) {
1852            input.parse().map(Expr::Yield)
1853        } else if input.peek(Token![unsafe]) {
1854            input.parse().map(Expr::Unsafe)
1855        } else if input.peek(Token![const]) {
1856            input.parse().map(Expr::Const)
1857        } else if input.peek(token::Brace) {
1858            input.parse().map(Expr::Block)
1859        } else if input.peek(Token![..]) {
1860            expr_range(input, allow_struct).map(Expr::Range)
1861        } else if input.peek(Token![_]) {
1862            input.parse().map(Expr::Infer)
1863        } else if input.peek(Lifetime) {
1864            atom_labeled(input)
1865        } else {
1866            Err(input.error("expected an expression"))
1867        }
1868    }
1869
1870    #[cfg(feature = "full")]
1871    fn atom_labeled(input: ParseStream) -> Result<Expr> {
1872        let the_label: Label = input.parse()?;
1873        let mut expr = if input.peek(Token![while]) {
1874            Expr::While(input.parse()?)
1875        } else if input.peek(Token![for]) {
1876            Expr::ForLoop(input.parse()?)
1877        } else if input.peek(Token![loop]) {
1878            Expr::Loop(input.parse()?)
1879        } else if input.peek(token::Brace) {
1880            Expr::Block(input.parse()?)
1881        } else {
1882            return Err(input.error("expected loop or block expression"));
1883        };
1884        match &mut expr {
1885            Expr::While(ExprWhile { label, .. })
1886            | Expr::ForLoop(ExprForLoop { label, .. })
1887            | Expr::Loop(ExprLoop { label, .. })
1888            | Expr::Block(ExprBlock { label, .. }) => *label = Some(the_label),
1889            _ => unreachable!(),
1890        }
1891        Ok(expr)
1892    }
1893
1894    #[cfg(not(feature = "full"))]
1895    fn atom_expr(input: ParseStream) -> Result<Expr> {
1896        if input.peek(token::Group) {
1897            expr_group(input)
1898        } else if input.peek(Lit) {
1899            input.parse().map(Expr::Lit)
1900        } else if input.peek(token::Paren) {
1901            input.call(expr_paren).map(Expr::Paren)
1902        } else if input.peek(Ident)
1903            || input.peek(Token![::])
1904            || input.peek(Token![<])
1905            || input.peek(Token![self])
1906            || input.peek(Token![Self])
1907            || input.peek(Token![super])
1908            || input.peek(Token![crate])
1909        {
1910            path_or_macro_or_struct(input)
1911        } else if input.is_empty() {
1912            Err(input.error("expected an expression"))
1913        } else {
1914            if input.peek(token::Brace) {
1915                let scan = input.fork();
1916                let content;
1917                braced!(content in scan);
1918                if content.parse::<Expr>().is_ok() && content.is_empty() {
1919                    let expr_block = verbatim::between(input, &scan);
1920                    input.advance_to(&scan);
1921                    return Ok(Expr::Verbatim(expr_block));
1922                }
1923            }
1924            Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
1925        }
1926    }
1927
1928    #[cfg(feature = "full")]
1929    fn expr_builtin(input: ParseStream) -> Result<Expr> {
1930        let begin = input.fork();
1931
1932        input.parse::<kw::builtin>()?;
1933        input.parse::<Token![#]>()?;
1934        input.parse::<Ident>()?;
1935
1936        let args;
1937        parenthesized!(args in input);
1938        args.parse::<TokenStream>()?;
1939
1940        Ok(Expr::Verbatim(verbatim::between(&begin, input)))
1941    }
1942
1943    fn path_or_macro_or_struct(
1944        input: ParseStream,
1945        #[cfg(feature = "full")] allow_struct: AllowStruct,
1946    ) -> Result<Expr> {
1947        let (qself, path) = path::parsing::qpath(input, true)?;
1948        rest_of_path_or_macro_or_struct(
1949            qself,
1950            path,
1951            input,
1952            #[cfg(feature = "full")]
1953            allow_struct,
1954        )
1955    }
1956
1957    fn rest_of_path_or_macro_or_struct(
1958        qself: Option<QSelf>,
1959        path: Path,
1960        input: ParseStream,
1961        #[cfg(feature = "full")] allow_struct: AllowStruct,
1962    ) -> Result<Expr> {
1963        if qself.is_none()
1964            && input.peek(Token![!])
1965            && !input.peek(Token![!=])
1966            && path.is_mod_style()
1967        {
1968            let bang_token: Token![!] = input.parse()?;
1969            let (delimiter, tokens) = mac::parse_delimiter(input)?;
1970            return Ok(Expr::Macro(ExprMacro {
1971                attrs: Vec::new(),
1972                mac: Macro {
1973                    path,
1974                    bang_token,
1975                    delimiter,
1976                    tokens,
1977                },
1978            }));
1979        }
1980
1981        #[cfg(not(feature = "full"))]
1982        let allow_struct = (true,);
1983        if allow_struct.0 && input.peek(token::Brace) {
1984            return expr_struct_helper(input, qself, path).map(Expr::Struct);
1985        }
1986
1987        Ok(Expr::Path(ExprPath {
1988            attrs: Vec::new(),
1989            qself,
1990            path,
1991        }))
1992    }
1993
1994    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
1995    impl Parse for ExprMacro {
1996        fn parse(input: ParseStream) -> Result<Self> {
1997            Ok(ExprMacro {
1998                attrs: Vec::new(),
1999                mac: input.parse()?,
2000            })
2001        }
2002    }
2003
2004    #[cfg(feature = "full")]
2005    fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
2006        let content;
2007        let paren_token = parenthesized!(content in input);
2008        if content.is_empty() {
2009            return Ok(Expr::Tuple(ExprTuple {
2010                attrs: Vec::new(),
2011                paren_token,
2012                elems: Punctuated::new(),
2013            }));
2014        }
2015
2016        let first: Expr = content.parse()?;
2017        if content.is_empty() {
2018            return Ok(Expr::Paren(ExprParen {
2019                attrs: Vec::new(),
2020                paren_token,
2021                expr: Box::new(first),
2022            }));
2023        }
2024
2025        let mut elems = Punctuated::new();
2026        elems.push_value(first);
2027        while !content.is_empty() {
2028            let punct = content.parse()?;
2029            elems.push_punct(punct);
2030            if content.is_empty() {
2031                break;
2032            }
2033            let value = content.parse()?;
2034            elems.push_value(value);
2035        }
2036        Ok(Expr::Tuple(ExprTuple {
2037            attrs: Vec::new(),
2038            paren_token,
2039            elems,
2040        }))
2041    }
2042
2043    #[cfg(feature = "full")]
2044    fn array_or_repeat(input: ParseStream) -> Result<Expr> {
2045        let content;
2046        let bracket_token = bracketed!(content in input);
2047        if content.is_empty() {
2048            return Ok(Expr::Array(ExprArray {
2049                attrs: Vec::new(),
2050                bracket_token,
2051                elems: Punctuated::new(),
2052            }));
2053        }
2054
2055        let first: Expr = content.parse()?;
2056        if content.is_empty() || content.peek(Token![,]) {
2057            let mut elems = Punctuated::new();
2058            elems.push_value(first);
2059            while !content.is_empty() {
2060                let punct = content.parse()?;
2061                elems.push_punct(punct);
2062                if content.is_empty() {
2063                    break;
2064                }
2065                let value = content.parse()?;
2066                elems.push_value(value);
2067            }
2068            Ok(Expr::Array(ExprArray {
2069                attrs: Vec::new(),
2070                bracket_token,
2071                elems,
2072            }))
2073        } else if content.peek(Token![;]) {
2074            let semi_token: Token![;] = content.parse()?;
2075            let len: Expr = content.parse()?;
2076            Ok(Expr::Repeat(ExprRepeat {
2077                attrs: Vec::new(),
2078                bracket_token,
2079                expr: Box::new(first),
2080                semi_token,
2081                len: Box::new(len),
2082            }))
2083        } else {
2084            Err(content.error("expected `,` or `;`"))
2085        }
2086    }
2087
2088    #[cfg(feature = "full")]
2089    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2090    impl Parse for ExprArray {
2091        fn parse(input: ParseStream) -> Result<Self> {
2092            let content;
2093            let bracket_token = bracketed!(content in input);
2094            let mut elems = Punctuated::new();
2095
2096            while !content.is_empty() {
2097                let first: Expr = content.parse()?;
2098                elems.push_value(first);
2099                if content.is_empty() {
2100                    break;
2101                }
2102                let punct = content.parse()?;
2103                elems.push_punct(punct);
2104            }
2105
2106            Ok(ExprArray {
2107                attrs: Vec::new(),
2108                bracket_token,
2109                elems,
2110            })
2111        }
2112    }
2113
2114    #[cfg(feature = "full")]
2115    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2116    impl Parse for ExprRepeat {
2117        fn parse(input: ParseStream) -> Result<Self> {
2118            let content;
2119            Ok(ExprRepeat {
2120                bracket_token: bracketed!(content in input),
2121                attrs: Vec::new(),
2122                expr: content.parse()?,
2123                semi_token: content.parse()?,
2124                len: content.parse()?,
2125            })
2126        }
2127    }
2128
2129    #[cfg(feature = "full")]
2130    fn continue_parsing_early(mut expr: &Expr) -> bool {
2131        while let Expr::Group(group) = expr {
2132            expr = &group.expr;
2133        }
2134        match expr {
2135            Expr::If(_)
2136            | Expr::While(_)
2137            | Expr::ForLoop(_)
2138            | Expr::Loop(_)
2139            | Expr::Match(_)
2140            | Expr::TryBlock(_)
2141            | Expr::Unsafe(_)
2142            | Expr::Const(_)
2143            | Expr::Block(_) => false,
2144            _ => true,
2145        }
2146    }
2147
2148    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2149    impl Parse for ExprLit {
2150        fn parse(input: ParseStream) -> Result<Self> {
2151            Ok(ExprLit {
2152                attrs: Vec::new(),
2153                lit: input.parse()?,
2154            })
2155        }
2156    }
2157
2158    fn expr_group(
2159        input: ParseStream,
2160        #[cfg(feature = "full")] allow_struct: AllowStruct,
2161    ) -> Result<Expr> {
2162        let group = crate::group::parse_group(input)?;
2163        let mut inner: Expr = group.content.parse()?;
2164
2165        match inner {
2166            Expr::Path(mut expr) if expr.attrs.is_empty() => {
2167                let grouped_len = expr.path.segments.len();
2168                Path::parse_rest(input, &mut expr.path, true)?;
2169                match rest_of_path_or_macro_or_struct(
2170                    expr.qself,
2171                    expr.path,
2172                    input,
2173                    #[cfg(feature = "full")]
2174                    allow_struct,
2175                )? {
2176                    Expr::Path(expr) if expr.path.segments.len() == grouped_len => {
2177                        inner = Expr::Path(expr);
2178                    }
2179                    extended => return Ok(extended),
2180                }
2181            }
2182            _ => {}
2183        }
2184
2185        Ok(Expr::Group(ExprGroup {
2186            attrs: Vec::new(),
2187            group_token: group.token,
2188            expr: Box::new(inner),
2189        }))
2190    }
2191
2192    #[cfg(feature = "full")]
2193    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2194    impl Parse for ExprParen {
2195        fn parse(input: ParseStream) -> Result<Self> {
2196            expr_paren(input)
2197        }
2198    }
2199
2200    fn expr_paren(input: ParseStream) -> Result<ExprParen> {
2201        let content;
2202        Ok(ExprParen {
2203            attrs: Vec::new(),
2204            paren_token: parenthesized!(content in input),
2205            expr: content.parse()?,
2206        })
2207    }
2208
2209    #[cfg(feature = "full")]
2210    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2211    impl Parse for ExprLet {
2212        fn parse(input: ParseStream) -> Result<Self> {
2213            Ok(ExprLet {
2214                attrs: Vec::new(),
2215                let_token: input.parse()?,
2216                pat: Box::new(Pat::parse_multi_with_leading_vert(input)?),
2217                eq_token: input.parse()?,
2218                expr: Box::new({
2219                    let allow_struct = AllowStruct(false);
2220                    let lhs = unary_expr(input, allow_struct)?;
2221                    parse_expr(input, lhs, allow_struct, Precedence::Compare)?
2222                }),
2223            })
2224        }
2225    }
2226
2227    #[cfg(feature = "full")]
2228    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2229    impl Parse for ExprIf {
2230        fn parse(input: ParseStream) -> Result<Self> {
2231            let attrs = input.call(Attribute::parse_outer)?;
2232            Ok(ExprIf {
2233                attrs,
2234                if_token: input.parse()?,
2235                cond: Box::new(input.call(Expr::parse_without_eager_brace)?),
2236                then_branch: input.parse()?,
2237                else_branch: {
2238                    if input.peek(Token![else]) {
2239                        Some(input.call(else_block)?)
2240                    } else {
2241                        None
2242                    }
2243                },
2244            })
2245        }
2246    }
2247
2248    #[cfg(feature = "full")]
2249    fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
2250        let else_token: Token![else] = input.parse()?;
2251
2252        let lookahead = input.lookahead1();
2253        let else_branch = if lookahead.peek(Token![if]) {
2254            input.parse().map(Expr::If)?
2255        } else if lookahead.peek(token::Brace) {
2256            Expr::Block(ExprBlock {
2257                attrs: Vec::new(),
2258                label: None,
2259                block: input.parse()?,
2260            })
2261        } else {
2262            return Err(lookahead.error());
2263        };
2264
2265        Ok((else_token, Box::new(else_branch)))
2266    }
2267
2268    #[cfg(feature = "full")]
2269    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2270    impl Parse for ExprInfer {
2271        fn parse(input: ParseStream) -> Result<Self> {
2272            Ok(ExprInfer {
2273                attrs: input.call(Attribute::parse_outer)?,
2274                underscore_token: input.parse()?,
2275            })
2276        }
2277    }
2278
2279    #[cfg(feature = "full")]
2280    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2281    impl Parse for ExprForLoop {
2282        fn parse(input: ParseStream) -> Result<Self> {
2283            let mut attrs = input.call(Attribute::parse_outer)?;
2284            let label: Option<Label> = input.parse()?;
2285            let for_token: Token![for] = input.parse()?;
2286
2287            let pat = Pat::parse_multi_with_leading_vert(input)?;
2288
2289            let in_token: Token![in] = input.parse()?;
2290            let expr: Expr = input.call(Expr::parse_without_eager_brace)?;
2291
2292            let content;
2293            let brace_token = braced!(content in input);
2294            attr::parsing::parse_inner(&content, &mut attrs)?;
2295            let stmts = content.call(Block::parse_within)?;
2296
2297            Ok(ExprForLoop {
2298                attrs,
2299                label,
2300                for_token,
2301                pat: Box::new(pat),
2302                in_token,
2303                expr: Box::new(expr),
2304                body: Block { brace_token, stmts },
2305            })
2306        }
2307    }
2308
2309    #[cfg(feature = "full")]
2310    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2311    impl Parse for ExprLoop {
2312        fn parse(input: ParseStream) -> Result<Self> {
2313            let mut attrs = input.call(Attribute::parse_outer)?;
2314            let label: Option<Label> = input.parse()?;
2315            let loop_token: Token![loop] = input.parse()?;
2316
2317            let content;
2318            let brace_token = braced!(content in input);
2319            attr::parsing::parse_inner(&content, &mut attrs)?;
2320            let stmts = content.call(Block::parse_within)?;
2321
2322            Ok(ExprLoop {
2323                attrs,
2324                label,
2325                loop_token,
2326                body: Block { brace_token, stmts },
2327            })
2328        }
2329    }
2330
2331    #[cfg(feature = "full")]
2332    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2333    impl Parse for ExprMatch {
2334        fn parse(input: ParseStream) -> Result<Self> {
2335            let mut attrs = input.call(Attribute::parse_outer)?;
2336            let match_token: Token![match] = input.parse()?;
2337            let expr = Expr::parse_without_eager_brace(input)?;
2338
2339            let content;
2340            let brace_token = braced!(content in input);
2341            attr::parsing::parse_inner(&content, &mut attrs)?;
2342
2343            let mut arms = Vec::new();
2344            while !content.is_empty() {
2345                arms.push(content.call(Arm::parse)?);
2346            }
2347
2348            Ok(ExprMatch {
2349                attrs,
2350                match_token,
2351                expr: Box::new(expr),
2352                brace_token,
2353                arms,
2354            })
2355        }
2356    }
2357
2358    macro_rules! impl_by_parsing_expr {
2359        (
2360            $(
2361                $expr_type:ty, $variant:ident, $msg:expr,
2362            )*
2363        ) => {
2364            $(
2365                #[cfg(all(feature = "full", feature = "printing"))]
2366                #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2367                impl Parse for $expr_type {
2368                    fn parse(input: ParseStream) -> Result<Self> {
2369                        let mut expr: Expr = input.parse()?;
2370                        loop {
2371                            match expr {
2372                                Expr::$variant(inner) => return Ok(inner),
2373                                Expr::Group(next) => expr = *next.expr,
2374                                _ => return Err(Error::new_spanned(expr, $msg)),
2375                            }
2376                        }
2377                    }
2378                }
2379            )*
2380        };
2381    }
2382
2383    impl_by_parsing_expr! {
2384        ExprAssign, Assign, "expected assignment expression",
2385        ExprAwait, Await, "expected await expression",
2386        ExprBinary, Binary, "expected binary operation",
2387        ExprCall, Call, "expected function call expression",
2388        ExprCast, Cast, "expected cast expression",
2389        ExprField, Field, "expected struct field access",
2390        ExprIndex, Index, "expected indexing expression",
2391        ExprMethodCall, MethodCall, "expected method call expression",
2392        ExprRange, Range, "expected range expression",
2393        ExprTry, Try, "expected try expression",
2394        ExprTuple, Tuple, "expected tuple expression",
2395    }
2396
2397    #[cfg(feature = "full")]
2398    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2399    impl Parse for ExprUnary {
2400        fn parse(input: ParseStream) -> Result<Self> {
2401            let attrs = Vec::new();
2402            let allow_struct = AllowStruct(true);
2403            expr_unary(input, attrs, allow_struct)
2404        }
2405    }
2406
2407    #[cfg(feature = "full")]
2408    fn expr_unary(
2409        input: ParseStream,
2410        attrs: Vec<Attribute>,
2411        allow_struct: AllowStruct,
2412    ) -> Result<ExprUnary> {
2413        Ok(ExprUnary {
2414            attrs,
2415            op: input.parse()?,
2416            expr: Box::new(unary_expr(input, allow_struct)?),
2417        })
2418    }
2419
2420    #[cfg(feature = "full")]
2421    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2422    impl Parse for ExprClosure {
2423        fn parse(input: ParseStream) -> Result<Self> {
2424            let allow_struct = AllowStruct(true);
2425            expr_closure(input, allow_struct)
2426        }
2427    }
2428
2429    #[cfg(feature = "full")]
2430    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2431    impl Parse for ExprReference {
2432        fn parse(input: ParseStream) -> Result<Self> {
2433            let allow_struct = AllowStruct(true);
2434            Ok(ExprReference {
2435                attrs: Vec::new(),
2436                and_token: input.parse()?,
2437                mutability: input.parse()?,
2438                expr: Box::new(unary_expr(input, allow_struct)?),
2439            })
2440        }
2441    }
2442
2443    #[cfg(feature = "full")]
2444    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2445    impl Parse for ExprBreak {
2446        fn parse(input: ParseStream) -> Result<Self> {
2447            let allow_struct = AllowStruct(true);
2448            expr_break(input, allow_struct)
2449        }
2450    }
2451
2452    #[cfg(feature = "full")]
2453    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2454    impl Parse for ExprReturn {
2455        fn parse(input: ParseStream) -> Result<Self> {
2456            let allow_struct = AllowStruct(true);
2457            expr_return(input, allow_struct)
2458        }
2459    }
2460
2461    #[cfg(feature = "full")]
2462    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2463    impl Parse for ExprTryBlock {
2464        fn parse(input: ParseStream) -> Result<Self> {
2465            Ok(ExprTryBlock {
2466                attrs: Vec::new(),
2467                try_token: input.parse()?,
2468                block: input.parse()?,
2469            })
2470        }
2471    }
2472
2473    #[cfg(feature = "full")]
2474    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2475    impl Parse for ExprYield {
2476        fn parse(input: ParseStream) -> Result<Self> {
2477            Ok(ExprYield {
2478                attrs: Vec::new(),
2479                yield_token: input.parse()?,
2480                expr: {
2481                    if can_begin_expr(input) {
2482                        Some(input.parse()?)
2483                    } else {
2484                        None
2485                    }
2486                },
2487            })
2488        }
2489    }
2490
2491    #[cfg(feature = "full")]
2492    fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
2493        let lifetimes: Option<BoundLifetimes> = input.parse()?;
2494        let constness: Option<Token![const]> = input.parse()?;
2495        let movability: Option<Token![static]> = input.parse()?;
2496        let asyncness: Option<Token![async]> = input.parse()?;
2497        let capture: Option<Token![move]> = input.parse()?;
2498        let or1_token: Token![|] = input.parse()?;
2499
2500        let mut inputs = Punctuated::new();
2501        loop {
2502            if input.peek(Token![|]) {
2503                break;
2504            }
2505            let value = closure_arg(input)?;
2506            inputs.push_value(value);
2507            if input.peek(Token![|]) {
2508                break;
2509            }
2510            let punct: Token![,] = input.parse()?;
2511            inputs.push_punct(punct);
2512        }
2513
2514        let or2_token: Token![|] = input.parse()?;
2515
2516        let (output, body) = if input.peek(Token![->]) {
2517            let arrow_token: Token![->] = input.parse()?;
2518            let ty: Type = input.parse()?;
2519            let body: Block = input.parse()?;
2520            let output = ReturnType::Type(arrow_token, Box::new(ty));
2521            let block = Expr::Block(ExprBlock {
2522                attrs: Vec::new(),
2523                label: None,
2524                block: body,
2525            });
2526            (output, block)
2527        } else {
2528            let body = ambiguous_expr(input, allow_struct)?;
2529            (ReturnType::Default, body)
2530        };
2531
2532        Ok(ExprClosure {
2533            attrs: Vec::new(),
2534            lifetimes,
2535            constness,
2536            movability,
2537            asyncness,
2538            capture,
2539            or1_token,
2540            inputs,
2541            or2_token,
2542            output,
2543            body: Box::new(body),
2544        })
2545    }
2546
2547    #[cfg(feature = "full")]
2548    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2549    impl Parse for ExprAsync {
2550        fn parse(input: ParseStream) -> Result<Self> {
2551            Ok(ExprAsync {
2552                attrs: Vec::new(),
2553                async_token: input.parse()?,
2554                capture: input.parse()?,
2555                block: input.parse()?,
2556            })
2557        }
2558    }
2559
2560    #[cfg(feature = "full")]
2561    fn closure_arg(input: ParseStream) -> Result<Pat> {
2562        let attrs = input.call(Attribute::parse_outer)?;
2563        let mut pat = Pat::parse_single(input)?;
2564
2565        if input.peek(Token![:]) {
2566            Ok(Pat::Type(PatType {
2567                attrs,
2568                pat: Box::new(pat),
2569                colon_token: input.parse()?,
2570                ty: input.parse()?,
2571            }))
2572        } else {
2573            match &mut pat {
2574                Pat::Const(pat) => pat.attrs = attrs,
2575                Pat::Ident(pat) => pat.attrs = attrs,
2576                Pat::Lit(pat) => pat.attrs = attrs,
2577                Pat::Macro(pat) => pat.attrs = attrs,
2578                Pat::Or(pat) => pat.attrs = attrs,
2579                Pat::Paren(pat) => pat.attrs = attrs,
2580                Pat::Path(pat) => pat.attrs = attrs,
2581                Pat::Range(pat) => pat.attrs = attrs,
2582                Pat::Reference(pat) => pat.attrs = attrs,
2583                Pat::Rest(pat) => pat.attrs = attrs,
2584                Pat::Slice(pat) => pat.attrs = attrs,
2585                Pat::Struct(pat) => pat.attrs = attrs,
2586                Pat::Tuple(pat) => pat.attrs = attrs,
2587                Pat::TupleStruct(pat) => pat.attrs = attrs,
2588                Pat::Type(_) => unreachable!(),
2589                Pat::Verbatim(_) => {}
2590                Pat::Wild(pat) => pat.attrs = attrs,
2591            }
2592            Ok(pat)
2593        }
2594    }
2595
2596    #[cfg(feature = "full")]
2597    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2598    impl Parse for ExprWhile {
2599        fn parse(input: ParseStream) -> Result<Self> {
2600            let mut attrs = input.call(Attribute::parse_outer)?;
2601            let label: Option<Label> = input.parse()?;
2602            let while_token: Token![while] = input.parse()?;
2603            let cond = Expr::parse_without_eager_brace(input)?;
2604
2605            let content;
2606            let brace_token = braced!(content in input);
2607            attr::parsing::parse_inner(&content, &mut attrs)?;
2608            let stmts = content.call(Block::parse_within)?;
2609
2610            Ok(ExprWhile {
2611                attrs,
2612                label,
2613                while_token,
2614                cond: Box::new(cond),
2615                body: Block { brace_token, stmts },
2616            })
2617        }
2618    }
2619
2620    #[cfg(feature = "full")]
2621    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2622    impl Parse for ExprConst {
2623        fn parse(input: ParseStream) -> Result<Self> {
2624            let const_token: Token![const] = input.parse()?;
2625
2626            let content;
2627            let brace_token = braced!(content in input);
2628            let inner_attrs = content.call(Attribute::parse_inner)?;
2629            let stmts = content.call(Block::parse_within)?;
2630
2631            Ok(ExprConst {
2632                attrs: inner_attrs,
2633                const_token,
2634                block: Block { brace_token, stmts },
2635            })
2636        }
2637    }
2638
2639    #[cfg(feature = "full")]
2640    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2641    impl Parse for Label {
2642        fn parse(input: ParseStream) -> Result<Self> {
2643            Ok(Label {
2644                name: input.parse()?,
2645                colon_token: input.parse()?,
2646            })
2647        }
2648    }
2649
2650    #[cfg(feature = "full")]
2651    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2652    impl Parse for Option<Label> {
2653        fn parse(input: ParseStream) -> Result<Self> {
2654            if input.peek(Lifetime) {
2655                input.parse().map(Some)
2656            } else {
2657                Ok(None)
2658            }
2659        }
2660    }
2661
2662    #[cfg(feature = "full")]
2663    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2664    impl Parse for ExprContinue {
2665        fn parse(input: ParseStream) -> Result<Self> {
2666            Ok(ExprContinue {
2667                attrs: Vec::new(),
2668                continue_token: input.parse()?,
2669                label: input.parse()?,
2670            })
2671        }
2672    }
2673
2674    #[cfg(feature = "full")]
2675    fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2676        let break_token: Token![break] = input.parse()?;
2677
2678        let ahead = input.fork();
2679        let label: Option<Lifetime> = ahead.parse()?;
2680        if label.is_some() && ahead.peek(Token![:]) {
2681            // Not allowed: `break 'label: loop {...}`
2682            // Parentheses are required. `break ('label: loop {...})`
2683            let _ = ambiguous_expr(input, allow_struct)?;
2684            let start_span = label.unwrap().apostrophe;
2685            let end_span = input.cursor().prev_span();
2686            return Err(crate::error::new2(
2687                start_span,
2688                end_span,
2689                "parentheses required",
2690            ));
2691        }
2692
2693        input.advance_to(&ahead);
2694        let expr = if can_begin_expr(input) && (allow_struct.0 || !input.peek(token::Brace)) {
2695            let expr = ambiguous_expr(input, allow_struct)?;
2696            Some(Box::new(expr))
2697        } else {
2698            None
2699        };
2700
2701        Ok(ExprBreak {
2702            attrs: Vec::new(),
2703            break_token,
2704            label,
2705            expr,
2706        })
2707    }
2708
2709    #[cfg(feature = "full")]
2710    fn expr_return(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
2711        Ok(ExprReturn {
2712            attrs: Vec::new(),
2713            return_token: input.parse()?,
2714            expr: {
2715                if can_begin_expr(input) {
2716                    // NOTE: return is greedy and eats blocks after it even when in a
2717                    // position where structs are not allowed, such as in if statement
2718                    // conditions. For example:
2719                    //
2720                    // if return { println!("A") } {} // Prints "A"
2721                    let expr = ambiguous_expr(input, allow_struct)?;
2722                    Some(Box::new(expr))
2723                } else {
2724                    None
2725                }
2726            },
2727        })
2728    }
2729
2730    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2731    impl Parse for FieldValue {
2732        fn parse(input: ParseStream) -> Result<Self> {
2733            let attrs = input.call(Attribute::parse_outer)?;
2734            let member: Member = input.parse()?;
2735            let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
2736                let colon_token: Token![:] = input.parse()?;
2737                let value: Expr = input.parse()?;
2738                (Some(colon_token), value)
2739            } else if let Member::Named(ident) = &member {
2740                let value = Expr::Path(ExprPath {
2741                    attrs: Vec::new(),
2742                    qself: None,
2743                    path: Path::from(ident.clone()),
2744                });
2745                (None, value)
2746            } else {
2747                unreachable!()
2748            };
2749
2750            Ok(FieldValue {
2751                attrs,
2752                member,
2753                colon_token,
2754                expr: value,
2755            })
2756        }
2757    }
2758
2759    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2760    impl Parse for ExprStruct {
2761        fn parse(input: ParseStream) -> Result<Self> {
2762            let (qself, path) = path::parsing::qpath(input, true)?;
2763            expr_struct_helper(input, qself, path)
2764        }
2765    }
2766
2767    fn expr_struct_helper(
2768        input: ParseStream,
2769        qself: Option<QSelf>,
2770        path: Path,
2771    ) -> Result<ExprStruct> {
2772        let content;
2773        let brace_token = braced!(content in input);
2774
2775        let mut fields = Punctuated::new();
2776        while !content.is_empty() {
2777            if content.peek(Token![..]) {
2778                return Ok(ExprStruct {
2779                    attrs: Vec::new(),
2780                    qself,
2781                    path,
2782                    brace_token,
2783                    fields,
2784                    dot2_token: Some(content.parse()?),
2785                    rest: if content.is_empty() {
2786                        None
2787                    } else {
2788                        Some(Box::new(content.parse()?))
2789                    },
2790                });
2791            }
2792
2793            fields.push(content.parse()?);
2794            if content.is_empty() {
2795                break;
2796            }
2797            let punct: Token![,] = content.parse()?;
2798            fields.push_punct(punct);
2799        }
2800
2801        Ok(ExprStruct {
2802            attrs: Vec::new(),
2803            qself,
2804            path,
2805            brace_token,
2806            fields,
2807            dot2_token: None,
2808            rest: None,
2809        })
2810    }
2811
2812    #[cfg(feature = "full")]
2813    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2814    impl Parse for ExprUnsafe {
2815        fn parse(input: ParseStream) -> Result<Self> {
2816            let unsafe_token: Token![unsafe] = input.parse()?;
2817
2818            let content;
2819            let brace_token = braced!(content in input);
2820            let inner_attrs = content.call(Attribute::parse_inner)?;
2821            let stmts = content.call(Block::parse_within)?;
2822
2823            Ok(ExprUnsafe {
2824                attrs: inner_attrs,
2825                unsafe_token,
2826                block: Block { brace_token, stmts },
2827            })
2828        }
2829    }
2830
2831    #[cfg(feature = "full")]
2832    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2833    impl Parse for ExprBlock {
2834        fn parse(input: ParseStream) -> Result<Self> {
2835            let mut attrs = input.call(Attribute::parse_outer)?;
2836            let label: Option<Label> = input.parse()?;
2837
2838            let content;
2839            let brace_token = braced!(content in input);
2840            attr::parsing::parse_inner(&content, &mut attrs)?;
2841            let stmts = content.call(Block::parse_within)?;
2842
2843            Ok(ExprBlock {
2844                attrs,
2845                label,
2846                block: Block { brace_token, stmts },
2847            })
2848        }
2849    }
2850
2851    #[cfg(feature = "full")]
2852    fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2853        let limits: RangeLimits = input.parse()?;
2854        let end = if matches!(limits, RangeLimits::HalfOpen(_))
2855            && (input.is_empty()
2856                || input.peek(Token![,])
2857                || input.peek(Token![;])
2858                || input.peek(Token![.]) && !input.peek(Token![..])
2859                || !allow_struct.0 && input.peek(token::Brace))
2860        {
2861            None
2862        } else {
2863            let to = ambiguous_expr(input, allow_struct)?;
2864            Some(Box::new(to))
2865        };
2866        Ok(ExprRange {
2867            attrs: Vec::new(),
2868            start: None,
2869            limits,
2870            end,
2871        })
2872    }
2873
2874    #[cfg(feature = "full")]
2875    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2876    impl Parse for RangeLimits {
2877        fn parse(input: ParseStream) -> Result<Self> {
2878            let lookahead = input.lookahead1();
2879            let dot_dot = lookahead.peek(Token![..]);
2880            let dot_dot_eq = dot_dot && lookahead.peek(Token![..=]);
2881            let dot_dot_dot = dot_dot && input.peek(Token![...]);
2882            if dot_dot_eq {
2883                input.parse().map(RangeLimits::Closed)
2884            } else if dot_dot && !dot_dot_dot {
2885                input.parse().map(RangeLimits::HalfOpen)
2886            } else {
2887                Err(lookahead.error())
2888            }
2889        }
2890    }
2891
2892    #[cfg(feature = "full")]
2893    impl RangeLimits {
2894        pub(crate) fn parse_obsolete(input: ParseStream) -> Result<Self> {
2895            let lookahead = input.lookahead1();
2896            let dot_dot = lookahead.peek(Token![..]);
2897            let dot_dot_eq = dot_dot && lookahead.peek(Token![..=]);
2898            let dot_dot_dot = dot_dot && input.peek(Token![...]);
2899            if dot_dot_eq {
2900                input.parse().map(RangeLimits::Closed)
2901            } else if dot_dot_dot {
2902                let dot3: Token![...] = input.parse()?;
2903                Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2904            } else if dot_dot {
2905                input.parse().map(RangeLimits::HalfOpen)
2906            } else {
2907                Err(lookahead.error())
2908            }
2909        }
2910    }
2911
2912    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2913    impl Parse for ExprPath {
2914        fn parse(input: ParseStream) -> Result<Self> {
2915            #[cfg(not(feature = "full"))]
2916            let attrs = Vec::new();
2917            #[cfg(feature = "full")]
2918            let attrs = input.call(Attribute::parse_outer)?;
2919
2920            let (qself, path) = path::parsing::qpath(input, true)?;
2921
2922            Ok(ExprPath { attrs, qself, path })
2923        }
2924    }
2925
2926    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2927    impl Parse for Member {
2928        fn parse(input: ParseStream) -> Result<Self> {
2929            if input.peek(Ident) {
2930                input.parse().map(Member::Named)
2931            } else if input.peek(LitInt) {
2932                input.parse().map(Member::Unnamed)
2933            } else {
2934                Err(input.error("expected identifier or integer"))
2935            }
2936        }
2937    }
2938
2939    #[cfg(feature = "full")]
2940    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2941    impl Parse for Arm {
2942        fn parse(input: ParseStream) -> Result<Arm> {
2943            let requires_comma;
2944            Ok(Arm {
2945                attrs: input.call(Attribute::parse_outer)?,
2946                pat: Pat::parse_multi_with_leading_vert(input)?,
2947                guard: {
2948                    if input.peek(Token![if]) {
2949                        let if_token: Token![if] = input.parse()?;
2950                        let guard: Expr = input.parse()?;
2951                        Some((if_token, Box::new(guard)))
2952                    } else {
2953                        None
2954                    }
2955                },
2956                fat_arrow_token: input.parse()?,
2957                body: {
2958                    let body = Expr::parse_with_earlier_boundary_rule(input)?;
2959                    requires_comma = requires_terminator(&body);
2960                    Box::new(body)
2961                },
2962                comma: {
2963                    if requires_comma && !input.is_empty() {
2964                        Some(input.parse()?)
2965                    } else {
2966                        input.parse()?
2967                    }
2968                },
2969            })
2970        }
2971    }
2972
2973    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2974    impl Parse for Index {
2975        fn parse(input: ParseStream) -> Result<Self> {
2976            let lit: LitInt = input.parse()?;
2977            if lit.suffix().is_empty() {
2978                Ok(Index {
2979                    index: lit
2980                        .base10_digits()
2981                        .parse()
2982                        .map_err(|err| Error::new(lit.span(), err))?,
2983                    span: lit.span(),
2984                })
2985            } else {
2986                Err(Error::new(lit.span(), "expected unsuffixed integer"))
2987            }
2988        }
2989    }
2990
2991    fn multi_index(e: &mut Expr, dot_token: &mut Token![.], float: LitFloat) -> Result<bool> {
2992        let float_token = float.token();
2993        let float_span = float_token.span();
2994        let mut float_repr = float_token.to_string();
2995        let trailing_dot = float_repr.ends_with('.');
2996        if trailing_dot {
2997            float_repr.truncate(float_repr.len() - 1);
2998        }
2999
3000        let mut offset = 0;
3001        for part in float_repr.split('.') {
3002            let mut index: Index =
3003                crate::parse_str(part).map_err(|err| Error::new(float_span, err))?;
3004            let part_end = offset + part.len();
3005            index.span = float_token.subspan(offset..part_end).unwrap_or(float_span);
3006
3007            let base = mem::replace(e, Expr::DUMMY);
3008            *e = Expr::Field(ExprField {
3009                attrs: Vec::new(),
3010                base: Box::new(base),
3011                dot_token: Token![.](dot_token.span),
3012                member: Member::Unnamed(index),
3013            });
3014
3015            let dot_span = float_token
3016                .subspan(part_end..part_end + 1)
3017                .unwrap_or(float_span);
3018            *dot_token = Token![.](dot_span);
3019            offset = part_end + 1;
3020        }
3021
3022        Ok(!trailing_dot)
3023    }
3024
3025    impl Member {
3026        pub(crate) fn is_named(&self) -> bool {
3027            match self {
3028                Member::Named(_) => true,
3029                Member::Unnamed(_) => false,
3030            }
3031        }
3032    }
3033
3034    fn check_cast(input: ParseStream) -> Result<()> {
3035        let kind = if input.peek(Token![.]) && !input.peek(Token![..]) {
3036            if input.peek2(Token![await]) {
3037                "`.await`"
3038            } else if input.peek2(Ident) && (input.peek3(token::Paren) || input.peek3(Token![::])) {
3039                "a method call"
3040            } else {
3041                "a field access"
3042            }
3043        } else if input.peek(Token![?]) {
3044            "`?`"
3045        } else if input.peek(token::Bracket) {
3046            "indexing"
3047        } else if input.peek(token::Paren) {
3048            "a function call"
3049        } else {
3050            return Ok(());
3051        };
3052        let msg = format!("casts cannot be followed by {}", kind);
3053        Err(input.error(msg))
3054    }
3055}
3056
3057#[cfg(feature = "printing")]
3058pub(crate) mod printing {
3059    use crate::attr::Attribute;
3060    #[cfg(feature = "full")]
3061    use crate::attr::FilterAttrs;
3062    #[cfg(feature = "full")]
3063    use crate::expr::{
3064        requires_terminator, Arm, Expr, ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock,
3065        ExprBreak, ExprClosure, ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer, ExprLet,
3066        ExprLoop, ExprMatch, ExprRange, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprTuple,
3067        ExprUnsafe, ExprWhile, ExprYield, Label, RangeLimits,
3068    };
3069    use crate::expr::{
3070        ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro,
3071        ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprUnary, FieldValue,
3072        Index, Member,
3073    };
3074    use crate::path;
3075    #[cfg(feature = "full")]
3076    use crate::token;
3077    use proc_macro2::{Literal, Span, TokenStream};
3078    use quote::{ToTokens, TokenStreamExt};
3079
3080    // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
3081    // before appending it to `TokenStream`.
3082    #[cfg(feature = "full")]
3083    fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) {
3084        if let Expr::Struct(_) = *e {
3085            token::Paren::default().surround(tokens, |tokens| {
3086                e.to_tokens(tokens);
3087            });
3088        } else {
3089            e.to_tokens(tokens);
3090        }
3091    }
3092
3093    #[cfg(feature = "full")]
3094    pub(crate) fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3095        tokens.append_all(attrs.outer());
3096    }
3097
3098    #[cfg(feature = "full")]
3099    fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3100        tokens.append_all(attrs.inner());
3101    }
3102
3103    #[cfg(not(feature = "full"))]
3104    pub(crate) fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3105
3106    #[cfg(feature = "full")]
3107    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3108    impl ToTokens for ExprArray {
3109        fn to_tokens(&self, tokens: &mut TokenStream) {
3110            outer_attrs_to_tokens(&self.attrs, tokens);
3111            self.bracket_token.surround(tokens, |tokens| {
3112                self.elems.to_tokens(tokens);
3113            });
3114        }
3115    }
3116
3117    #[cfg(feature = "full")]
3118    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3119    impl ToTokens for ExprAssign {
3120        fn to_tokens(&self, tokens: &mut TokenStream) {
3121            outer_attrs_to_tokens(&self.attrs, tokens);
3122            self.left.to_tokens(tokens);
3123            self.eq_token.to_tokens(tokens);
3124            self.right.to_tokens(tokens);
3125        }
3126    }
3127
3128    #[cfg(feature = "full")]
3129    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3130    impl ToTokens for ExprAsync {
3131        fn to_tokens(&self, tokens: &mut TokenStream) {
3132            outer_attrs_to_tokens(&self.attrs, tokens);
3133            self.async_token.to_tokens(tokens);
3134            self.capture.to_tokens(tokens);
3135            self.block.to_tokens(tokens);
3136        }
3137    }
3138
3139    #[cfg(feature = "full")]
3140    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3141    impl ToTokens for ExprAwait {
3142        fn to_tokens(&self, tokens: &mut TokenStream) {
3143            outer_attrs_to_tokens(&self.attrs, tokens);
3144            self.base.to_tokens(tokens);
3145            self.dot_token.to_tokens(tokens);
3146            self.await_token.to_tokens(tokens);
3147        }
3148    }
3149
3150    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3151    impl ToTokens for ExprBinary {
3152        fn to_tokens(&self, tokens: &mut TokenStream) {
3153            outer_attrs_to_tokens(&self.attrs, tokens);
3154            self.left.to_tokens(tokens);
3155            self.op.to_tokens(tokens);
3156            self.right.to_tokens(tokens);
3157        }
3158    }
3159
3160    #[cfg(feature = "full")]
3161    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3162    impl ToTokens for ExprBlock {
3163        fn to_tokens(&self, tokens: &mut TokenStream) {
3164            outer_attrs_to_tokens(&self.attrs, tokens);
3165            self.label.to_tokens(tokens);
3166            self.block.brace_token.surround(tokens, |tokens| {
3167                inner_attrs_to_tokens(&self.attrs, tokens);
3168                tokens.append_all(&self.block.stmts);
3169            });
3170        }
3171    }
3172
3173    #[cfg(feature = "full")]
3174    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3175    impl ToTokens for ExprBreak {
3176        fn to_tokens(&self, tokens: &mut TokenStream) {
3177            outer_attrs_to_tokens(&self.attrs, tokens);
3178            self.break_token.to_tokens(tokens);
3179            self.label.to_tokens(tokens);
3180            self.expr.to_tokens(tokens);
3181        }
3182    }
3183
3184    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3185    impl ToTokens for ExprCall {
3186        fn to_tokens(&self, tokens: &mut TokenStream) {
3187            outer_attrs_to_tokens(&self.attrs, tokens);
3188            self.func.to_tokens(tokens);
3189            self.paren_token.surround(tokens, |tokens| {
3190                self.args.to_tokens(tokens);
3191            });
3192        }
3193    }
3194
3195    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3196    impl ToTokens for ExprCast {
3197        fn to_tokens(&self, tokens: &mut TokenStream) {
3198            outer_attrs_to_tokens(&self.attrs, tokens);
3199            self.expr.to_tokens(tokens);
3200            self.as_token.to_tokens(tokens);
3201            self.ty.to_tokens(tokens);
3202        }
3203    }
3204
3205    #[cfg(feature = "full")]
3206    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3207    impl ToTokens for ExprClosure {
3208        fn to_tokens(&self, tokens: &mut TokenStream) {
3209            outer_attrs_to_tokens(&self.attrs, tokens);
3210            self.lifetimes.to_tokens(tokens);
3211            self.constness.to_tokens(tokens);
3212            self.movability.to_tokens(tokens);
3213            self.asyncness.to_tokens(tokens);
3214            self.capture.to_tokens(tokens);
3215            self.or1_token.to_tokens(tokens);
3216            self.inputs.to_tokens(tokens);
3217            self.or2_token.to_tokens(tokens);
3218            self.output.to_tokens(tokens);
3219            self.body.to_tokens(tokens);
3220        }
3221    }
3222
3223    #[cfg(feature = "full")]
3224    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3225    impl ToTokens for ExprConst {
3226        fn to_tokens(&self, tokens: &mut TokenStream) {
3227            outer_attrs_to_tokens(&self.attrs, tokens);
3228            self.const_token.to_tokens(tokens);
3229            self.block.brace_token.surround(tokens, |tokens| {
3230                inner_attrs_to_tokens(&self.attrs, tokens);
3231                tokens.append_all(&self.block.stmts);
3232            });
3233        }
3234    }
3235
3236    #[cfg(feature = "full")]
3237    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3238    impl ToTokens for ExprContinue {
3239        fn to_tokens(&self, tokens: &mut TokenStream) {
3240            outer_attrs_to_tokens(&self.attrs, tokens);
3241            self.continue_token.to_tokens(tokens);
3242            self.label.to_tokens(tokens);
3243        }
3244    }
3245
3246    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3247    impl ToTokens for ExprField {
3248        fn to_tokens(&self, tokens: &mut TokenStream) {
3249            outer_attrs_to_tokens(&self.attrs, tokens);
3250            self.base.to_tokens(tokens);
3251            self.dot_token.to_tokens(tokens);
3252            self.member.to_tokens(tokens);
3253        }
3254    }
3255
3256    #[cfg(feature = "full")]
3257    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3258    impl ToTokens for ExprForLoop {
3259        fn to_tokens(&self, tokens: &mut TokenStream) {
3260            outer_attrs_to_tokens(&self.attrs, tokens);
3261            self.label.to_tokens(tokens);
3262            self.for_token.to_tokens(tokens);
3263            self.pat.to_tokens(tokens);
3264            self.in_token.to_tokens(tokens);
3265            wrap_bare_struct(tokens, &self.expr);
3266            self.body.brace_token.surround(tokens, |tokens| {
3267                inner_attrs_to_tokens(&self.attrs, tokens);
3268                tokens.append_all(&self.body.stmts);
3269            });
3270        }
3271    }
3272
3273    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3274    impl ToTokens for ExprGroup {
3275        fn to_tokens(&self, tokens: &mut TokenStream) {
3276            outer_attrs_to_tokens(&self.attrs, tokens);
3277            self.group_token.surround(tokens, |tokens| {
3278                self.expr.to_tokens(tokens);
3279            });
3280        }
3281    }
3282
3283    #[cfg(feature = "full")]
3284    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3285    impl ToTokens for ExprIf {
3286        fn to_tokens(&self, tokens: &mut TokenStream) {
3287            outer_attrs_to_tokens(&self.attrs, tokens);
3288            self.if_token.to_tokens(tokens);
3289            wrap_bare_struct(tokens, &self.cond);
3290            self.then_branch.to_tokens(tokens);
3291            if let Some((else_token, else_)) = &self.else_branch {
3292                else_token.to_tokens(tokens);
3293                // If we are not one of the valid expressions to exist in an else
3294                // clause, wrap ourselves in a block.
3295                match **else_ {
3296                    Expr::If(_) | Expr::Block(_) => else_.to_tokens(tokens),
3297                    _ => token::Brace::default().surround(tokens, |tokens| else_.to_tokens(tokens)),
3298                }
3299            }
3300        }
3301    }
3302
3303    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3304    impl ToTokens for ExprIndex {
3305        fn to_tokens(&self, tokens: &mut TokenStream) {
3306            outer_attrs_to_tokens(&self.attrs, tokens);
3307            self.expr.to_tokens(tokens);
3308            self.bracket_token.surround(tokens, |tokens| {
3309                self.index.to_tokens(tokens);
3310            });
3311        }
3312    }
3313
3314    #[cfg(feature = "full")]
3315    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3316    impl ToTokens for ExprInfer {
3317        fn to_tokens(&self, tokens: &mut TokenStream) {
3318            outer_attrs_to_tokens(&self.attrs, tokens);
3319            self.underscore_token.to_tokens(tokens);
3320        }
3321    }
3322
3323    #[cfg(feature = "full")]
3324    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3325    impl ToTokens for ExprLet {
3326        fn to_tokens(&self, tokens: &mut TokenStream) {
3327            outer_attrs_to_tokens(&self.attrs, tokens);
3328            self.let_token.to_tokens(tokens);
3329            self.pat.to_tokens(tokens);
3330            self.eq_token.to_tokens(tokens);
3331            wrap_bare_struct(tokens, &self.expr);
3332        }
3333    }
3334
3335    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3336    impl ToTokens for ExprLit {
3337        fn to_tokens(&self, tokens: &mut TokenStream) {
3338            outer_attrs_to_tokens(&self.attrs, tokens);
3339            self.lit.to_tokens(tokens);
3340        }
3341    }
3342
3343    #[cfg(feature = "full")]
3344    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3345    impl ToTokens for ExprLoop {
3346        fn to_tokens(&self, tokens: &mut TokenStream) {
3347            outer_attrs_to_tokens(&self.attrs, tokens);
3348            self.label.to_tokens(tokens);
3349            self.loop_token.to_tokens(tokens);
3350            self.body.brace_token.surround(tokens, |tokens| {
3351                inner_attrs_to_tokens(&self.attrs, tokens);
3352                tokens.append_all(&self.body.stmts);
3353            });
3354        }
3355    }
3356
3357    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3358    impl ToTokens for ExprMacro {
3359        fn to_tokens(&self, tokens: &mut TokenStream) {
3360            outer_attrs_to_tokens(&self.attrs, tokens);
3361            self.mac.to_tokens(tokens);
3362        }
3363    }
3364
3365    #[cfg(feature = "full")]
3366    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3367    impl ToTokens for ExprMatch {
3368        fn to_tokens(&self, tokens: &mut TokenStream) {
3369            outer_attrs_to_tokens(&self.attrs, tokens);
3370            self.match_token.to_tokens(tokens);
3371            wrap_bare_struct(tokens, &self.expr);
3372            self.brace_token.surround(tokens, |tokens| {
3373                inner_attrs_to_tokens(&self.attrs, tokens);
3374                for (i, arm) in self.arms.iter().enumerate() {
3375                    arm.to_tokens(tokens);
3376                    // Ensure that we have a comma after a non-block arm, except
3377                    // for the last one.
3378                    let is_last = i == self.arms.len() - 1;
3379                    if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() {
3380                        <Token![,]>::default().to_tokens(tokens);
3381                    }
3382                }
3383            });
3384        }
3385    }
3386
3387    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3388    impl ToTokens for ExprMethodCall {
3389        fn to_tokens(&self, tokens: &mut TokenStream) {
3390            outer_attrs_to_tokens(&self.attrs, tokens);
3391            self.receiver.to_tokens(tokens);
3392            self.dot_token.to_tokens(tokens);
3393            self.method.to_tokens(tokens);
3394            self.turbofish.to_tokens(tokens);
3395            self.paren_token.surround(tokens, |tokens| {
3396                self.args.to_tokens(tokens);
3397            });
3398        }
3399    }
3400
3401    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3402    impl ToTokens for ExprParen {
3403        fn to_tokens(&self, tokens: &mut TokenStream) {
3404            outer_attrs_to_tokens(&self.attrs, tokens);
3405            self.paren_token.surround(tokens, |tokens| {
3406                self.expr.to_tokens(tokens);
3407            });
3408        }
3409    }
3410
3411    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3412    impl ToTokens for ExprPath {
3413        fn to_tokens(&self, tokens: &mut TokenStream) {
3414            outer_attrs_to_tokens(&self.attrs, tokens);
3415            path::printing::print_path(tokens, &self.qself, &self.path);
3416        }
3417    }
3418
3419    #[cfg(feature = "full")]
3420    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3421    impl ToTokens for ExprRange {
3422        fn to_tokens(&self, tokens: &mut TokenStream) {
3423            outer_attrs_to_tokens(&self.attrs, tokens);
3424            self.start.to_tokens(tokens);
3425            self.limits.to_tokens(tokens);
3426            self.end.to_tokens(tokens);
3427        }
3428    }
3429
3430    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3431    impl ToTokens for ExprReference {
3432        fn to_tokens(&self, tokens: &mut TokenStream) {
3433            outer_attrs_to_tokens(&self.attrs, tokens);
3434            self.and_token.to_tokens(tokens);
3435            self.mutability.to_tokens(tokens);
3436            self.expr.to_tokens(tokens);
3437        }
3438    }
3439
3440    #[cfg(feature = "full")]
3441    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3442    impl ToTokens for ExprRepeat {
3443        fn to_tokens(&self, tokens: &mut TokenStream) {
3444            outer_attrs_to_tokens(&self.attrs, tokens);
3445            self.bracket_token.surround(tokens, |tokens| {
3446                self.expr.to_tokens(tokens);
3447                self.semi_token.to_tokens(tokens);
3448                self.len.to_tokens(tokens);
3449            });
3450        }
3451    }
3452
3453    #[cfg(feature = "full")]
3454    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3455    impl ToTokens for ExprReturn {
3456        fn to_tokens(&self, tokens: &mut TokenStream) {
3457            outer_attrs_to_tokens(&self.attrs, tokens);
3458            self.return_token.to_tokens(tokens);
3459            self.expr.to_tokens(tokens);
3460        }
3461    }
3462
3463    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3464    impl ToTokens for ExprStruct {
3465        fn to_tokens(&self, tokens: &mut TokenStream) {
3466            outer_attrs_to_tokens(&self.attrs, tokens);
3467            path::printing::print_path(tokens, &self.qself, &self.path);
3468            self.brace_token.surround(tokens, |tokens| {
3469                self.fields.to_tokens(tokens);
3470                if let Some(dot2_token) = &self.dot2_token {
3471                    dot2_token.to_tokens(tokens);
3472                } else if self.rest.is_some() {
3473                    Token![..](Span::call_site()).to_tokens(tokens);
3474                }
3475                self.rest.to_tokens(tokens);
3476            });
3477        }
3478    }
3479
3480    #[cfg(feature = "full")]
3481    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3482    impl ToTokens for ExprTry {
3483        fn to_tokens(&self, tokens: &mut TokenStream) {
3484            outer_attrs_to_tokens(&self.attrs, tokens);
3485            self.expr.to_tokens(tokens);
3486            self.question_token.to_tokens(tokens);
3487        }
3488    }
3489
3490    #[cfg(feature = "full")]
3491    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3492    impl ToTokens for ExprTryBlock {
3493        fn to_tokens(&self, tokens: &mut TokenStream) {
3494            outer_attrs_to_tokens(&self.attrs, tokens);
3495            self.try_token.to_tokens(tokens);
3496            self.block.to_tokens(tokens);
3497        }
3498    }
3499
3500    #[cfg(feature = "full")]
3501    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3502    impl ToTokens for ExprTuple {
3503        fn to_tokens(&self, tokens: &mut TokenStream) {
3504            outer_attrs_to_tokens(&self.attrs, tokens);
3505            self.paren_token.surround(tokens, |tokens| {
3506                self.elems.to_tokens(tokens);
3507                // If we only have one argument, we need a trailing comma to
3508                // distinguish ExprTuple from ExprParen.
3509                if self.elems.len() == 1 && !self.elems.trailing_punct() {
3510                    <Token![,]>::default().to_tokens(tokens);
3511                }
3512            });
3513        }
3514    }
3515
3516    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3517    impl ToTokens for ExprUnary {
3518        fn to_tokens(&self, tokens: &mut TokenStream) {
3519            outer_attrs_to_tokens(&self.attrs, tokens);
3520            self.op.to_tokens(tokens);
3521            self.expr.to_tokens(tokens);
3522        }
3523    }
3524
3525    #[cfg(feature = "full")]
3526    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3527    impl ToTokens for ExprUnsafe {
3528        fn to_tokens(&self, tokens: &mut TokenStream) {
3529            outer_attrs_to_tokens(&self.attrs, tokens);
3530            self.unsafe_token.to_tokens(tokens);
3531            self.block.brace_token.surround(tokens, |tokens| {
3532                inner_attrs_to_tokens(&self.attrs, tokens);
3533                tokens.append_all(&self.block.stmts);
3534            });
3535        }
3536    }
3537
3538    #[cfg(feature = "full")]
3539    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3540    impl ToTokens for ExprWhile {
3541        fn to_tokens(&self, tokens: &mut TokenStream) {
3542            outer_attrs_to_tokens(&self.attrs, tokens);
3543            self.label.to_tokens(tokens);
3544            self.while_token.to_tokens(tokens);
3545            wrap_bare_struct(tokens, &self.cond);
3546            self.body.brace_token.surround(tokens, |tokens| {
3547                inner_attrs_to_tokens(&self.attrs, tokens);
3548                tokens.append_all(&self.body.stmts);
3549            });
3550        }
3551    }
3552
3553    #[cfg(feature = "full")]
3554    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3555    impl ToTokens for ExprYield {
3556        fn to_tokens(&self, tokens: &mut TokenStream) {
3557            outer_attrs_to_tokens(&self.attrs, tokens);
3558            self.yield_token.to_tokens(tokens);
3559            self.expr.to_tokens(tokens);
3560        }
3561    }
3562
3563    #[cfg(feature = "full")]
3564    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3565    impl ToTokens for Arm {
3566        fn to_tokens(&self, tokens: &mut TokenStream) {
3567            tokens.append_all(&self.attrs);
3568            self.pat.to_tokens(tokens);
3569            if let Some((if_token, guard)) = &self.guard {
3570                if_token.to_tokens(tokens);
3571                guard.to_tokens(tokens);
3572            }
3573            self.fat_arrow_token.to_tokens(tokens);
3574            self.body.to_tokens(tokens);
3575            self.comma.to_tokens(tokens);
3576        }
3577    }
3578
3579    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3580    impl ToTokens for FieldValue {
3581        fn to_tokens(&self, tokens: &mut TokenStream) {
3582            outer_attrs_to_tokens(&self.attrs, tokens);
3583            self.member.to_tokens(tokens);
3584            if let Some(colon_token) = &self.colon_token {
3585                colon_token.to_tokens(tokens);
3586                self.expr.to_tokens(tokens);
3587            }
3588        }
3589    }
3590
3591    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3592    impl ToTokens for Index {
3593        fn to_tokens(&self, tokens: &mut TokenStream) {
3594            let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
3595            lit.set_span(self.span);
3596            tokens.append(lit);
3597        }
3598    }
3599
3600    #[cfg(feature = "full")]
3601    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3602    impl ToTokens for Label {
3603        fn to_tokens(&self, tokens: &mut TokenStream) {
3604            self.name.to_tokens(tokens);
3605            self.colon_token.to_tokens(tokens);
3606        }
3607    }
3608
3609    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3610    impl ToTokens for Member {
3611        fn to_tokens(&self, tokens: &mut TokenStream) {
3612            match self {
3613                Member::Named(ident) => ident.to_tokens(tokens),
3614                Member::Unnamed(index) => index.to_tokens(tokens),
3615            }
3616        }
3617    }
3618
3619    #[cfg(feature = "full")]
3620    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3621    impl ToTokens for RangeLimits {
3622        fn to_tokens(&self, tokens: &mut TokenStream) {
3623            match self {
3624                RangeLimits::HalfOpen(t) => t.to_tokens(tokens),
3625                RangeLimits::Closed(t) => t.to_tokens(tokens),
3626            }
3627        }
3628    }
3629}