syn/
expr.rs

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