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