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 allow_plus = false;
1375                let allow_group_generic = false;
1376                let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
1377                check_cast(input)?;
1378                lhs = Expr::Cast(ExprCast {
1379                    attrs: Vec::new(),
1380                    expr: Box::new(lhs),
1381                    as_token,
1382                    ty: Box::new(ty),
1383                });
1384            } else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) {
1385                let colon_token: Token![:] = input.parse()?;
1386                let allow_plus = false;
1387                let allow_group_generic = false;
1388                let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
1389                check_cast(input)?;
1390                lhs = Expr::Type(ExprType {
1391                    attrs: Vec::new(),
1392                    expr: Box::new(lhs),
1393                    colon_token,
1394                    ty: Box::new(ty),
1395                });
1396            } else {
1397                break;
1398            }
1399        }
1400        Ok(lhs)
1401    }
1402
1403    #[cfg(not(feature = "full"))]
1404    fn parse_expr(
1405        input: ParseStream,
1406        mut lhs: Expr,
1407        allow_struct: AllowStruct,
1408        base: Precedence,
1409    ) -> Result<Expr> {
1410        loop {
1411            if input
1412                .fork()
1413                .parse::<BinOp>()
1414                .ok()
1415                .map_or(false, |op| Precedence::of(&op) >= base)
1416            {
1417                let op: BinOp = input.parse()?;
1418                let precedence = Precedence::of(&op);
1419                let mut rhs = unary_expr(input, allow_struct)?;
1420                loop {
1421                    let next = peek_precedence(input);
1422                    if next > precedence || next == precedence && precedence == Precedence::Assign {
1423                        rhs = parse_expr(input, rhs, allow_struct, next)?;
1424                    } else {
1425                        break;
1426                    }
1427                }
1428                lhs = Expr::Binary(ExprBinary {
1429                    attrs: Vec::new(),
1430                    left: Box::new(lhs),
1431                    op,
1432                    right: Box::new(rhs),
1433                });
1434            } else if Precedence::Cast >= base && input.peek(Token![as]) {
1435                let as_token: Token![as] = input.parse()?;
1436                let allow_plus = false;
1437                let allow_group_generic = false;
1438                let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
1439                check_cast(input)?;
1440                lhs = Expr::Cast(ExprCast {
1441                    attrs: Vec::new(),
1442                    expr: Box::new(lhs),
1443                    as_token,
1444                    ty: Box::new(ty),
1445                });
1446            } else {
1447                break;
1448            }
1449        }
1450        Ok(lhs)
1451    }
1452
1453    fn peek_precedence(input: ParseStream) -> Precedence {
1454        if let Ok(op) = input.fork().parse() {
1455            Precedence::of(&op)
1456        } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
1457            Precedence::Assign
1458        } else if input.peek(Token![..]) {
1459            Precedence::Range
1460        } else if input.peek(Token![as])
1461            || cfg!(feature = "full") && input.peek(Token![:]) && !input.peek(Token![::])
1462        {
1463            Precedence::Cast
1464        } else {
1465            Precedence::Any
1466        }
1467    }
1468
1469    // Parse an arbitrary expression.
1470    fn ambiguous_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1471        let lhs = unary_expr(input, allow_struct)?;
1472        parse_expr(input, lhs, allow_struct, Precedence::Any)
1473    }
1474
1475    #[cfg(feature = "full")]
1476    fn expr_attrs(input: ParseStream) -> Result<Vec<Attribute>> {
1477        let mut attrs = Vec::new();
1478        loop {
1479            if input.peek(token::Group) {
1480                let ahead = input.fork();
1481                let group = crate::group::parse_group(&ahead)?;
1482                if !group.content.peek(Token![#]) || group.content.peek2(Token![!]) {
1483                    break;
1484                }
1485                let attr = group.content.call(attr::parsing::single_parse_outer)?;
1486                if !group.content.is_empty() {
1487                    break;
1488                }
1489                attrs.push(attr);
1490            } else if input.peek(Token![#]) {
1491                attrs.push(input.call(attr::parsing::single_parse_outer)?);
1492            } else {
1493                break;
1494            }
1495        }
1496        Ok(attrs)
1497    }
1498
1499    // <UnOp> <trailer>
1500    // & <trailer>
1501    // &mut <trailer>
1502    // box <trailer>
1503    #[cfg(feature = "full")]
1504    fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1505        let begin = input.fork();
1506        let attrs = input.call(expr_attrs)?;
1507        if input.peek(Token![&]) {
1508            let and_token: Token![&] = input.parse()?;
1509            let raw: Option<raw> =
1510                if input.peek(raw) && (input.peek2(Token![mut]) || input.peek2(Token![const])) {
1511                    Some(input.parse()?)
1512                } else {
1513                    None
1514                };
1515            let mutability: Option<Token![mut]> = input.parse()?;
1516            if raw.is_some() && mutability.is_none() {
1517                input.parse::<Token![const]>()?;
1518            }
1519            let expr = Box::new(unary_expr(input, allow_struct)?);
1520            if raw.is_some() {
1521                Ok(Expr::Verbatim(verbatim::between(begin, input)))
1522            } else {
1523                Ok(Expr::Reference(ExprReference {
1524                    attrs,
1525                    and_token,
1526                    raw: Reserved::default(),
1527                    mutability,
1528                    expr,
1529                }))
1530            }
1531        } else if input.peek(Token![box]) {
1532            expr_box(input, attrs, allow_struct).map(Expr::Box)
1533        } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
1534            expr_unary(input, attrs, allow_struct).map(Expr::Unary)
1535        } else {
1536            trailer_expr(begin, attrs, input, allow_struct)
1537        }
1538    }
1539
1540    #[cfg(not(feature = "full"))]
1541    fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1542        if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
1543            Ok(Expr::Unary(ExprUnary {
1544                attrs: Vec::new(),
1545                op: input.parse()?,
1546                expr: Box::new(unary_expr(input, allow_struct)?),
1547            }))
1548        } else {
1549            trailer_expr(input, allow_struct)
1550        }
1551    }
1552
1553    // <atom> (..<args>) ...
1554    // <atom> . <ident> (..<args>) ...
1555    // <atom> . <ident> ...
1556    // <atom> . <lit> ...
1557    // <atom> [ <expr> ] ...
1558    // <atom> ? ...
1559    #[cfg(feature = "full")]
1560    fn trailer_expr(
1561        begin: ParseBuffer,
1562        mut attrs: Vec<Attribute>,
1563        input: ParseStream,
1564        allow_struct: AllowStruct,
1565    ) -> Result<Expr> {
1566        let atom = atom_expr(input, allow_struct)?;
1567        let mut e = trailer_helper(input, atom)?;
1568
1569        if let Expr::Verbatim(tokens) = &mut e {
1570            *tokens = verbatim::between(begin, input);
1571        } else {
1572            let inner_attrs = e.replace_attrs(Vec::new());
1573            attrs.extend(inner_attrs);
1574            e.replace_attrs(attrs);
1575        }
1576
1577        Ok(e)
1578    }
1579
1580    #[cfg(feature = "full")]
1581    fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
1582        loop {
1583            if input.peek(token::Paren) {
1584                let content;
1585                e = Expr::Call(ExprCall {
1586                    attrs: Vec::new(),
1587                    func: Box::new(e),
1588                    paren_token: parenthesized!(content in input),
1589                    args: content.parse_terminated(Expr::parse)?,
1590                });
1591            } else if input.peek(Token![.])
1592                && !input.peek(Token![..])
1593                && match e {
1594                    Expr::Range(_) => false,
1595                    _ => true,
1596                }
1597            {
1598                let mut dot_token: Token![.] = input.parse()?;
1599
1600                let await_token: Option<token::Await> = input.parse()?;
1601                if let Some(await_token) = await_token {
1602                    e = Expr::Await(ExprAwait {
1603                        attrs: Vec::new(),
1604                        base: Box::new(e),
1605                        dot_token,
1606                        await_token,
1607                    });
1608                    continue;
1609                }
1610
1611                let float_token: Option<LitFloat> = input.parse()?;
1612                if let Some(float_token) = float_token {
1613                    if multi_index(&mut e, &mut dot_token, float_token)? {
1614                        continue;
1615                    }
1616                }
1617
1618                let member: Member = input.parse()?;
1619                let turbofish = if member.is_named() && input.peek(Token![::]) {
1620                    Some(input.parse::<MethodTurbofish>()?)
1621                } else {
1622                    None
1623                };
1624
1625                if turbofish.is_some() || input.peek(token::Paren) {
1626                    if let Member::Named(method) = member {
1627                        let content;
1628                        e = Expr::MethodCall(ExprMethodCall {
1629                            attrs: Vec::new(),
1630                            receiver: Box::new(e),
1631                            dot_token,
1632                            method,
1633                            turbofish,
1634                            paren_token: parenthesized!(content in input),
1635                            args: content.parse_terminated(Expr::parse)?,
1636                        });
1637                        continue;
1638                    }
1639                }
1640
1641                e = Expr::Field(ExprField {
1642                    attrs: Vec::new(),
1643                    base: Box::new(e),
1644                    dot_token,
1645                    member,
1646                });
1647            } else if input.peek(token::Bracket) {
1648                let content;
1649                e = Expr::Index(ExprIndex {
1650                    attrs: Vec::new(),
1651                    expr: Box::new(e),
1652                    bracket_token: bracketed!(content in input),
1653                    index: content.parse()?,
1654                });
1655            } else if input.peek(Token![?]) {
1656                e = Expr::Try(ExprTry {
1657                    attrs: Vec::new(),
1658                    expr: Box::new(e),
1659                    question_token: input.parse()?,
1660                });
1661            } else {
1662                break;
1663            }
1664        }
1665        Ok(e)
1666    }
1667
1668    #[cfg(not(feature = "full"))]
1669    fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1670        let mut e = atom_expr(input, allow_struct)?;
1671
1672        loop {
1673            if input.peek(token::Paren) {
1674                let content;
1675                e = Expr::Call(ExprCall {
1676                    attrs: Vec::new(),
1677                    func: Box::new(e),
1678                    paren_token: parenthesized!(content in input),
1679                    args: content.parse_terminated(Expr::parse)?,
1680                });
1681            } else if input.peek(Token![.]) && !input.peek(Token![..]) && !input.peek2(token::Await)
1682            {
1683                let mut dot_token: Token![.] = input.parse()?;
1684                let float_token: Option<LitFloat> = input.parse()?;
1685                if let Some(float_token) = float_token {
1686                    if multi_index(&mut e, &mut dot_token, float_token)? {
1687                        continue;
1688                    }
1689                }
1690                e = Expr::Field(ExprField {
1691                    attrs: Vec::new(),
1692                    base: Box::new(e),
1693                    dot_token,
1694                    member: input.parse()?,
1695                });
1696            } else if input.peek(token::Bracket) {
1697                let content;
1698                e = Expr::Index(ExprIndex {
1699                    attrs: Vec::new(),
1700                    expr: Box::new(e),
1701                    bracket_token: bracketed!(content in input),
1702                    index: content.parse()?,
1703                });
1704            } else {
1705                break;
1706            }
1707        }
1708
1709        Ok(e)
1710    }
1711
1712    // Parse all atomic expressions which don't have to worry about precedence
1713    // interactions, as they are fully contained.
1714    #[cfg(feature = "full")]
1715    fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1716        if input.peek(token::Group)
1717            && !input.peek2(Token![::])
1718            && !input.peek2(Token![!])
1719            && !input.peek2(token::Brace)
1720        {
1721            input.call(expr_group).map(Expr::Group)
1722        } else if input.peek(Lit) {
1723            input.parse().map(Expr::Lit)
1724        } else if input.peek(Token![async])
1725            && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
1726        {
1727            input.parse().map(Expr::Async)
1728        } else if input.peek(Token![try]) && input.peek2(token::Brace) {
1729            input.parse().map(Expr::TryBlock)
1730        } else if input.peek(Token![|])
1731            || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1732            || input.peek(Token![static])
1733            || input.peek(Token![move])
1734        {
1735            expr_closure(input, allow_struct).map(Expr::Closure)
1736        } else if input.peek(Token![for])
1737            && input.peek2(Token![<])
1738            && (input.peek3(Lifetime) || input.peek3(Token![>]))
1739        {
1740            let begin = input.fork();
1741            input.parse::<BoundLifetimes>()?;
1742            expr_closure(input, allow_struct)?;
1743            let verbatim = verbatim::between(begin, input);
1744            Ok(Expr::Verbatim(verbatim))
1745        } else if input.peek(Ident)
1746            || input.peek(Token![::])
1747            || input.peek(Token![<])
1748            || input.peek(Token![self])
1749            || input.peek(Token![Self])
1750            || input.peek(Token![super])
1751            || input.peek(Token![crate])
1752        {
1753            path_or_macro_or_struct(input, allow_struct)
1754        } else if input.peek(token::Paren) {
1755            paren_or_tuple(input)
1756        } else if input.peek(Token![break]) {
1757            expr_break(input, allow_struct).map(Expr::Break)
1758        } else if input.peek(Token![continue]) {
1759            input.parse().map(Expr::Continue)
1760        } else if input.peek(Token![return]) {
1761            expr_ret(input, allow_struct).map(Expr::Return)
1762        } else if input.peek(token::Bracket) {
1763            array_or_repeat(input)
1764        } else if input.peek(Token![let]) {
1765            input.parse().map(Expr::Let)
1766        } else if input.peek(Token![if]) {
1767            input.parse().map(Expr::If)
1768        } else if input.peek(Token![while]) {
1769            input.parse().map(Expr::While)
1770        } else if input.peek(Token![for]) {
1771            input.parse().map(Expr::ForLoop)
1772        } else if input.peek(Token![loop]) {
1773            input.parse().map(Expr::Loop)
1774        } else if input.peek(Token![match]) {
1775            input.parse().map(Expr::Match)
1776        } else if input.peek(Token![yield]) {
1777            input.parse().map(Expr::Yield)
1778        } else if input.peek(Token![unsafe]) {
1779            input.parse().map(Expr::Unsafe)
1780        } else if input.peek(Token![const]) {
1781            input.call(expr_const).map(Expr::Verbatim)
1782        } else if input.peek(token::Brace) {
1783            input.parse().map(Expr::Block)
1784        } else if input.peek(Token![..]) {
1785            expr_range(input, allow_struct).map(Expr::Range)
1786        } else if input.peek(Token![_]) {
1787            Ok(Expr::Verbatim(TokenStream::from(
1788                input.parse::<TokenTree>()?,
1789            )))
1790        } else if input.peek(Lifetime) {
1791            let the_label: Label = input.parse()?;
1792            let mut expr = if input.peek(Token![while]) {
1793                Expr::While(input.parse()?)
1794            } else if input.peek(Token![for]) {
1795                Expr::ForLoop(input.parse()?)
1796            } else if input.peek(Token![loop]) {
1797                Expr::Loop(input.parse()?)
1798            } else if input.peek(token::Brace) {
1799                Expr::Block(input.parse()?)
1800            } else {
1801                return Err(input.error("expected loop or block expression"));
1802            };
1803            match &mut expr {
1804                Expr::While(ExprWhile { label, .. })
1805                | Expr::ForLoop(ExprForLoop { label, .. })
1806                | Expr::Loop(ExprLoop { label, .. })
1807                | Expr::Block(ExprBlock { label, .. }) => *label = Some(the_label),
1808                _ => unreachable!(),
1809            }
1810            Ok(expr)
1811        } else {
1812            Err(input.error("expected expression"))
1813        }
1814    }
1815
1816    #[cfg(not(feature = "full"))]
1817    fn atom_expr(input: ParseStream, _allow_struct: AllowStruct) -> Result<Expr> {
1818        if input.peek(Lit) {
1819            input.parse().map(Expr::Lit)
1820        } else if input.peek(token::Paren) {
1821            input.call(expr_paren).map(Expr::Paren)
1822        } else if input.peek(Ident)
1823            || input.peek(Token![::])
1824            || input.peek(Token![<])
1825            || input.peek(Token![self])
1826            || input.peek(Token![Self])
1827            || input.peek(Token![super])
1828            || input.peek(Token![crate])
1829        {
1830            input.parse().map(Expr::Path)
1831        } else {
1832            Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
1833        }
1834    }
1835
1836    #[cfg(feature = "full")]
1837    fn path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1838        let begin = input.fork();
1839        let expr: ExprPath = input.parse()?;
1840
1841        if expr.qself.is_none() && input.peek(Token![!]) && !input.peek(Token![!=]) {
1842            let mut contains_arguments = false;
1843            for segment in &expr.path.segments {
1844                match segment.arguments {
1845                    PathArguments::None => {}
1846                    PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
1847                        contains_arguments = true;
1848                    }
1849                }
1850            }
1851
1852            if !contains_arguments {
1853                let bang_token: Token![!] = input.parse()?;
1854                let (delimiter, tokens) = mac::parse_delimiter(input)?;
1855                return Ok(Expr::Macro(ExprMacro {
1856                    attrs: Vec::new(),
1857                    mac: Macro {
1858                        path: expr.path,
1859                        bang_token,
1860                        delimiter,
1861                        tokens,
1862                    },
1863                }));
1864            }
1865        }
1866
1867        if allow_struct.0 && input.peek(token::Brace) {
1868            let expr_struct = expr_struct_helper(input, expr.path)?;
1869            if expr.qself.is_some() {
1870                Ok(Expr::Verbatim(verbatim::between(begin, input)))
1871            } else {
1872                Ok(Expr::Struct(expr_struct))
1873            }
1874        } else {
1875            Ok(Expr::Path(expr))
1876        }
1877    }
1878
1879    #[cfg(feature = "full")]
1880    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
1881    impl Parse for ExprMacro {
1882        fn parse(input: ParseStream) -> Result<Self> {
1883            Ok(ExprMacro {
1884                attrs: Vec::new(),
1885                mac: input.parse()?,
1886            })
1887        }
1888    }
1889
1890    #[cfg(feature = "full")]
1891    fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
1892        let content;
1893        let paren_token = parenthesized!(content in input);
1894        if content.is_empty() {
1895            return Ok(Expr::Tuple(ExprTuple {
1896                attrs: Vec::new(),
1897                paren_token,
1898                elems: Punctuated::new(),
1899            }));
1900        }
1901
1902        let first: Expr = content.parse()?;
1903        if content.is_empty() {
1904            return Ok(Expr::Paren(ExprParen {
1905                attrs: Vec::new(),
1906                paren_token,
1907                expr: Box::new(first),
1908            }));
1909        }
1910
1911        let mut elems = Punctuated::new();
1912        elems.push_value(first);
1913        while !content.is_empty() {
1914            let punct = content.parse()?;
1915            elems.push_punct(punct);
1916            if content.is_empty() {
1917                break;
1918            }
1919            let value = content.parse()?;
1920            elems.push_value(value);
1921        }
1922        Ok(Expr::Tuple(ExprTuple {
1923            attrs: Vec::new(),
1924            paren_token,
1925            elems,
1926        }))
1927    }
1928
1929    #[cfg(feature = "full")]
1930    fn array_or_repeat(input: ParseStream) -> Result<Expr> {
1931        let content;
1932        let bracket_token = bracketed!(content in input);
1933        if content.is_empty() {
1934            return Ok(Expr::Array(ExprArray {
1935                attrs: Vec::new(),
1936                bracket_token,
1937                elems: Punctuated::new(),
1938            }));
1939        }
1940
1941        let first: Expr = content.parse()?;
1942        if content.is_empty() || content.peek(Token![,]) {
1943            let mut elems = Punctuated::new();
1944            elems.push_value(first);
1945            while !content.is_empty() {
1946                let punct = content.parse()?;
1947                elems.push_punct(punct);
1948                if content.is_empty() {
1949                    break;
1950                }
1951                let value = content.parse()?;
1952                elems.push_value(value);
1953            }
1954            Ok(Expr::Array(ExprArray {
1955                attrs: Vec::new(),
1956                bracket_token,
1957                elems,
1958            }))
1959        } else if content.peek(Token![;]) {
1960            let semi_token: Token![;] = content.parse()?;
1961            let len: Expr = content.parse()?;
1962            Ok(Expr::Repeat(ExprRepeat {
1963                attrs: Vec::new(),
1964                bracket_token,
1965                expr: Box::new(first),
1966                semi_token,
1967                len: Box::new(len),
1968            }))
1969        } else {
1970            Err(content.error("expected `,` or `;`"))
1971        }
1972    }
1973
1974    #[cfg(feature = "full")]
1975    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
1976    impl Parse for ExprArray {
1977        fn parse(input: ParseStream) -> Result<Self> {
1978            let content;
1979            let bracket_token = bracketed!(content in input);
1980            let mut elems = Punctuated::new();
1981
1982            while !content.is_empty() {
1983                let first: Expr = content.parse()?;
1984                elems.push_value(first);
1985                if content.is_empty() {
1986                    break;
1987                }
1988                let punct = content.parse()?;
1989                elems.push_punct(punct);
1990            }
1991
1992            Ok(ExprArray {
1993                attrs: Vec::new(),
1994                bracket_token,
1995                elems,
1996            })
1997        }
1998    }
1999
2000    #[cfg(feature = "full")]
2001    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2002    impl Parse for ExprRepeat {
2003        fn parse(input: ParseStream) -> Result<Self> {
2004            let content;
2005            Ok(ExprRepeat {
2006                bracket_token: bracketed!(content in input),
2007                attrs: Vec::new(),
2008                expr: content.parse()?,
2009                semi_token: content.parse()?,
2010                len: content.parse()?,
2011            })
2012        }
2013    }
2014
2015    #[cfg(feature = "full")]
2016    pub(crate) fn expr_early(input: ParseStream) -> Result<Expr> {
2017        let mut attrs = input.call(expr_attrs)?;
2018        let mut expr = if input.peek(Token![if]) {
2019            Expr::If(input.parse()?)
2020        } else if input.peek(Token![while]) {
2021            Expr::While(input.parse()?)
2022        } else if input.peek(Token![for])
2023            && !(input.peek2(Token![<]) && (input.peek3(Lifetime) || input.peek3(Token![>])))
2024        {
2025            Expr::ForLoop(input.parse()?)
2026        } else if input.peek(Token![loop]) {
2027            Expr::Loop(input.parse()?)
2028        } else if input.peek(Token![match]) {
2029            Expr::Match(input.parse()?)
2030        } else if input.peek(Token![try]) && input.peek2(token::Brace) {
2031            Expr::TryBlock(input.parse()?)
2032        } else if input.peek(Token![unsafe]) {
2033            Expr::Unsafe(input.parse()?)
2034        } else if input.peek(Token![const]) {
2035            Expr::Verbatim(input.call(expr_const)?)
2036        } else if input.peek(token::Brace) {
2037            Expr::Block(input.parse()?)
2038        } else {
2039            let allow_struct = AllowStruct(true);
2040            let mut expr = unary_expr(input, allow_struct)?;
2041
2042            attrs.extend(expr.replace_attrs(Vec::new()));
2043            expr.replace_attrs(attrs);
2044
2045            return parse_expr(input, expr, allow_struct, Precedence::Any);
2046        };
2047
2048        if input.peek(Token![.]) && !input.peek(Token![..]) || input.peek(Token![?]) {
2049            expr = trailer_helper(input, expr)?;
2050
2051            attrs.extend(expr.replace_attrs(Vec::new()));
2052            expr.replace_attrs(attrs);
2053
2054            let allow_struct = AllowStruct(true);
2055            return parse_expr(input, expr, allow_struct, Precedence::Any);
2056        }
2057
2058        attrs.extend(expr.replace_attrs(Vec::new()));
2059        expr.replace_attrs(attrs);
2060        Ok(expr)
2061    }
2062
2063    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2064    impl Parse for ExprLit {
2065        fn parse(input: ParseStream) -> Result<Self> {
2066            Ok(ExprLit {
2067                attrs: Vec::new(),
2068                lit: input.parse()?,
2069            })
2070        }
2071    }
2072
2073    #[cfg(feature = "full")]
2074    fn expr_group(input: ParseStream) -> Result<ExprGroup> {
2075        let group = crate::group::parse_group(input)?;
2076        Ok(ExprGroup {
2077            attrs: Vec::new(),
2078            group_token: group.token,
2079            expr: group.content.parse()?,
2080        })
2081    }
2082
2083    #[cfg(feature = "full")]
2084    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2085    impl Parse for ExprParen {
2086        fn parse(input: ParseStream) -> Result<Self> {
2087            expr_paren(input)
2088        }
2089    }
2090
2091    fn expr_paren(input: ParseStream) -> Result<ExprParen> {
2092        let content;
2093        Ok(ExprParen {
2094            attrs: Vec::new(),
2095            paren_token: parenthesized!(content in input),
2096            expr: content.parse()?,
2097        })
2098    }
2099
2100    #[cfg(feature = "full")]
2101    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2102    impl Parse for GenericMethodArgument {
2103        fn parse(input: ParseStream) -> Result<Self> {
2104            if input.peek(Lit) {
2105                let lit = input.parse()?;
2106                return Ok(GenericMethodArgument::Const(Expr::Lit(lit)));
2107            }
2108
2109            if input.peek(token::Brace) {
2110                let block: ExprBlock = input.parse()?;
2111                return Ok(GenericMethodArgument::Const(Expr::Block(block)));
2112            }
2113
2114            input.parse().map(GenericMethodArgument::Type)
2115        }
2116    }
2117
2118    #[cfg(feature = "full")]
2119    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2120    impl Parse for MethodTurbofish {
2121        fn parse(input: ParseStream) -> Result<Self> {
2122            Ok(MethodTurbofish {
2123                colon2_token: input.parse()?,
2124                lt_token: input.parse()?,
2125                args: {
2126                    let mut args = Punctuated::new();
2127                    loop {
2128                        if input.peek(Token![>]) {
2129                            break;
2130                        }
2131                        let value: GenericMethodArgument = input.parse()?;
2132                        args.push_value(value);
2133                        if input.peek(Token![>]) {
2134                            break;
2135                        }
2136                        let punct = input.parse()?;
2137                        args.push_punct(punct);
2138                    }
2139                    args
2140                },
2141                gt_token: input.parse()?,
2142            })
2143        }
2144    }
2145
2146    #[cfg(feature = "full")]
2147    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2148    impl Parse for ExprLet {
2149        fn parse(input: ParseStream) -> Result<Self> {
2150            Ok(ExprLet {
2151                attrs: Vec::new(),
2152                let_token: input.parse()?,
2153                pat: pat::parsing::multi_pat_with_leading_vert(input)?,
2154                eq_token: input.parse()?,
2155                expr: Box::new({
2156                    let allow_struct = AllowStruct(false);
2157                    let lhs = unary_expr(input, allow_struct)?;
2158                    parse_expr(input, lhs, allow_struct, Precedence::Compare)?
2159                }),
2160            })
2161        }
2162    }
2163
2164    #[cfg(feature = "full")]
2165    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2166    impl Parse for ExprIf {
2167        fn parse(input: ParseStream) -> Result<Self> {
2168            let attrs = input.call(Attribute::parse_outer)?;
2169            Ok(ExprIf {
2170                attrs,
2171                if_token: input.parse()?,
2172                cond: Box::new(input.call(Expr::parse_without_eager_brace)?),
2173                then_branch: input.parse()?,
2174                else_branch: {
2175                    if input.peek(Token![else]) {
2176                        Some(input.call(else_block)?)
2177                    } else {
2178                        None
2179                    }
2180                },
2181            })
2182        }
2183    }
2184
2185    #[cfg(feature = "full")]
2186    fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
2187        let else_token: Token![else] = input.parse()?;
2188
2189        let lookahead = input.lookahead1();
2190        let else_branch = if input.peek(Token![if]) {
2191            input.parse().map(Expr::If)?
2192        } else if input.peek(token::Brace) {
2193            Expr::Block(ExprBlock {
2194                attrs: Vec::new(),
2195                label: None,
2196                block: input.parse()?,
2197            })
2198        } else {
2199            return Err(lookahead.error());
2200        };
2201
2202        Ok((else_token, Box::new(else_branch)))
2203    }
2204
2205    #[cfg(feature = "full")]
2206    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2207    impl Parse for ExprForLoop {
2208        fn parse(input: ParseStream) -> Result<Self> {
2209            let mut attrs = input.call(Attribute::parse_outer)?;
2210            let label: Option<Label> = input.parse()?;
2211            let for_token: Token![for] = input.parse()?;
2212
2213            let pat = pat::parsing::multi_pat_with_leading_vert(input)?;
2214
2215            let in_token: Token![in] = input.parse()?;
2216            let expr: Expr = input.call(Expr::parse_without_eager_brace)?;
2217
2218            let content;
2219            let brace_token = braced!(content in input);
2220            attr::parsing::parse_inner(&content, &mut attrs)?;
2221            let stmts = content.call(Block::parse_within)?;
2222
2223            Ok(ExprForLoop {
2224                attrs,
2225                label,
2226                for_token,
2227                pat,
2228                in_token,
2229                expr: Box::new(expr),
2230                body: Block { brace_token, stmts },
2231            })
2232        }
2233    }
2234
2235    #[cfg(feature = "full")]
2236    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2237    impl Parse for ExprLoop {
2238        fn parse(input: ParseStream) -> Result<Self> {
2239            let mut attrs = input.call(Attribute::parse_outer)?;
2240            let label: Option<Label> = input.parse()?;
2241            let loop_token: Token![loop] = input.parse()?;
2242
2243            let content;
2244            let brace_token = braced!(content in input);
2245            attr::parsing::parse_inner(&content, &mut attrs)?;
2246            let stmts = content.call(Block::parse_within)?;
2247
2248            Ok(ExprLoop {
2249                attrs,
2250                label,
2251                loop_token,
2252                body: Block { brace_token, stmts },
2253            })
2254        }
2255    }
2256
2257    #[cfg(feature = "full")]
2258    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2259    impl Parse for ExprMatch {
2260        fn parse(input: ParseStream) -> Result<Self> {
2261            let mut attrs = input.call(Attribute::parse_outer)?;
2262            let match_token: Token![match] = input.parse()?;
2263            let expr = Expr::parse_without_eager_brace(input)?;
2264
2265            let content;
2266            let brace_token = braced!(content in input);
2267            attr::parsing::parse_inner(&content, &mut attrs)?;
2268
2269            let mut arms = Vec::new();
2270            while !content.is_empty() {
2271                arms.push(content.call(Arm::parse)?);
2272            }
2273
2274            Ok(ExprMatch {
2275                attrs,
2276                match_token,
2277                expr: Box::new(expr),
2278                brace_token,
2279                arms,
2280            })
2281        }
2282    }
2283
2284    macro_rules! impl_by_parsing_expr {
2285        (
2286            $(
2287                $expr_type:ty, $variant:ident, $msg:expr,
2288            )*
2289        ) => {
2290            $(
2291                #[cfg(all(feature = "full", feature = "printing"))]
2292                #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2293                impl Parse for $expr_type {
2294                    fn parse(input: ParseStream) -> Result<Self> {
2295                        let mut expr: Expr = input.parse()?;
2296                        loop {
2297                            match expr {
2298                                Expr::$variant(inner) => return Ok(inner),
2299                                Expr::Group(next) => expr = *next.expr,
2300                                _ => return Err(Error::new_spanned(expr, $msg)),
2301                            }
2302                        }
2303                    }
2304                }
2305            )*
2306        };
2307    }
2308
2309    impl_by_parsing_expr! {
2310        ExprAssign, Assign, "expected assignment expression",
2311        ExprAssignOp, AssignOp, "expected compound assignment expression",
2312        ExprAwait, Await, "expected await expression",
2313        ExprBinary, Binary, "expected binary operation",
2314        ExprCall, Call, "expected function call expression",
2315        ExprCast, Cast, "expected cast expression",
2316        ExprField, Field, "expected struct field access",
2317        ExprIndex, Index, "expected indexing expression",
2318        ExprMethodCall, MethodCall, "expected method call expression",
2319        ExprRange, Range, "expected range expression",
2320        ExprTry, Try, "expected try expression",
2321        ExprTuple, Tuple, "expected tuple expression",
2322        ExprType, Type, "expected type ascription expression",
2323    }
2324
2325    #[cfg(feature = "full")]
2326    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2327    impl Parse for ExprBox {
2328        fn parse(input: ParseStream) -> Result<Self> {
2329            let attrs = Vec::new();
2330            let allow_struct = AllowStruct(true);
2331            expr_box(input, attrs, allow_struct)
2332        }
2333    }
2334
2335    #[cfg(feature = "full")]
2336    fn expr_box(
2337        input: ParseStream,
2338        attrs: Vec<Attribute>,
2339        allow_struct: AllowStruct,
2340    ) -> Result<ExprBox> {
2341        Ok(ExprBox {
2342            attrs,
2343            box_token: input.parse()?,
2344            expr: Box::new(unary_expr(input, allow_struct)?),
2345        })
2346    }
2347
2348    #[cfg(feature = "full")]
2349    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2350    impl Parse for ExprUnary {
2351        fn parse(input: ParseStream) -> Result<Self> {
2352            let attrs = Vec::new();
2353            let allow_struct = AllowStruct(true);
2354            expr_unary(input, attrs, allow_struct)
2355        }
2356    }
2357
2358    #[cfg(feature = "full")]
2359    fn expr_unary(
2360        input: ParseStream,
2361        attrs: Vec<Attribute>,
2362        allow_struct: AllowStruct,
2363    ) -> Result<ExprUnary> {
2364        Ok(ExprUnary {
2365            attrs,
2366            op: input.parse()?,
2367            expr: Box::new(unary_expr(input, allow_struct)?),
2368        })
2369    }
2370
2371    #[cfg(feature = "full")]
2372    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2373    impl Parse for ExprClosure {
2374        fn parse(input: ParseStream) -> Result<Self> {
2375            let allow_struct = AllowStruct(true);
2376            expr_closure(input, allow_struct)
2377        }
2378    }
2379
2380    #[cfg(feature = "full")]
2381    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2382    impl Parse for ExprReference {
2383        fn parse(input: ParseStream) -> Result<Self> {
2384            let allow_struct = AllowStruct(true);
2385            Ok(ExprReference {
2386                attrs: Vec::new(),
2387                and_token: input.parse()?,
2388                raw: Reserved::default(),
2389                mutability: input.parse()?,
2390                expr: Box::new(unary_expr(input, allow_struct)?),
2391            })
2392        }
2393    }
2394
2395    #[cfg(feature = "full")]
2396    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2397    impl Parse for ExprBreak {
2398        fn parse(input: ParseStream) -> Result<Self> {
2399            let allow_struct = AllowStruct(true);
2400            expr_break(input, allow_struct)
2401        }
2402    }
2403
2404    #[cfg(feature = "full")]
2405    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2406    impl Parse for ExprReturn {
2407        fn parse(input: ParseStream) -> Result<Self> {
2408            let allow_struct = AllowStruct(true);
2409            expr_ret(input, allow_struct)
2410        }
2411    }
2412
2413    #[cfg(feature = "full")]
2414    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2415    impl Parse for ExprTryBlock {
2416        fn parse(input: ParseStream) -> Result<Self> {
2417            Ok(ExprTryBlock {
2418                attrs: Vec::new(),
2419                try_token: input.parse()?,
2420                block: input.parse()?,
2421            })
2422        }
2423    }
2424
2425    #[cfg(feature = "full")]
2426    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2427    impl Parse for ExprYield {
2428        fn parse(input: ParseStream) -> Result<Self> {
2429            Ok(ExprYield {
2430                attrs: Vec::new(),
2431                yield_token: input.parse()?,
2432                expr: {
2433                    if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
2434                        Some(input.parse()?)
2435                    } else {
2436                        None
2437                    }
2438                },
2439            })
2440        }
2441    }
2442
2443    #[cfg(feature = "full")]
2444    fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
2445        let movability: Option<Token![static]> = input.parse()?;
2446        let asyncness: Option<Token![async]> = input.parse()?;
2447        let capture: Option<Token![move]> = input.parse()?;
2448        let or1_token: Token![|] = input.parse()?;
2449
2450        let mut inputs = Punctuated::new();
2451        loop {
2452            if input.peek(Token![|]) {
2453                break;
2454            }
2455            let value = closure_arg(input)?;
2456            inputs.push_value(value);
2457            if input.peek(Token![|]) {
2458                break;
2459            }
2460            let punct: Token![,] = input.parse()?;
2461            inputs.push_punct(punct);
2462        }
2463
2464        let or2_token: Token![|] = input.parse()?;
2465
2466        let (output, body) = if input.peek(Token![->]) {
2467            let arrow_token: Token![->] = input.parse()?;
2468            let ty: Type = input.parse()?;
2469            let body: Block = input.parse()?;
2470            let output = ReturnType::Type(arrow_token, Box::new(ty));
2471            let block = Expr::Block(ExprBlock {
2472                attrs: Vec::new(),
2473                label: None,
2474                block: body,
2475            });
2476            (output, block)
2477        } else {
2478            let body = ambiguous_expr(input, allow_struct)?;
2479            (ReturnType::Default, body)
2480        };
2481
2482        Ok(ExprClosure {
2483            attrs: Vec::new(),
2484            movability,
2485            asyncness,
2486            capture,
2487            or1_token,
2488            inputs,
2489            or2_token,
2490            output,
2491            body: Box::new(body),
2492        })
2493    }
2494
2495    #[cfg(feature = "full")]
2496    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2497    impl Parse for ExprAsync {
2498        fn parse(input: ParseStream) -> Result<Self> {
2499            Ok(ExprAsync {
2500                attrs: Vec::new(),
2501                async_token: input.parse()?,
2502                capture: input.parse()?,
2503                block: input.parse()?,
2504            })
2505        }
2506    }
2507
2508    #[cfg(feature = "full")]
2509    fn closure_arg(input: ParseStream) -> Result<Pat> {
2510        let attrs = input.call(Attribute::parse_outer)?;
2511        let mut pat: Pat = input.parse()?;
2512
2513        if input.peek(Token![:]) {
2514            Ok(Pat::Type(PatType {
2515                attrs,
2516                pat: Box::new(pat),
2517                colon_token: input.parse()?,
2518                ty: input.parse()?,
2519            }))
2520        } else {
2521            match &mut pat {
2522                Pat::Box(pat) => pat.attrs = attrs,
2523                Pat::Ident(pat) => pat.attrs = attrs,
2524                Pat::Lit(pat) => pat.attrs = attrs,
2525                Pat::Macro(pat) => pat.attrs = attrs,
2526                Pat::Or(pat) => pat.attrs = attrs,
2527                Pat::Path(pat) => pat.attrs = attrs,
2528                Pat::Range(pat) => pat.attrs = attrs,
2529                Pat::Reference(pat) => pat.attrs = attrs,
2530                Pat::Rest(pat) => pat.attrs = attrs,
2531                Pat::Slice(pat) => pat.attrs = attrs,
2532                Pat::Struct(pat) => pat.attrs = attrs,
2533                Pat::Tuple(pat) => pat.attrs = attrs,
2534                Pat::TupleStruct(pat) => pat.attrs = attrs,
2535                Pat::Type(_) => unreachable!(),
2536                Pat::Verbatim(_) => {}
2537                Pat::Wild(pat) => pat.attrs = attrs,
2538
2539                #[cfg(syn_no_non_exhaustive)]
2540                _ => unreachable!(),
2541            }
2542            Ok(pat)
2543        }
2544    }
2545
2546    #[cfg(feature = "full")]
2547    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2548    impl Parse for ExprWhile {
2549        fn parse(input: ParseStream) -> Result<Self> {
2550            let mut attrs = input.call(Attribute::parse_outer)?;
2551            let label: Option<Label> = input.parse()?;
2552            let while_token: Token![while] = input.parse()?;
2553            let cond = Expr::parse_without_eager_brace(input)?;
2554
2555            let content;
2556            let brace_token = braced!(content in input);
2557            attr::parsing::parse_inner(&content, &mut attrs)?;
2558            let stmts = content.call(Block::parse_within)?;
2559
2560            Ok(ExprWhile {
2561                attrs,
2562                label,
2563                while_token,
2564                cond: Box::new(cond),
2565                body: Block { brace_token, stmts },
2566            })
2567        }
2568    }
2569
2570    #[cfg(feature = "full")]
2571    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2572    impl Parse for Label {
2573        fn parse(input: ParseStream) -> Result<Self> {
2574            Ok(Label {
2575                name: input.parse()?,
2576                colon_token: input.parse()?,
2577            })
2578        }
2579    }
2580
2581    #[cfg(feature = "full")]
2582    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2583    impl Parse for Option<Label> {
2584        fn parse(input: ParseStream) -> Result<Self> {
2585            if input.peek(Lifetime) {
2586                input.parse().map(Some)
2587            } else {
2588                Ok(None)
2589            }
2590        }
2591    }
2592
2593    #[cfg(feature = "full")]
2594    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2595    impl Parse for ExprContinue {
2596        fn parse(input: ParseStream) -> Result<Self> {
2597            Ok(ExprContinue {
2598                attrs: Vec::new(),
2599                continue_token: input.parse()?,
2600                label: input.parse()?,
2601            })
2602        }
2603    }
2604
2605    #[cfg(feature = "full")]
2606    fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2607        Ok(ExprBreak {
2608            attrs: Vec::new(),
2609            break_token: input.parse()?,
2610            label: input.parse()?,
2611            expr: {
2612                if input.is_empty()
2613                    || input.peek(Token![,])
2614                    || input.peek(Token![;])
2615                    || !allow_struct.0 && input.peek(token::Brace)
2616                {
2617                    None
2618                } else {
2619                    let expr = ambiguous_expr(input, allow_struct)?;
2620                    Some(Box::new(expr))
2621                }
2622            },
2623        })
2624    }
2625
2626    #[cfg(feature = "full")]
2627    fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
2628        Ok(ExprReturn {
2629            attrs: Vec::new(),
2630            return_token: input.parse()?,
2631            expr: {
2632                if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
2633                    None
2634                } else {
2635                    // NOTE: return is greedy and eats blocks after it even when in a
2636                    // position where structs are not allowed, such as in if statement
2637                    // conditions. For example:
2638                    //
2639                    // if return { println!("A") } {} // Prints "A"
2640                    let expr = ambiguous_expr(input, allow_struct)?;
2641                    Some(Box::new(expr))
2642                }
2643            },
2644        })
2645    }
2646
2647    #[cfg(feature = "full")]
2648    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2649    impl Parse for FieldValue {
2650        fn parse(input: ParseStream) -> Result<Self> {
2651            let attrs = input.call(Attribute::parse_outer)?;
2652            let member: Member = input.parse()?;
2653            let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
2654                let colon_token: Token![:] = input.parse()?;
2655                let value: Expr = input.parse()?;
2656                (Some(colon_token), value)
2657            } else if let Member::Named(ident) = &member {
2658                let value = Expr::Path(ExprPath {
2659                    attrs: Vec::new(),
2660                    qself: None,
2661                    path: Path::from(ident.clone()),
2662                });
2663                (None, value)
2664            } else {
2665                unreachable!()
2666            };
2667
2668            Ok(FieldValue {
2669                attrs,
2670                member,
2671                colon_token,
2672                expr: value,
2673            })
2674        }
2675    }
2676
2677    #[cfg(feature = "full")]
2678    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2679    impl Parse for ExprStruct {
2680        fn parse(input: ParseStream) -> Result<Self> {
2681            let path: Path = input.parse()?;
2682            expr_struct_helper(input, path)
2683        }
2684    }
2685
2686    #[cfg(feature = "full")]
2687    fn expr_struct_helper(input: ParseStream, path: Path) -> Result<ExprStruct> {
2688        let content;
2689        let brace_token = braced!(content in input);
2690
2691        let mut fields = Punctuated::new();
2692        while !content.is_empty() {
2693            if content.peek(Token![..]) {
2694                return Ok(ExprStruct {
2695                    attrs: Vec::new(),
2696                    brace_token,
2697                    path,
2698                    fields,
2699                    dot2_token: Some(content.parse()?),
2700                    rest: if content.is_empty() {
2701                        None
2702                    } else {
2703                        Some(Box::new(content.parse()?))
2704                    },
2705                });
2706            }
2707
2708            fields.push(content.parse()?);
2709            if content.is_empty() {
2710                break;
2711            }
2712            let punct: Token![,] = content.parse()?;
2713            fields.push_punct(punct);
2714        }
2715
2716        Ok(ExprStruct {
2717            attrs: Vec::new(),
2718            brace_token,
2719            path,
2720            fields,
2721            dot2_token: None,
2722            rest: None,
2723        })
2724    }
2725
2726    #[cfg(feature = "full")]
2727    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2728    impl Parse for ExprUnsafe {
2729        fn parse(input: ParseStream) -> Result<Self> {
2730            let unsafe_token: Token![unsafe] = input.parse()?;
2731
2732            let content;
2733            let brace_token = braced!(content in input);
2734            let inner_attrs = content.call(Attribute::parse_inner)?;
2735            let stmts = content.call(Block::parse_within)?;
2736
2737            Ok(ExprUnsafe {
2738                attrs: inner_attrs,
2739                unsafe_token,
2740                block: Block { brace_token, stmts },
2741            })
2742        }
2743    }
2744
2745    #[cfg(feature = "full")]
2746    pub(crate) fn expr_const(input: ParseStream) -> Result<TokenStream> {
2747        let begin = input.fork();
2748        input.parse::<Token![const]>()?;
2749
2750        let content;
2751        braced!(content in input);
2752        content.call(Attribute::parse_inner)?;
2753        content.call(Block::parse_within)?;
2754
2755        Ok(verbatim::between(begin, input))
2756    }
2757
2758    #[cfg(feature = "full")]
2759    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2760    impl Parse for ExprBlock {
2761        fn parse(input: ParseStream) -> Result<Self> {
2762            let mut attrs = input.call(Attribute::parse_outer)?;
2763            let label: Option<Label> = input.parse()?;
2764
2765            let content;
2766            let brace_token = braced!(content in input);
2767            attr::parsing::parse_inner(&content, &mut attrs)?;
2768            let stmts = content.call(Block::parse_within)?;
2769
2770            Ok(ExprBlock {
2771                attrs,
2772                label,
2773                block: Block { brace_token, stmts },
2774            })
2775        }
2776    }
2777
2778    #[cfg(feature = "full")]
2779    fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2780        Ok(ExprRange {
2781            attrs: Vec::new(),
2782            from: None,
2783            limits: input.parse()?,
2784            to: {
2785                if input.is_empty()
2786                    || input.peek(Token![,])
2787                    || input.peek(Token![;])
2788                    || input.peek(Token![.]) && !input.peek(Token![..])
2789                    || !allow_struct.0 && input.peek(token::Brace)
2790                {
2791                    None
2792                } else {
2793                    let to = ambiguous_expr(input, allow_struct)?;
2794                    Some(Box::new(to))
2795                }
2796            },
2797        })
2798    }
2799
2800    #[cfg(feature = "full")]
2801    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2802    impl Parse for RangeLimits {
2803        fn parse(input: ParseStream) -> Result<Self> {
2804            let lookahead = input.lookahead1();
2805            if lookahead.peek(Token![..=]) {
2806                input.parse().map(RangeLimits::Closed)
2807            } else if lookahead.peek(Token![...]) {
2808                let dot3: Token![...] = input.parse()?;
2809                Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2810            } else if lookahead.peek(Token![..]) {
2811                input.parse().map(RangeLimits::HalfOpen)
2812            } else {
2813                Err(lookahead.error())
2814            }
2815        }
2816    }
2817
2818    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2819    impl Parse for ExprPath {
2820        fn parse(input: ParseStream) -> Result<Self> {
2821            #[cfg(not(feature = "full"))]
2822            let attrs = Vec::new();
2823            #[cfg(feature = "full")]
2824            let attrs = input.call(Attribute::parse_outer)?;
2825
2826            let (qself, path) = path::parsing::qpath(input, true)?;
2827
2828            Ok(ExprPath { attrs, qself, path })
2829        }
2830    }
2831
2832    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2833    impl Parse for Member {
2834        fn parse(input: ParseStream) -> Result<Self> {
2835            if input.peek(Ident) {
2836                input.parse().map(Member::Named)
2837            } else if input.peek(LitInt) {
2838                input.parse().map(Member::Unnamed)
2839            } else {
2840                Err(input.error("expected identifier or integer"))
2841            }
2842        }
2843    }
2844
2845    #[cfg(feature = "full")]
2846    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2847    impl Parse for Arm {
2848        fn parse(input: ParseStream) -> Result<Arm> {
2849            let requires_comma;
2850            Ok(Arm {
2851                attrs: input.call(Attribute::parse_outer)?,
2852                pat: pat::parsing::multi_pat_with_leading_vert(input)?,
2853                guard: {
2854                    if input.peek(Token![if]) {
2855                        let if_token: Token![if] = input.parse()?;
2856                        let guard: Expr = input.parse()?;
2857                        Some((if_token, Box::new(guard)))
2858                    } else {
2859                        None
2860                    }
2861                },
2862                fat_arrow_token: input.parse()?,
2863                body: {
2864                    let body = input.call(expr_early)?;
2865                    requires_comma = requires_terminator(&body);
2866                    Box::new(body)
2867                },
2868                comma: {
2869                    if requires_comma && !input.is_empty() {
2870                        Some(input.parse()?)
2871                    } else {
2872                        input.parse()?
2873                    }
2874                },
2875            })
2876        }
2877    }
2878
2879    #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2880    impl Parse for Index {
2881        fn parse(input: ParseStream) -> Result<Self> {
2882            let lit: LitInt = input.parse()?;
2883            if lit.suffix().is_empty() {
2884                Ok(Index {
2885                    index: lit
2886                        .base10_digits()
2887                        .parse()
2888                        .map_err(|err| Error::new(lit.span(), err))?,
2889                    span: lit.span(),
2890                })
2891            } else {
2892                Err(Error::new(lit.span(), "expected unsuffixed integer"))
2893            }
2894        }
2895    }
2896
2897    fn multi_index(e: &mut Expr, dot_token: &mut Token![.], float: LitFloat) -> Result<bool> {
2898        let mut float_repr = float.to_string();
2899        let trailing_dot = float_repr.ends_with('.');
2900        if trailing_dot {
2901            float_repr.truncate(float_repr.len() - 1);
2902        }
2903        for part in float_repr.split('.') {
2904            let index = crate::parse_str(part).map_err(|err| Error::new(float.span(), err))?;
2905            #[cfg(not(syn_no_const_vec_new))]
2906            let base = mem::replace(e, Expr::DUMMY);
2907            #[cfg(syn_no_const_vec_new)]
2908            let base = mem::replace(e, Expr::Verbatim(TokenStream::new()));
2909            *e = Expr::Field(ExprField {
2910                attrs: Vec::new(),
2911                base: Box::new(base),
2912                dot_token: Token![.](dot_token.span),
2913                member: Member::Unnamed(index),
2914            });
2915            *dot_token = Token![.](float.span());
2916        }
2917        Ok(!trailing_dot)
2918    }
2919
2920    #[cfg(feature = "full")]
2921    impl Member {
2922        fn is_named(&self) -> bool {
2923            match *self {
2924                Member::Named(_) => true,
2925                Member::Unnamed(_) => false,
2926            }
2927        }
2928    }
2929
2930    fn check_cast(input: ParseStream) -> Result<()> {
2931        let kind = if input.peek(Token![.]) && !input.peek(Token![..]) {
2932            if input.peek2(token::Await) {
2933                "`.await`"
2934            } else if input.peek2(Ident) && (input.peek3(token::Paren) || input.peek3(Token![::])) {
2935                "a method call"
2936            } else {
2937                "a field access"
2938            }
2939        } else if input.peek(Token![?]) {
2940            "`?`"
2941        } else if input.peek(token::Bracket) {
2942            "indexing"
2943        } else if input.peek(token::Paren) {
2944            "a function call"
2945        } else {
2946            return Ok(());
2947        };
2948        let msg = format!("casts cannot be followed by {}", kind);
2949        Err(input.error(msg))
2950    }
2951}
2952
2953#[cfg(feature = "printing")]
2954pub(crate) mod printing {
2955    use super::*;
2956    #[cfg(feature = "full")]
2957    use crate::attr::FilterAttrs;
2958    use proc_macro2::{Literal, TokenStream};
2959    use quote::{ToTokens, TokenStreamExt};
2960
2961    // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
2962    // before appending it to `TokenStream`.
2963    #[cfg(feature = "full")]
2964    fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) {
2965        if let Expr::Struct(_) = *e {
2966            token::Paren::default().surround(tokens, |tokens| {
2967                e.to_tokens(tokens);
2968            });
2969        } else {
2970            e.to_tokens(tokens);
2971        }
2972    }
2973
2974    #[cfg(feature = "full")]
2975    pub(crate) fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
2976        tokens.append_all(attrs.outer());
2977    }
2978
2979    #[cfg(feature = "full")]
2980    fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
2981        tokens.append_all(attrs.inner());
2982    }
2983
2984    #[cfg(not(feature = "full"))]
2985    pub(crate) fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
2986
2987    #[cfg(feature = "full")]
2988    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
2989    impl ToTokens for ExprBox {
2990        fn to_tokens(&self, tokens: &mut TokenStream) {
2991            outer_attrs_to_tokens(&self.attrs, tokens);
2992            self.box_token.to_tokens(tokens);
2993            self.expr.to_tokens(tokens);
2994        }
2995    }
2996
2997    #[cfg(feature = "full")]
2998    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
2999    impl ToTokens for ExprArray {
3000        fn to_tokens(&self, tokens: &mut TokenStream) {
3001            outer_attrs_to_tokens(&self.attrs, tokens);
3002            self.bracket_token.surround(tokens, |tokens| {
3003                self.elems.to_tokens(tokens);
3004            });
3005        }
3006    }
3007
3008    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3009    impl ToTokens for ExprCall {
3010        fn to_tokens(&self, tokens: &mut TokenStream) {
3011            outer_attrs_to_tokens(&self.attrs, tokens);
3012            self.func.to_tokens(tokens);
3013            self.paren_token.surround(tokens, |tokens| {
3014                self.args.to_tokens(tokens);
3015            });
3016        }
3017    }
3018
3019    #[cfg(feature = "full")]
3020    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3021    impl ToTokens for ExprMethodCall {
3022        fn to_tokens(&self, tokens: &mut TokenStream) {
3023            outer_attrs_to_tokens(&self.attrs, tokens);
3024            self.receiver.to_tokens(tokens);
3025            self.dot_token.to_tokens(tokens);
3026            self.method.to_tokens(tokens);
3027            self.turbofish.to_tokens(tokens);
3028            self.paren_token.surround(tokens, |tokens| {
3029                self.args.to_tokens(tokens);
3030            });
3031        }
3032    }
3033
3034    #[cfg(feature = "full")]
3035    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3036    impl ToTokens for MethodTurbofish {
3037        fn to_tokens(&self, tokens: &mut TokenStream) {
3038            self.colon2_token.to_tokens(tokens);
3039            self.lt_token.to_tokens(tokens);
3040            self.args.to_tokens(tokens);
3041            self.gt_token.to_tokens(tokens);
3042        }
3043    }
3044
3045    #[cfg(feature = "full")]
3046    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3047    impl ToTokens for GenericMethodArgument {
3048        fn to_tokens(&self, tokens: &mut TokenStream) {
3049            match self {
3050                GenericMethodArgument::Type(t) => t.to_tokens(tokens),
3051                GenericMethodArgument::Const(c) => c.to_tokens(tokens),
3052            }
3053        }
3054    }
3055
3056    #[cfg(feature = "full")]
3057    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3058    impl ToTokens for ExprTuple {
3059        fn to_tokens(&self, tokens: &mut TokenStream) {
3060            outer_attrs_to_tokens(&self.attrs, tokens);
3061            self.paren_token.surround(tokens, |tokens| {
3062                self.elems.to_tokens(tokens);
3063                // If we only have one argument, we need a trailing comma to
3064                // distinguish ExprTuple from ExprParen.
3065                if self.elems.len() == 1 && !self.elems.trailing_punct() {
3066                    <Token![,]>::default().to_tokens(tokens);
3067                }
3068            });
3069        }
3070    }
3071
3072    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3073    impl ToTokens for ExprBinary {
3074        fn to_tokens(&self, tokens: &mut TokenStream) {
3075            outer_attrs_to_tokens(&self.attrs, tokens);
3076            self.left.to_tokens(tokens);
3077            self.op.to_tokens(tokens);
3078            self.right.to_tokens(tokens);
3079        }
3080    }
3081
3082    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3083    impl ToTokens for ExprUnary {
3084        fn to_tokens(&self, tokens: &mut TokenStream) {
3085            outer_attrs_to_tokens(&self.attrs, tokens);
3086            self.op.to_tokens(tokens);
3087            self.expr.to_tokens(tokens);
3088        }
3089    }
3090
3091    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3092    impl ToTokens for ExprLit {
3093        fn to_tokens(&self, tokens: &mut TokenStream) {
3094            outer_attrs_to_tokens(&self.attrs, tokens);
3095            self.lit.to_tokens(tokens);
3096        }
3097    }
3098
3099    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3100    impl ToTokens for ExprCast {
3101        fn to_tokens(&self, tokens: &mut TokenStream) {
3102            outer_attrs_to_tokens(&self.attrs, tokens);
3103            self.expr.to_tokens(tokens);
3104            self.as_token.to_tokens(tokens);
3105            self.ty.to_tokens(tokens);
3106        }
3107    }
3108
3109    #[cfg(feature = "full")]
3110    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3111    impl ToTokens for ExprType {
3112        fn to_tokens(&self, tokens: &mut TokenStream) {
3113            outer_attrs_to_tokens(&self.attrs, tokens);
3114            self.expr.to_tokens(tokens);
3115            self.colon_token.to_tokens(tokens);
3116            self.ty.to_tokens(tokens);
3117        }
3118    }
3119
3120    #[cfg(feature = "full")]
3121    fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>) {
3122        if let Some((else_token, else_)) = else_ {
3123            else_token.to_tokens(tokens);
3124
3125            // If we are not one of the valid expressions to exist in an else
3126            // clause, wrap ourselves in a block.
3127            match **else_ {
3128                Expr::If(_) | Expr::Block(_) => {
3129                    else_.to_tokens(tokens);
3130                }
3131                _ => {
3132                    token::Brace::default().surround(tokens, |tokens| {
3133                        else_.to_tokens(tokens);
3134                    });
3135                }
3136            }
3137        }
3138    }
3139
3140    #[cfg(feature = "full")]
3141    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3142    impl ToTokens for ExprLet {
3143        fn to_tokens(&self, tokens: &mut TokenStream) {
3144            outer_attrs_to_tokens(&self.attrs, tokens);
3145            self.let_token.to_tokens(tokens);
3146            self.pat.to_tokens(tokens);
3147            self.eq_token.to_tokens(tokens);
3148            wrap_bare_struct(tokens, &self.expr);
3149        }
3150    }
3151
3152    #[cfg(feature = "full")]
3153    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3154    impl ToTokens for ExprIf {
3155        fn to_tokens(&self, tokens: &mut TokenStream) {
3156            outer_attrs_to_tokens(&self.attrs, tokens);
3157            self.if_token.to_tokens(tokens);
3158            wrap_bare_struct(tokens, &self.cond);
3159            self.then_branch.to_tokens(tokens);
3160            maybe_wrap_else(tokens, &self.else_branch);
3161        }
3162    }
3163
3164    #[cfg(feature = "full")]
3165    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3166    impl ToTokens for ExprWhile {
3167        fn to_tokens(&self, tokens: &mut TokenStream) {
3168            outer_attrs_to_tokens(&self.attrs, tokens);
3169            self.label.to_tokens(tokens);
3170            self.while_token.to_tokens(tokens);
3171            wrap_bare_struct(tokens, &self.cond);
3172            self.body.brace_token.surround(tokens, |tokens| {
3173                inner_attrs_to_tokens(&self.attrs, tokens);
3174                tokens.append_all(&self.body.stmts);
3175            });
3176        }
3177    }
3178
3179    #[cfg(feature = "full")]
3180    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3181    impl ToTokens for ExprForLoop {
3182        fn to_tokens(&self, tokens: &mut TokenStream) {
3183            outer_attrs_to_tokens(&self.attrs, tokens);
3184            self.label.to_tokens(tokens);
3185            self.for_token.to_tokens(tokens);
3186            self.pat.to_tokens(tokens);
3187            self.in_token.to_tokens(tokens);
3188            wrap_bare_struct(tokens, &self.expr);
3189            self.body.brace_token.surround(tokens, |tokens| {
3190                inner_attrs_to_tokens(&self.attrs, tokens);
3191                tokens.append_all(&self.body.stmts);
3192            });
3193        }
3194    }
3195
3196    #[cfg(feature = "full")]
3197    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3198    impl ToTokens for ExprLoop {
3199        fn to_tokens(&self, tokens: &mut TokenStream) {
3200            outer_attrs_to_tokens(&self.attrs, tokens);
3201            self.label.to_tokens(tokens);
3202            self.loop_token.to_tokens(tokens);
3203            self.body.brace_token.surround(tokens, |tokens| {
3204                inner_attrs_to_tokens(&self.attrs, tokens);
3205                tokens.append_all(&self.body.stmts);
3206            });
3207        }
3208    }
3209
3210    #[cfg(feature = "full")]
3211    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3212    impl ToTokens for ExprMatch {
3213        fn to_tokens(&self, tokens: &mut TokenStream) {
3214            outer_attrs_to_tokens(&self.attrs, tokens);
3215            self.match_token.to_tokens(tokens);
3216            wrap_bare_struct(tokens, &self.expr);
3217            self.brace_token.surround(tokens, |tokens| {
3218                inner_attrs_to_tokens(&self.attrs, tokens);
3219                for (i, arm) in self.arms.iter().enumerate() {
3220                    arm.to_tokens(tokens);
3221                    // Ensure that we have a comma after a non-block arm, except
3222                    // for the last one.
3223                    let is_last = i == self.arms.len() - 1;
3224                    if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() {
3225                        <Token![,]>::default().to_tokens(tokens);
3226                    }
3227                }
3228            });
3229        }
3230    }
3231
3232    #[cfg(feature = "full")]
3233    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3234    impl ToTokens for ExprAsync {
3235        fn to_tokens(&self, tokens: &mut TokenStream) {
3236            outer_attrs_to_tokens(&self.attrs, tokens);
3237            self.async_token.to_tokens(tokens);
3238            self.capture.to_tokens(tokens);
3239            self.block.to_tokens(tokens);
3240        }
3241    }
3242
3243    #[cfg(feature = "full")]
3244    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3245    impl ToTokens for ExprAwait {
3246        fn to_tokens(&self, tokens: &mut TokenStream) {
3247            outer_attrs_to_tokens(&self.attrs, tokens);
3248            self.base.to_tokens(tokens);
3249            self.dot_token.to_tokens(tokens);
3250            self.await_token.to_tokens(tokens);
3251        }
3252    }
3253
3254    #[cfg(feature = "full")]
3255    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3256    impl ToTokens for ExprTryBlock {
3257        fn to_tokens(&self, tokens: &mut TokenStream) {
3258            outer_attrs_to_tokens(&self.attrs, tokens);
3259            self.try_token.to_tokens(tokens);
3260            self.block.to_tokens(tokens);
3261        }
3262    }
3263
3264    #[cfg(feature = "full")]
3265    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3266    impl ToTokens for ExprYield {
3267        fn to_tokens(&self, tokens: &mut TokenStream) {
3268            outer_attrs_to_tokens(&self.attrs, tokens);
3269            self.yield_token.to_tokens(tokens);
3270            self.expr.to_tokens(tokens);
3271        }
3272    }
3273
3274    #[cfg(feature = "full")]
3275    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3276    impl ToTokens for ExprClosure {
3277        fn to_tokens(&self, tokens: &mut TokenStream) {
3278            outer_attrs_to_tokens(&self.attrs, tokens);
3279            self.movability.to_tokens(tokens);
3280            self.asyncness.to_tokens(tokens);
3281            self.capture.to_tokens(tokens);
3282            self.or1_token.to_tokens(tokens);
3283            self.inputs.to_tokens(tokens);
3284            self.or2_token.to_tokens(tokens);
3285            self.output.to_tokens(tokens);
3286            self.body.to_tokens(tokens);
3287        }
3288    }
3289
3290    #[cfg(feature = "full")]
3291    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3292    impl ToTokens for ExprUnsafe {
3293        fn to_tokens(&self, tokens: &mut TokenStream) {
3294            outer_attrs_to_tokens(&self.attrs, tokens);
3295            self.unsafe_token.to_tokens(tokens);
3296            self.block.brace_token.surround(tokens, |tokens| {
3297                inner_attrs_to_tokens(&self.attrs, tokens);
3298                tokens.append_all(&self.block.stmts);
3299            });
3300        }
3301    }
3302
3303    #[cfg(feature = "full")]
3304    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3305    impl ToTokens for ExprBlock {
3306        fn to_tokens(&self, tokens: &mut TokenStream) {
3307            outer_attrs_to_tokens(&self.attrs, tokens);
3308            self.label.to_tokens(tokens);
3309            self.block.brace_token.surround(tokens, |tokens| {
3310                inner_attrs_to_tokens(&self.attrs, tokens);
3311                tokens.append_all(&self.block.stmts);
3312            });
3313        }
3314    }
3315
3316    #[cfg(feature = "full")]
3317    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3318    impl ToTokens for ExprAssign {
3319        fn to_tokens(&self, tokens: &mut TokenStream) {
3320            outer_attrs_to_tokens(&self.attrs, tokens);
3321            self.left.to_tokens(tokens);
3322            self.eq_token.to_tokens(tokens);
3323            self.right.to_tokens(tokens);
3324        }
3325    }
3326
3327    #[cfg(feature = "full")]
3328    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3329    impl ToTokens for ExprAssignOp {
3330        fn to_tokens(&self, tokens: &mut TokenStream) {
3331            outer_attrs_to_tokens(&self.attrs, tokens);
3332            self.left.to_tokens(tokens);
3333            self.op.to_tokens(tokens);
3334            self.right.to_tokens(tokens);
3335        }
3336    }
3337
3338    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3339    impl ToTokens for ExprField {
3340        fn to_tokens(&self, tokens: &mut TokenStream) {
3341            outer_attrs_to_tokens(&self.attrs, tokens);
3342            self.base.to_tokens(tokens);
3343            self.dot_token.to_tokens(tokens);
3344            self.member.to_tokens(tokens);
3345        }
3346    }
3347
3348    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3349    impl ToTokens for Member {
3350        fn to_tokens(&self, tokens: &mut TokenStream) {
3351            match self {
3352                Member::Named(ident) => ident.to_tokens(tokens),
3353                Member::Unnamed(index) => index.to_tokens(tokens),
3354            }
3355        }
3356    }
3357
3358    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3359    impl ToTokens for Index {
3360        fn to_tokens(&self, tokens: &mut TokenStream) {
3361            let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
3362            lit.set_span(self.span);
3363            tokens.append(lit);
3364        }
3365    }
3366
3367    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3368    impl ToTokens for ExprIndex {
3369        fn to_tokens(&self, tokens: &mut TokenStream) {
3370            outer_attrs_to_tokens(&self.attrs, tokens);
3371            self.expr.to_tokens(tokens);
3372            self.bracket_token.surround(tokens, |tokens| {
3373                self.index.to_tokens(tokens);
3374            });
3375        }
3376    }
3377
3378    #[cfg(feature = "full")]
3379    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3380    impl ToTokens for RangeLimits {
3381        fn to_tokens(&self, tokens: &mut TokenStream) {
3382            match self {
3383                RangeLimits::HalfOpen(t) => t.to_tokens(tokens),
3384                RangeLimits::Closed(t) => t.to_tokens(tokens),
3385            }
3386        }
3387    }
3388
3389    #[cfg(feature = "full")]
3390    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3391    impl ToTokens for ExprRange {
3392        fn to_tokens(&self, tokens: &mut TokenStream) {
3393            outer_attrs_to_tokens(&self.attrs, tokens);
3394            self.from.to_tokens(tokens);
3395            self.limits.to_tokens(tokens);
3396            self.to.to_tokens(tokens);
3397        }
3398    }
3399
3400    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3401    impl ToTokens for ExprPath {
3402        fn to_tokens(&self, tokens: &mut TokenStream) {
3403            outer_attrs_to_tokens(&self.attrs, tokens);
3404            path::printing::print_path(tokens, &self.qself, &self.path);
3405        }
3406    }
3407
3408    #[cfg(feature = "full")]
3409    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3410    impl ToTokens for ExprReference {
3411        fn to_tokens(&self, tokens: &mut TokenStream) {
3412            outer_attrs_to_tokens(&self.attrs, tokens);
3413            self.and_token.to_tokens(tokens);
3414            self.mutability.to_tokens(tokens);
3415            self.expr.to_tokens(tokens);
3416        }
3417    }
3418
3419    #[cfg(feature = "full")]
3420    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3421    impl ToTokens for ExprBreak {
3422        fn to_tokens(&self, tokens: &mut TokenStream) {
3423            outer_attrs_to_tokens(&self.attrs, tokens);
3424            self.break_token.to_tokens(tokens);
3425            self.label.to_tokens(tokens);
3426            self.expr.to_tokens(tokens);
3427        }
3428    }
3429
3430    #[cfg(feature = "full")]
3431    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3432    impl ToTokens for ExprContinue {
3433        fn to_tokens(&self, tokens: &mut TokenStream) {
3434            outer_attrs_to_tokens(&self.attrs, tokens);
3435            self.continue_token.to_tokens(tokens);
3436            self.label.to_tokens(tokens);
3437        }
3438    }
3439
3440    #[cfg(feature = "full")]
3441    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3442    impl ToTokens for ExprReturn {
3443        fn to_tokens(&self, tokens: &mut TokenStream) {
3444            outer_attrs_to_tokens(&self.attrs, tokens);
3445            self.return_token.to_tokens(tokens);
3446            self.expr.to_tokens(tokens);
3447        }
3448    }
3449
3450    #[cfg(feature = "full")]
3451    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3452    impl ToTokens for ExprMacro {
3453        fn to_tokens(&self, tokens: &mut TokenStream) {
3454            outer_attrs_to_tokens(&self.attrs, tokens);
3455            self.mac.to_tokens(tokens);
3456        }
3457    }
3458
3459    #[cfg(feature = "full")]
3460    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3461    impl ToTokens for ExprStruct {
3462        fn to_tokens(&self, tokens: &mut TokenStream) {
3463            outer_attrs_to_tokens(&self.attrs, tokens);
3464            self.path.to_tokens(tokens);
3465            self.brace_token.surround(tokens, |tokens| {
3466                self.fields.to_tokens(tokens);
3467                if let Some(dot2_token) = &self.dot2_token {
3468                    dot2_token.to_tokens(tokens);
3469                } else if self.rest.is_some() {
3470                    Token![..](Span::call_site()).to_tokens(tokens);
3471                }
3472                self.rest.to_tokens(tokens);
3473            });
3474        }
3475    }
3476
3477    #[cfg(feature = "full")]
3478    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3479    impl ToTokens for ExprRepeat {
3480        fn to_tokens(&self, tokens: &mut TokenStream) {
3481            outer_attrs_to_tokens(&self.attrs, tokens);
3482            self.bracket_token.surround(tokens, |tokens| {
3483                self.expr.to_tokens(tokens);
3484                self.semi_token.to_tokens(tokens);
3485                self.len.to_tokens(tokens);
3486            });
3487        }
3488    }
3489
3490    #[cfg(feature = "full")]
3491    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3492    impl ToTokens for ExprGroup {
3493        fn to_tokens(&self, tokens: &mut TokenStream) {
3494            outer_attrs_to_tokens(&self.attrs, tokens);
3495            self.group_token.surround(tokens, |tokens| {
3496                self.expr.to_tokens(tokens);
3497            });
3498        }
3499    }
3500
3501    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3502    impl ToTokens for ExprParen {
3503        fn to_tokens(&self, tokens: &mut TokenStream) {
3504            outer_attrs_to_tokens(&self.attrs, tokens);
3505            self.paren_token.surround(tokens, |tokens| {
3506                self.expr.to_tokens(tokens);
3507            });
3508        }
3509    }
3510
3511    #[cfg(feature = "full")]
3512    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3513    impl ToTokens for ExprTry {
3514        fn to_tokens(&self, tokens: &mut TokenStream) {
3515            outer_attrs_to_tokens(&self.attrs, tokens);
3516            self.expr.to_tokens(tokens);
3517            self.question_token.to_tokens(tokens);
3518        }
3519    }
3520
3521    #[cfg(feature = "full")]
3522    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3523    impl ToTokens for Label {
3524        fn to_tokens(&self, tokens: &mut TokenStream) {
3525            self.name.to_tokens(tokens);
3526            self.colon_token.to_tokens(tokens);
3527        }
3528    }
3529
3530    #[cfg(feature = "full")]
3531    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3532    impl ToTokens for FieldValue {
3533        fn to_tokens(&self, tokens: &mut TokenStream) {
3534            outer_attrs_to_tokens(&self.attrs, tokens);
3535            self.member.to_tokens(tokens);
3536            if let Some(colon_token) = &self.colon_token {
3537                colon_token.to_tokens(tokens);
3538                self.expr.to_tokens(tokens);
3539            }
3540        }
3541    }
3542
3543    #[cfg(feature = "full")]
3544    #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3545    impl ToTokens for Arm {
3546        fn to_tokens(&self, tokens: &mut TokenStream) {
3547            tokens.append_all(&self.attrs);
3548            self.pat.to_tokens(tokens);
3549            if let Some((if_token, guard)) = &self.guard {
3550                if_token.to_tokens(tokens);
3551                guard.to_tokens(tokens);
3552            }
3553            self.fat_arrow_token.to_tokens(tokens);
3554            self.body.to_tokens(tokens);
3555            self.comma.to_tokens(tokens);
3556        }
3557    }
3558}