syn/
expr.rs

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