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
1039ast_struct! {
1040    /// The index of an unnamed tuple struct field.
1041    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
1042    pub struct Index {
1043        pub index: u32,
1044        pub span: Span,
1045    }
1046}
1047
1048impl From<usize> for Index {
1049    fn from(index: usize) -> Index {
1050        assert!(index < u32::MAX as usize);
1051        Index {
1052            index: index as u32,
1053            span: Span::call_site(),
1054        }
1055    }
1056}
1057
1058impl Eq for Index {}
1059
1060impl PartialEq for Index {
1061    fn eq(&self, other: &Self) -> bool {
1062        self.index == other.index
1063    }
1064}
1065
1066impl Hash for Index {
1067    fn hash<H: Hasher>(&self, state: &mut H) {
1068        self.index.hash(state);
1069    }
1070}
1071
1072#[cfg(feature = "printing")]
1073impl IdentFragment for Index {
1074    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1075        Display::fmt(&self.index, formatter)
1076    }
1077
1078    fn span(&self) -> Option<Span> {
1079        Some(self.span)
1080    }
1081}
1082
1083ast_struct! {
1084    /// A field-value pair in a struct literal.
1085    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
1086    pub struct FieldValue {
1087        pub attrs: Vec<Attribute>,
1088        pub member: Member,
1089
1090        /// The colon in `Struct { x: x }`. If written in shorthand like
1091        /// `Struct { x }`, there is no colon.
1092        pub colon_token: Option<Token![:]>,
1093
1094        pub expr: Expr,
1095    }
1096}
1097
1098#[cfg(feature = "full")]
1099ast_struct! {
1100    /// A lifetime labeling a `for`, `while`, or `loop`.
1101    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
1102    pub struct Label {
1103        pub name: Lifetime,
1104        pub colon_token: Token![:],
1105    }
1106}
1107
1108#[cfg(feature = "full")]
1109ast_struct! {
1110    /// One arm of a `match` expression: `0..=10 => { return true; }`.
1111    ///
1112    /// As in:
1113    ///
1114    /// ```
1115    /// # fn f() -> bool {
1116    /// #     let n = 0;
1117    /// match n {
1118    ///     0..=10 => {
1119    ///         return true;
1120    ///     }
1121    ///     // ...
1122    ///     # _ => {}
1123    /// }
1124    /// #   false
1125    /// # }
1126    /// ```
1127    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
1128    pub struct Arm {
1129        pub attrs: Vec<Attribute>,
1130        pub pat: Pat,
1131        pub guard: Option<(Token![if], Box<Expr>)>,
1132        pub fat_arrow_token: Token![=>],
1133        pub body: Box<Expr>,
1134        pub comma: Option<Token![,]>,
1135    }
1136}
1137
1138#[cfg(feature = "full")]
1139ast_enum! {
1140    /// Limit types of a range, inclusive or exclusive.
1141    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
1142    pub enum RangeLimits {
1143        /// Inclusive at the beginning, exclusive at the end.
1144        HalfOpen(Token![..]),
1145        /// Inclusive at the beginning and end.
1146        Closed(Token![..=]),
1147    }
1148}
1149
1150#[cfg(feature = "full")]
1151ast_enum! {
1152    /// Mutability of a raw pointer (`*const T`, `*mut T`), in which non-mutable
1153    /// isn't the implicit default.
1154    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
1155    pub enum PointerMutability {
1156        Const(Token![const]),
1157        Mut(Token![mut]),
1158    }
1159}
1160
1161#[cfg(feature = "parsing")]
1162pub(crate) mod parsing {
1163    #[cfg(feature = "full")]
1164    use crate::attr;
1165    use crate::attr::Attribute;
1166    #[cfg(feature = "full")]
1167    use crate::classify;
1168    use crate::error::{Error, Result};
1169    #[cfg(feature = "full")]
1170    use crate::expr::{
1171        Arm, ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure,
1172        ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch,
1173        ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprUnsafe,
1174        ExprWhile, ExprYield, Label, PointerMutability, RangeLimits,
1175    };
1176    use crate::expr::{
1177        Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro,
1178        ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprTuple, ExprUnary,
1179        FieldValue, Index, Member,
1180    };
1181    #[cfg(feature = "full")]
1182    use crate::generics::BoundLifetimes;
1183    use crate::ident::Ident;
1184    #[cfg(feature = "full")]
1185    use crate::lifetime::Lifetime;
1186    use crate::lit::{Lit, LitFloat, LitInt};
1187    use crate::mac::{self, Macro};
1188    use crate::op::BinOp;
1189    use crate::parse::discouraged::Speculative as _;
1190    #[cfg(feature = "full")]
1191    use crate::parse::ParseBuffer;
1192    use crate::parse::{Parse, ParseStream};
1193    #[cfg(feature = "full")]
1194    use crate::pat::{Pat, PatType};
1195    use crate::path::{self, AngleBracketedGenericArguments, Path, QSelf};
1196    use crate::precedence::Precedence;
1197    use crate::punctuated::Punctuated;
1198    #[cfg(feature = "full")]
1199    use crate::stmt::Block;
1200    use crate::token;
1201    use crate::ty;
1202    #[cfg(feature = "full")]
1203    use crate::ty::{ReturnType, Type};
1204    use crate::verbatim;
1205    #[cfg(feature = "full")]
1206    use proc_macro2::TokenStream;
1207    use std::mem;
1208
1209    // When we're parsing expressions which occur before blocks, like in an if
1210    // statement's condition, we cannot parse a struct literal.
1211    //
1212    // Struct literals are ambiguous in certain positions
1213    // https://github.com/rust-lang/rfcs/pull/92
1214    #[cfg(feature = "full")]
1215    pub(super) struct AllowStruct(pub bool);
1216
1217    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1218    impl Parse for Expr {
1219        fn parse(input: ParseStream) -> Result<Self> {
1220            ambiguous_expr(
1221                input,
1222                #[cfg(feature = "full")]
1223                AllowStruct(true),
1224            )
1225        }
1226    }
1227
1228    #[cfg(feature = "full")]
1229    pub(super) fn parse_with_earlier_boundary_rule(input: ParseStream) -> Result<Expr> {
1230        let mut attrs = input.call(expr_attrs)?;
1231        let mut expr = if input.peek(token::Group) {
1232            let allow_struct = AllowStruct(true);
1233            let atom = expr_group(input, allow_struct)?;
1234            if continue_parsing_early(&atom) {
1235                trailer_helper(input, atom)?
1236            } else {
1237                atom
1238            }
1239        } else if input.peek(Token![if]) {
1240            Expr::If(input.parse()?)
1241        } else if input.peek(Token![while]) {
1242            Expr::While(input.parse()?)
1243        } else if input.peek(Token![for])
1244            && !(input.peek2(Token![<]) && (input.peek3(Lifetime) || input.peek3(Token![>])))
1245        {
1246            Expr::ForLoop(input.parse()?)
1247        } else if input.peek(Token![loop]) {
1248            Expr::Loop(input.parse()?)
1249        } else if input.peek(Token![match]) {
1250            Expr::Match(input.parse()?)
1251        } else if input.peek(Token![try]) && input.peek2(token::Brace) {
1252            Expr::TryBlock(input.parse()?)
1253        } else if input.peek(Token![unsafe]) {
1254            Expr::Unsafe(input.parse()?)
1255        } else if input.peek(Token![const]) && input.peek2(token::Brace) {
1256            Expr::Const(input.parse()?)
1257        } else if input.peek(token::Brace) {
1258            Expr::Block(input.parse()?)
1259        } else if input.peek(Lifetime) {
1260            atom_labeled(input)?
1261        } else {
1262            let allow_struct = AllowStruct(true);
1263            unary_expr(input, allow_struct)?
1264        };
1265
1266        if continue_parsing_early(&expr) {
1267            attrs.extend(expr.replace_attrs(Vec::new()));
1268            expr.replace_attrs(attrs);
1269
1270            let allow_struct = AllowStruct(true);
1271            return parse_expr(input, expr, allow_struct, Precedence::MIN);
1272        }
1273
1274        if input.peek(Token![.]) && !input.peek(Token![..]) || input.peek(Token![?]) {
1275            expr = trailer_helper(input, expr)?;
1276
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        attrs.extend(expr.replace_attrs(Vec::new()));
1285        expr.replace_attrs(attrs);
1286        Ok(expr)
1287    }
1288
1289    #[cfg(feature = "full")]
1290    impl Copy for AllowStruct {}
1291
1292    #[cfg(feature = "full")]
1293    impl Clone for AllowStruct {
1294        fn clone(&self) -> Self {
1295            *self
1296        }
1297    }
1298
1299    #[cfg(feature = "full")]
1300    fn parse_expr(
1301        input: ParseStream,
1302        mut lhs: Expr,
1303        allow_struct: AllowStruct,
1304        base: Precedence,
1305    ) -> Result<Expr> {
1306        loop {
1307            let ahead = input.fork();
1308            if let Expr::Range(ExprRange { end: Some(_), .. }) = lhs {
1309                // A range with an upper bound cannot be the left-hand side of
1310                // another binary operator.
1311                break;
1312            } else if let Ok(op) = ahead.parse::<BinOp>() {
1313                let precedence = Precedence::of_binop(&op);
1314                if precedence < base {
1315                    break;
1316                }
1317                if precedence == Precedence::Compare {
1318                    if let Expr::Binary(lhs) = &lhs {
1319                        if Precedence::of_binop(&lhs.op) == Precedence::Compare {
1320                            return Err(input.error("comparison operators cannot be chained"));
1321                        }
1322                    }
1323                }
1324                input.advance_to(&ahead);
1325                let right = parse_binop_rhs(input, allow_struct, precedence)?;
1326                lhs = Expr::Binary(ExprBinary {
1327                    attrs: Vec::new(),
1328                    left: Box::new(lhs),
1329                    op,
1330                    right,
1331                });
1332            } else if Precedence::Assign >= base && input.peek(Token![=]) && !input.peek(Token![=>])
1333            {
1334                let eq_token: Token![=] = input.parse()?;
1335                let right = parse_binop_rhs(input, allow_struct, Precedence::Assign)?;
1336                lhs = Expr::Assign(ExprAssign {
1337                    attrs: Vec::new(),
1338                    left: Box::new(lhs),
1339                    eq_token,
1340                    right,
1341                });
1342            } else if Precedence::Range >= base && input.peek(Token![..]) {
1343                let limits: RangeLimits = input.parse()?;
1344                let end = parse_range_end(input, &limits, allow_struct)?;
1345                lhs = Expr::Range(ExprRange {
1346                    attrs: Vec::new(),
1347                    start: Some(Box::new(lhs)),
1348                    limits,
1349                    end,
1350                });
1351            } else if Precedence::Cast >= base && input.peek(Token![as]) {
1352                let as_token: Token![as] = input.parse()?;
1353                let allow_plus = false;
1354                let allow_group_generic = false;
1355                let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
1356                check_cast(input)?;
1357                lhs = Expr::Cast(ExprCast {
1358                    attrs: Vec::new(),
1359                    expr: Box::new(lhs),
1360                    as_token,
1361                    ty: Box::new(ty),
1362                });
1363            } else {
1364                break;
1365            }
1366        }
1367        Ok(lhs)
1368    }
1369
1370    #[cfg(not(feature = "full"))]
1371    fn parse_expr(input: ParseStream, mut lhs: Expr, base: Precedence) -> Result<Expr> {
1372        loop {
1373            let ahead = input.fork();
1374            if let Ok(op) = ahead.parse::<BinOp>() {
1375                let precedence = Precedence::of_binop(&op);
1376                if precedence < base {
1377                    break;
1378                }
1379                if precedence == Precedence::Compare {
1380                    if let Expr::Binary(lhs) = &lhs {
1381                        if Precedence::of_binop(&lhs.op) == Precedence::Compare {
1382                            return Err(input.error("comparison operators cannot be chained"));
1383                        }
1384                    }
1385                }
1386                input.advance_to(&ahead);
1387                let right = parse_binop_rhs(input, precedence)?;
1388                lhs = Expr::Binary(ExprBinary {
1389                    attrs: Vec::new(),
1390                    left: Box::new(lhs),
1391                    op,
1392                    right,
1393                });
1394            } else if Precedence::Cast >= base && input.peek(Token![as]) {
1395                let as_token: Token![as] = input.parse()?;
1396                let allow_plus = false;
1397                let allow_group_generic = false;
1398                let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
1399                check_cast(input)?;
1400                lhs = Expr::Cast(ExprCast {
1401                    attrs: Vec::new(),
1402                    expr: Box::new(lhs),
1403                    as_token,
1404                    ty: Box::new(ty),
1405                });
1406            } else {
1407                break;
1408            }
1409        }
1410        Ok(lhs)
1411    }
1412
1413    fn parse_binop_rhs(
1414        input: ParseStream,
1415        #[cfg(feature = "full")] allow_struct: AllowStruct,
1416        precedence: Precedence,
1417    ) -> Result<Box<Expr>> {
1418        let mut rhs = unary_expr(
1419            input,
1420            #[cfg(feature = "full")]
1421            allow_struct,
1422        )?;
1423        loop {
1424            let next = peek_precedence(input);
1425            if next > precedence || next == precedence && precedence == Precedence::Assign {
1426                let cursor = input.cursor();
1427                rhs = parse_expr(
1428                    input,
1429                    rhs,
1430                    #[cfg(feature = "full")]
1431                    allow_struct,
1432                    next,
1433                )?;
1434                if cursor == input.cursor() {
1435                    // Bespoke grammar restrictions separate from precedence can
1436                    // cause parsing to not advance, such as `..a` being
1437                    // disallowed in the left-hand side of binary operators,
1438                    // even ones that have lower precedence than `..`.
1439                    break;
1440                }
1441            } else {
1442                break;
1443            }
1444        }
1445        Ok(Box::new(rhs))
1446    }
1447
1448    fn peek_precedence(input: ParseStream) -> Precedence {
1449        if let Ok(op) = input.fork().parse() {
1450            Precedence::of_binop(&op)
1451        } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
1452            Precedence::Assign
1453        } else if input.peek(Token![..]) {
1454            Precedence::Range
1455        } else if input.peek(Token![as]) {
1456            Precedence::Cast
1457        } else {
1458            Precedence::MIN
1459        }
1460    }
1461
1462    // Parse an arbitrary expression.
1463    pub(super) fn ambiguous_expr(
1464        input: ParseStream,
1465        #[cfg(feature = "full")] allow_struct: AllowStruct,
1466    ) -> Result<Expr> {
1467        let lhs = unary_expr(
1468            input,
1469            #[cfg(feature = "full")]
1470            allow_struct,
1471        )?;
1472        parse_expr(
1473            input,
1474            lhs,
1475            #[cfg(feature = "full")]
1476            allow_struct,
1477            Precedence::MIN,
1478        )
1479    }
1480
1481    #[cfg(feature = "full")]
1482    fn expr_attrs(input: ParseStream) -> Result<Vec<Attribute>> {
1483        let mut attrs = Vec::new();
1484        while !input.peek(token::Group) && input.peek(Token![#]) {
1485            attrs.push(input.call(attr::parsing::single_parse_outer)?);
1486        }
1487        Ok(attrs)
1488    }
1489
1490    // <UnOp> <trailer>
1491    // & <trailer>
1492    // &mut <trailer>
1493    // box <trailer>
1494    #[cfg(feature = "full")]
1495    fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1496        let begin = input.fork();
1497        let attrs = input.call(expr_attrs)?;
1498        if input.peek(token::Group) {
1499            return trailer_expr(begin, attrs, input, allow_struct);
1500        }
1501
1502        if input.peek(Token![&]) {
1503            let and_token: Token![&] = input.parse()?;
1504            let raw: Option<Token![raw]> = if input.peek(Token![raw])
1505                && (input.peek2(Token![mut]) || input.peek2(Token![const]))
1506            {
1507                Some(input.parse()?)
1508            } else {
1509                None
1510            };
1511            let mutability: Option<Token![mut]> = input.parse()?;
1512            let const_token: Option<Token![const]> = if raw.is_some() && mutability.is_none() {
1513                Some(input.parse()?)
1514            } else {
1515                None
1516            };
1517            let expr = Box::new(unary_expr(input, allow_struct)?);
1518            if let Some(raw) = raw {
1519                Ok(Expr::RawAddr(ExprRawAddr {
1520                    attrs,
1521                    and_token,
1522                    raw,
1523                    mutability: match mutability {
1524                        Some(mut_token) => PointerMutability::Mut(mut_token),
1525                        None => PointerMutability::Const(const_token.unwrap()),
1526                    },
1527                    expr,
1528                }))
1529            } else {
1530                Ok(Expr::Reference(ExprReference {
1531                    attrs,
1532                    and_token,
1533                    mutability,
1534                    expr,
1535                }))
1536            }
1537        } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
1538            expr_unary(input, attrs, allow_struct).map(Expr::Unary)
1539        } else {
1540            trailer_expr(begin, attrs, input, allow_struct)
1541        }
1542    }
1543
1544    #[cfg(not(feature = "full"))]
1545    fn unary_expr(input: ParseStream) -> Result<Expr> {
1546        if input.peek(Token![&]) {
1547            Ok(Expr::Reference(ExprReference {
1548                attrs: Vec::new(),
1549                and_token: input.parse()?,
1550                mutability: input.parse()?,
1551                expr: Box::new(unary_expr(input)?),
1552            }))
1553        } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
1554            Ok(Expr::Unary(ExprUnary {
1555                attrs: Vec::new(),
1556                op: input.parse()?,
1557                expr: Box::new(unary_expr(input)?),
1558            }))
1559        } else {
1560            trailer_expr(input)
1561        }
1562    }
1563
1564    // <atom> (..<args>) ...
1565    // <atom> . <ident> (..<args>) ...
1566    // <atom> . <ident> ...
1567    // <atom> . <lit> ...
1568    // <atom> [ <expr> ] ...
1569    // <atom> ? ...
1570    #[cfg(feature = "full")]
1571    fn trailer_expr(
1572        begin: ParseBuffer,
1573        mut attrs: Vec<Attribute>,
1574        input: ParseStream,
1575        allow_struct: AllowStruct,
1576    ) -> Result<Expr> {
1577        let atom = atom_expr(input, allow_struct)?;
1578        let mut e = trailer_helper(input, atom)?;
1579
1580        if let Expr::Verbatim(tokens) = &mut e {
1581            *tokens = verbatim::between(&begin, input);
1582        } else {
1583            let inner_attrs = e.replace_attrs(Vec::new());
1584            attrs.extend(inner_attrs);
1585            e.replace_attrs(attrs);
1586        }
1587
1588        Ok(e)
1589    }
1590
1591    #[cfg(feature = "full")]
1592    fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
1593        loop {
1594            if input.peek(token::Paren) {
1595                let content;
1596                e = Expr::Call(ExprCall {
1597                    attrs: Vec::new(),
1598                    func: Box::new(e),
1599                    paren_token: parenthesized!(content in input),
1600                    args: content.parse_terminated(Expr::parse, Token![,])?,
1601                });
1602            } else if input.peek(Token![.])
1603                && !input.peek(Token![..])
1604                && match e {
1605                    Expr::Range(_) => false,
1606                    _ => true,
1607                }
1608            {
1609                let mut dot_token: Token![.] = input.parse()?;
1610
1611                let float_token: Option<LitFloat> = input.parse()?;
1612                if let Some(float_token) = float_token {
1613                    if multi_index(&mut e, &mut dot_token, float_token)? {
1614                        continue;
1615                    }
1616                }
1617
1618                let await_token: Option<Token![await]> = input.parse()?;
1619                if let Some(await_token) = await_token {
1620                    e = Expr::Await(ExprAwait {
1621                        attrs: Vec::new(),
1622                        base: Box::new(e),
1623                        dot_token,
1624                        await_token,
1625                    });
1626                    continue;
1627                }
1628
1629                let member: Member = input.parse()?;
1630                let turbofish = if member.is_named() && input.peek(Token![::]) {
1631                    Some(AngleBracketedGenericArguments::parse_turbofish(input)?)
1632                } else {
1633                    None
1634                };
1635
1636                if turbofish.is_some() || input.peek(token::Paren) {
1637                    if let Member::Named(method) = member {
1638                        let content;
1639                        e = Expr::MethodCall(ExprMethodCall {
1640                            attrs: Vec::new(),
1641                            receiver: Box::new(e),
1642                            dot_token,
1643                            method,
1644                            turbofish,
1645                            paren_token: parenthesized!(content in input),
1646                            args: content.parse_terminated(Expr::parse, Token![,])?,
1647                        });
1648                        continue;
1649                    }
1650                }
1651
1652                e = Expr::Field(ExprField {
1653                    attrs: Vec::new(),
1654                    base: Box::new(e),
1655                    dot_token,
1656                    member,
1657                });
1658            } else if input.peek(token::Bracket) {
1659                let content;
1660                e = Expr::Index(ExprIndex {
1661                    attrs: Vec::new(),
1662                    expr: Box::new(e),
1663                    bracket_token: bracketed!(content in input),
1664                    index: content.parse()?,
1665                });
1666            } else if input.peek(Token![?]) {
1667                e = Expr::Try(ExprTry {
1668                    attrs: Vec::new(),
1669                    expr: Box::new(e),
1670                    question_token: input.parse()?,
1671                });
1672            } else {
1673                break;
1674            }
1675        }
1676        Ok(e)
1677    }
1678
1679    #[cfg(not(feature = "full"))]
1680    fn trailer_expr(input: ParseStream) -> Result<Expr> {
1681        let mut e = atom_expr(input)?;
1682
1683        loop {
1684            if input.peek(token::Paren) {
1685                let content;
1686                e = Expr::Call(ExprCall {
1687                    attrs: Vec::new(),
1688                    func: Box::new(e),
1689                    paren_token: parenthesized!(content in input),
1690                    args: content.parse_terminated(Expr::parse, Token![,])?,
1691                });
1692            } else if input.peek(Token![.])
1693                && !input.peek(Token![..])
1694                && !input.peek2(Token![await])
1695            {
1696                let mut dot_token: Token![.] = input.parse()?;
1697
1698                let float_token: Option<LitFloat> = input.parse()?;
1699                if let Some(float_token) = float_token {
1700                    if multi_index(&mut e, &mut dot_token, float_token)? {
1701                        continue;
1702                    }
1703                }
1704
1705                let member: Member = input.parse()?;
1706                let turbofish = if member.is_named() && input.peek(Token![::]) {
1707                    let colon2_token: Token![::] = input.parse()?;
1708                    let turbofish =
1709                        AngleBracketedGenericArguments::do_parse(Some(colon2_token), input)?;
1710                    Some(turbofish)
1711                } else {
1712                    None
1713                };
1714
1715                if turbofish.is_some() || input.peek(token::Paren) {
1716                    if let Member::Named(method) = member {
1717                        let content;
1718                        e = Expr::MethodCall(ExprMethodCall {
1719                            attrs: Vec::new(),
1720                            receiver: Box::new(e),
1721                            dot_token,
1722                            method,
1723                            turbofish,
1724                            paren_token: parenthesized!(content in input),
1725                            args: content.parse_terminated(Expr::parse, Token![,])?,
1726                        });
1727                        continue;
1728                    }
1729                }
1730
1731                e = Expr::Field(ExprField {
1732                    attrs: Vec::new(),
1733                    base: Box::new(e),
1734                    dot_token,
1735                    member,
1736                });
1737            } else if input.peek(token::Bracket) {
1738                let content;
1739                e = Expr::Index(ExprIndex {
1740                    attrs: Vec::new(),
1741                    expr: Box::new(e),
1742                    bracket_token: bracketed!(content in input),
1743                    index: content.parse()?,
1744                });
1745            } else {
1746                break;
1747            }
1748        }
1749
1750        Ok(e)
1751    }
1752
1753    // Parse all atomic expressions which don't have to worry about precedence
1754    // interactions, as they are fully contained.
1755    #[cfg(feature = "full")]
1756    fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1757        if input.peek(token::Group) {
1758            expr_group(input, allow_struct)
1759        } else if input.peek(Lit) {
1760            input.parse().map(Expr::Lit)
1761        } else if input.peek(Token![async])
1762            && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
1763        {
1764            input.parse().map(Expr::Async)
1765        } else if input.peek(Token![try]) && input.peek2(token::Brace) {
1766            input.parse().map(Expr::TryBlock)
1767        } else if input.peek(Token![|])
1768            || input.peek(Token![move])
1769            || input.peek(Token![for])
1770                && input.peek2(Token![<])
1771                && (input.peek3(Lifetime) || input.peek3(Token![>]))
1772            || input.peek(Token![const]) && !input.peek2(token::Brace)
1773            || input.peek(Token![static])
1774            || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1775        {
1776            expr_closure(input, allow_struct).map(Expr::Closure)
1777        } else if token::parsing::peek_keyword(input.cursor(), "builtin") && input.peek2(Token![#])
1778        {
1779            expr_builtin(input)
1780        } else if input.peek(Ident)
1781            || input.peek(Token![::])
1782            || input.peek(Token![<])
1783            || input.peek(Token![self])
1784            || input.peek(Token![Self])
1785            || input.peek(Token![super])
1786            || input.peek(Token![crate])
1787            || input.peek(Token![try]) && (input.peek2(Token![!]) || input.peek2(Token![::]))
1788        {
1789            path_or_macro_or_struct(input, allow_struct)
1790        } else if input.peek(token::Paren) {
1791            paren_or_tuple(input)
1792        } else if input.peek(Token![break]) {
1793            expr_break(input, allow_struct).map(Expr::Break)
1794        } else if input.peek(Token![continue]) {
1795            input.parse().map(Expr::Continue)
1796        } else if input.peek(Token![return]) {
1797            input.parse().map(Expr::Return)
1798        } else if input.peek(Token![become]) {
1799            expr_become(input)
1800        } else if input.peek(token::Bracket) {
1801            array_or_repeat(input)
1802        } else if input.peek(Token![let]) {
1803            expr_let(input, allow_struct).map(Expr::Let)
1804        } else if input.peek(Token![if]) {
1805            input.parse().map(Expr::If)
1806        } else if input.peek(Token![while]) {
1807            input.parse().map(Expr::While)
1808        } else if input.peek(Token![for]) {
1809            input.parse().map(Expr::ForLoop)
1810        } else if input.peek(Token![loop]) {
1811            input.parse().map(Expr::Loop)
1812        } else if input.peek(Token![match]) {
1813            input.parse().map(Expr::Match)
1814        } else if input.peek(Token![yield]) {
1815            input.parse().map(Expr::Yield)
1816        } else if input.peek(Token![unsafe]) {
1817            input.parse().map(Expr::Unsafe)
1818        } else if input.peek(Token![const]) {
1819            input.parse().map(Expr::Const)
1820        } else if input.peek(token::Brace) {
1821            input.parse().map(Expr::Block)
1822        } else if input.peek(Token![..]) {
1823            expr_range(input, allow_struct).map(Expr::Range)
1824        } else if input.peek(Token![_]) {
1825            input.parse().map(Expr::Infer)
1826        } else if input.peek(Lifetime) {
1827            atom_labeled(input)
1828        } else {
1829            Err(input.error("expected an expression"))
1830        }
1831    }
1832
1833    #[cfg(feature = "full")]
1834    fn atom_labeled(input: ParseStream) -> Result<Expr> {
1835        let the_label: Label = input.parse()?;
1836        let mut expr = if input.peek(Token![while]) {
1837            Expr::While(input.parse()?)
1838        } else if input.peek(Token![for]) {
1839            Expr::ForLoop(input.parse()?)
1840        } else if input.peek(Token![loop]) {
1841            Expr::Loop(input.parse()?)
1842        } else if input.peek(token::Brace) {
1843            Expr::Block(input.parse()?)
1844        } else {
1845            return Err(input.error("expected loop or block expression"));
1846        };
1847        match &mut expr {
1848            Expr::While(ExprWhile { label, .. })
1849            | Expr::ForLoop(ExprForLoop { label, .. })
1850            | Expr::Loop(ExprLoop { label, .. })
1851            | Expr::Block(ExprBlock { label, .. }) => *label = Some(the_label),
1852            _ => unreachable!(),
1853        }
1854        Ok(expr)
1855    }
1856
1857    #[cfg(not(feature = "full"))]
1858    fn atom_expr(input: ParseStream) -> Result<Expr> {
1859        if input.peek(token::Group) {
1860            expr_group(input)
1861        } else if input.peek(Lit) {
1862            input.parse().map(Expr::Lit)
1863        } else if input.peek(token::Paren) {
1864            paren_or_tuple(input)
1865        } else if input.peek(Ident)
1866            || input.peek(Token![::])
1867            || input.peek(Token![<])
1868            || input.peek(Token![self])
1869            || input.peek(Token![Self])
1870            || input.peek(Token![super])
1871            || input.peek(Token![crate])
1872        {
1873            path_or_macro_or_struct(input)
1874        } else if input.is_empty() {
1875            Err(input.error("expected an expression"))
1876        } else {
1877            if input.peek(token::Brace) {
1878                let scan = input.fork();
1879                let content;
1880                braced!(content in scan);
1881                if content.parse::<Expr>().is_ok() && content.is_empty() {
1882                    let expr_block = verbatim::between(input, &scan);
1883                    input.advance_to(&scan);
1884                    return Ok(Expr::Verbatim(expr_block));
1885                }
1886            }
1887            Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
1888        }
1889    }
1890
1891    #[cfg(feature = "full")]
1892    fn expr_builtin(input: ParseStream) -> Result<Expr> {
1893        let begin = input.fork();
1894
1895        token::parsing::keyword(input, "builtin")?;
1896        input.parse::<Token![#]>()?;
1897        input.parse::<Ident>()?;
1898
1899        let args;
1900        parenthesized!(args in input);
1901        args.parse::<TokenStream>()?;
1902
1903        Ok(Expr::Verbatim(verbatim::between(&begin, input)))
1904    }
1905
1906    fn path_or_macro_or_struct(
1907        input: ParseStream,
1908        #[cfg(feature = "full")] allow_struct: AllowStruct,
1909    ) -> Result<Expr> {
1910        let expr_style = true;
1911        let (qself, path) = path::parsing::qpath(input, expr_style)?;
1912        rest_of_path_or_macro_or_struct(
1913            qself,
1914            path,
1915            input,
1916            #[cfg(feature = "full")]
1917            allow_struct,
1918        )
1919    }
1920
1921    fn rest_of_path_or_macro_or_struct(
1922        qself: Option<QSelf>,
1923        path: Path,
1924        input: ParseStream,
1925        #[cfg(feature = "full")] allow_struct: AllowStruct,
1926    ) -> Result<Expr> {
1927        if qself.is_none()
1928            && input.peek(Token![!])
1929            && !input.peek(Token![!=])
1930            && path.is_mod_style()
1931        {
1932            let bang_token: Token![!] = input.parse()?;
1933            let (delimiter, tokens) = mac::parse_delimiter(input)?;
1934            return Ok(Expr::Macro(ExprMacro {
1935                attrs: Vec::new(),
1936                mac: Macro {
1937                    path,
1938                    bang_token,
1939                    delimiter,
1940                    tokens,
1941                },
1942            }));
1943        }
1944
1945        #[cfg(not(feature = "full"))]
1946        let allow_struct = (true,);
1947        if allow_struct.0 && input.peek(token::Brace) {
1948            return expr_struct_helper(input, qself, path).map(Expr::Struct);
1949        }
1950
1951        Ok(Expr::Path(ExprPath {
1952            attrs: Vec::new(),
1953            qself,
1954            path,
1955        }))
1956    }
1957
1958    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1959    impl Parse for ExprMacro {
1960        fn parse(input: ParseStream) -> Result<Self> {
1961            Ok(ExprMacro {
1962                attrs: Vec::new(),
1963                mac: input.parse()?,
1964            })
1965        }
1966    }
1967
1968    fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
1969        let content;
1970        let paren_token = parenthesized!(content in input);
1971        if content.is_empty() {
1972            return Ok(Expr::Tuple(ExprTuple {
1973                attrs: Vec::new(),
1974                paren_token,
1975                elems: Punctuated::new(),
1976            }));
1977        }
1978
1979        let first: Expr = content.parse()?;
1980        if content.is_empty() {
1981            return Ok(Expr::Paren(ExprParen {
1982                attrs: Vec::new(),
1983                paren_token,
1984                expr: Box::new(first),
1985            }));
1986        }
1987
1988        let mut elems = Punctuated::new();
1989        elems.push_value(first);
1990        while !content.is_empty() {
1991            let punct = content.parse()?;
1992            elems.push_punct(punct);
1993            if content.is_empty() {
1994                break;
1995            }
1996            let value = content.parse()?;
1997            elems.push_value(value);
1998        }
1999        Ok(Expr::Tuple(ExprTuple {
2000            attrs: Vec::new(),
2001            paren_token,
2002            elems,
2003        }))
2004    }
2005
2006    #[cfg(feature = "full")]
2007    fn array_or_repeat(input: ParseStream) -> Result<Expr> {
2008        let content;
2009        let bracket_token = bracketed!(content in input);
2010        if content.is_empty() {
2011            return Ok(Expr::Array(ExprArray {
2012                attrs: Vec::new(),
2013                bracket_token,
2014                elems: Punctuated::new(),
2015            }));
2016        }
2017
2018        let first: Expr = content.parse()?;
2019        if content.is_empty() || content.peek(Token![,]) {
2020            let mut elems = Punctuated::new();
2021            elems.push_value(first);
2022            while !content.is_empty() {
2023                let punct = content.parse()?;
2024                elems.push_punct(punct);
2025                if content.is_empty() {
2026                    break;
2027                }
2028                let value = content.parse()?;
2029                elems.push_value(value);
2030            }
2031            Ok(Expr::Array(ExprArray {
2032                attrs: Vec::new(),
2033                bracket_token,
2034                elems,
2035            }))
2036        } else if content.peek(Token![;]) {
2037            let semi_token: Token![;] = content.parse()?;
2038            let len: Expr = content.parse()?;
2039            Ok(Expr::Repeat(ExprRepeat {
2040                attrs: Vec::new(),
2041                bracket_token,
2042                expr: Box::new(first),
2043                semi_token,
2044                len: Box::new(len),
2045            }))
2046        } else {
2047            Err(content.error("expected `,` or `;`"))
2048        }
2049    }
2050
2051    #[cfg(feature = "full")]
2052    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2053    impl Parse for ExprArray {
2054        fn parse(input: ParseStream) -> Result<Self> {
2055            let content;
2056            let bracket_token = bracketed!(content in input);
2057            let mut elems = Punctuated::new();
2058
2059            while !content.is_empty() {
2060                let first: Expr = content.parse()?;
2061                elems.push_value(first);
2062                if content.is_empty() {
2063                    break;
2064                }
2065                let punct = content.parse()?;
2066                elems.push_punct(punct);
2067            }
2068
2069            Ok(ExprArray {
2070                attrs: Vec::new(),
2071                bracket_token,
2072                elems,
2073            })
2074        }
2075    }
2076
2077    #[cfg(feature = "full")]
2078    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2079    impl Parse for ExprRepeat {
2080        fn parse(input: ParseStream) -> Result<Self> {
2081            let content;
2082            Ok(ExprRepeat {
2083                bracket_token: bracketed!(content in input),
2084                attrs: Vec::new(),
2085                expr: content.parse()?,
2086                semi_token: content.parse()?,
2087                len: content.parse()?,
2088            })
2089        }
2090    }
2091
2092    #[cfg(feature = "full")]
2093    fn continue_parsing_early(mut expr: &Expr) -> bool {
2094        while let Expr::Group(group) = expr {
2095            expr = &group.expr;
2096        }
2097        match expr {
2098            Expr::If(_)
2099            | Expr::While(_)
2100            | Expr::ForLoop(_)
2101            | Expr::Loop(_)
2102            | Expr::Match(_)
2103            | Expr::TryBlock(_)
2104            | Expr::Unsafe(_)
2105            | Expr::Const(_)
2106            | Expr::Block(_) => false,
2107            _ => true,
2108        }
2109    }
2110
2111    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2112    impl Parse for ExprLit {
2113        fn parse(input: ParseStream) -> Result<Self> {
2114            Ok(ExprLit {
2115                attrs: Vec::new(),
2116                lit: input.parse()?,
2117            })
2118        }
2119    }
2120
2121    fn expr_group(
2122        input: ParseStream,
2123        #[cfg(feature = "full")] allow_struct: AllowStruct,
2124    ) -> Result<Expr> {
2125        let group = crate::group::parse_group(input)?;
2126        let mut inner: Expr = group.content.parse()?;
2127
2128        match inner {
2129            Expr::Path(mut expr) if expr.attrs.is_empty() => {
2130                let grouped_len = expr.path.segments.len();
2131                Path::parse_rest(input, &mut expr.path, true)?;
2132                match rest_of_path_or_macro_or_struct(
2133                    expr.qself,
2134                    expr.path,
2135                    input,
2136                    #[cfg(feature = "full")]
2137                    allow_struct,
2138                )? {
2139                    Expr::Path(expr) if expr.path.segments.len() == grouped_len => {
2140                        inner = Expr::Path(expr);
2141                    }
2142                    extended => return Ok(extended),
2143                }
2144            }
2145            _ => {}
2146        }
2147
2148        Ok(Expr::Group(ExprGroup {
2149            attrs: Vec::new(),
2150            group_token: group.token,
2151            expr: Box::new(inner),
2152        }))
2153    }
2154
2155    #[cfg(feature = "full")]
2156    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2157    impl Parse for ExprParen {
2158        fn parse(input: ParseStream) -> Result<Self> {
2159            let content;
2160            Ok(ExprParen {
2161                attrs: Vec::new(),
2162                paren_token: parenthesized!(content in input),
2163                expr: content.parse()?,
2164            })
2165        }
2166    }
2167
2168    #[cfg(feature = "full")]
2169    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2170    impl Parse for ExprLet {
2171        fn parse(input: ParseStream) -> Result<Self> {
2172            let allow_struct = AllowStruct(true);
2173            expr_let(input, allow_struct)
2174        }
2175    }
2176
2177    #[cfg(feature = "full")]
2178    fn expr_let(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprLet> {
2179        Ok(ExprLet {
2180            attrs: Vec::new(),
2181            let_token: input.parse()?,
2182            pat: Box::new(Pat::parse_multi_with_leading_vert(input)?),
2183            eq_token: input.parse()?,
2184            expr: Box::new({
2185                let lhs = unary_expr(input, allow_struct)?;
2186                parse_expr(input, lhs, allow_struct, Precedence::Compare)?
2187            }),
2188        })
2189    }
2190
2191    #[cfg(feature = "full")]
2192    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2193    impl Parse for ExprIf {
2194        fn parse(input: ParseStream) -> Result<Self> {
2195            let attrs = input.call(Attribute::parse_outer)?;
2196
2197            let mut clauses = Vec::new();
2198            let mut expr;
2199            loop {
2200                let if_token: Token![if] = input.parse()?;
2201                let cond = input.call(Expr::parse_without_eager_brace)?;
2202                let then_branch: Block = input.parse()?;
2203
2204                expr = ExprIf {
2205                    attrs: Vec::new(),
2206                    if_token,
2207                    cond: Box::new(cond),
2208                    then_branch,
2209                    else_branch: None,
2210                };
2211
2212                if !input.peek(Token![else]) {
2213                    break;
2214                }
2215
2216                let else_token: Token![else] = input.parse()?;
2217                let lookahead = input.lookahead1();
2218                if lookahead.peek(Token![if]) {
2219                    expr.else_branch = Some((else_token, Box::new(Expr::PLACEHOLDER)));
2220                    clauses.push(expr);
2221                    continue;
2222                } else if lookahead.peek(token::Brace) {
2223                    expr.else_branch = Some((
2224                        else_token,
2225                        Box::new(Expr::Block(ExprBlock {
2226                            attrs: Vec::new(),
2227                            label: None,
2228                            block: input.parse()?,
2229                        })),
2230                    ));
2231                    break;
2232                } else {
2233                    return Err(lookahead.error());
2234                }
2235            }
2236
2237            while let Some(mut prev) = clauses.pop() {
2238                *prev.else_branch.as_mut().unwrap().1 = Expr::If(expr);
2239                expr = prev;
2240            }
2241            expr.attrs = attrs;
2242            Ok(expr)
2243        }
2244    }
2245
2246    #[cfg(feature = "full")]
2247    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2248    impl Parse for ExprInfer {
2249        fn parse(input: ParseStream) -> Result<Self> {
2250            Ok(ExprInfer {
2251                attrs: input.call(Attribute::parse_outer)?,
2252                underscore_token: input.parse()?,
2253            })
2254        }
2255    }
2256
2257    #[cfg(feature = "full")]
2258    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2259    impl Parse for ExprForLoop {
2260        fn parse(input: ParseStream) -> Result<Self> {
2261            let mut attrs = input.call(Attribute::parse_outer)?;
2262            let label: Option<Label> = input.parse()?;
2263            let for_token: Token![for] = input.parse()?;
2264
2265            let pat = Pat::parse_multi_with_leading_vert(input)?;
2266
2267            let in_token: Token![in] = input.parse()?;
2268            let expr: Expr = input.call(Expr::parse_without_eager_brace)?;
2269
2270            let content;
2271            let brace_token = braced!(content in input);
2272            attr::parsing::parse_inner(&content, &mut attrs)?;
2273            let stmts = content.call(Block::parse_within)?;
2274
2275            Ok(ExprForLoop {
2276                attrs,
2277                label,
2278                for_token,
2279                pat: Box::new(pat),
2280                in_token,
2281                expr: Box::new(expr),
2282                body: Block { brace_token, stmts },
2283            })
2284        }
2285    }
2286
2287    #[cfg(feature = "full")]
2288    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2289    impl Parse for ExprLoop {
2290        fn parse(input: ParseStream) -> Result<Self> {
2291            let mut attrs = input.call(Attribute::parse_outer)?;
2292            let label: Option<Label> = input.parse()?;
2293            let loop_token: Token![loop] = input.parse()?;
2294
2295            let content;
2296            let brace_token = braced!(content in input);
2297            attr::parsing::parse_inner(&content, &mut attrs)?;
2298            let stmts = content.call(Block::parse_within)?;
2299
2300            Ok(ExprLoop {
2301                attrs,
2302                label,
2303                loop_token,
2304                body: Block { brace_token, stmts },
2305            })
2306        }
2307    }
2308
2309    #[cfg(feature = "full")]
2310    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2311    impl Parse for ExprMatch {
2312        fn parse(input: ParseStream) -> Result<Self> {
2313            let mut attrs = input.call(Attribute::parse_outer)?;
2314            let match_token: Token![match] = input.parse()?;
2315            let expr = Expr::parse_without_eager_brace(input)?;
2316
2317            let content;
2318            let brace_token = braced!(content in input);
2319            attr::parsing::parse_inner(&content, &mut attrs)?;
2320
2321            let mut arms = Vec::new();
2322            while !content.is_empty() {
2323                arms.push(content.call(Arm::parse)?);
2324            }
2325
2326            Ok(ExprMatch {
2327                attrs,
2328                match_token,
2329                expr: Box::new(expr),
2330                brace_token,
2331                arms,
2332            })
2333        }
2334    }
2335
2336    macro_rules! impl_by_parsing_expr {
2337        (
2338            $(
2339                $expr_type:ty, $variant:ident, $msg:expr,
2340            )*
2341        ) => {
2342            $(
2343                #[cfg(all(feature = "full", feature = "printing"))]
2344                #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2345                impl Parse for $expr_type {
2346                    fn parse(input: ParseStream) -> Result<Self> {
2347                        let mut expr: Expr = input.parse()?;
2348                        loop {
2349                            match expr {
2350                                Expr::$variant(inner) => return Ok(inner),
2351                                Expr::Group(next) => expr = *next.expr,
2352                                _ => return Err(Error::new_spanned(expr, $msg)),
2353                            }
2354                        }
2355                    }
2356                }
2357            )*
2358        };
2359    }
2360
2361    impl_by_parsing_expr! {
2362        ExprAssign, Assign, "expected assignment expression",
2363        ExprAwait, Await, "expected await expression",
2364        ExprBinary, Binary, "expected binary operation",
2365        ExprCall, Call, "expected function call expression",
2366        ExprCast, Cast, "expected cast expression",
2367        ExprField, Field, "expected struct field access",
2368        ExprIndex, Index, "expected indexing expression",
2369        ExprMethodCall, MethodCall, "expected method call expression",
2370        ExprRange, Range, "expected range expression",
2371        ExprTry, Try, "expected try expression",
2372        ExprTuple, Tuple, "expected tuple expression",
2373    }
2374
2375    #[cfg(feature = "full")]
2376    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2377    impl Parse for ExprUnary {
2378        fn parse(input: ParseStream) -> Result<Self> {
2379            let attrs = Vec::new();
2380            let allow_struct = AllowStruct(true);
2381            expr_unary(input, attrs, allow_struct)
2382        }
2383    }
2384
2385    #[cfg(feature = "full")]
2386    fn expr_unary(
2387        input: ParseStream,
2388        attrs: Vec<Attribute>,
2389        allow_struct: AllowStruct,
2390    ) -> Result<ExprUnary> {
2391        Ok(ExprUnary {
2392            attrs,
2393            op: input.parse()?,
2394            expr: Box::new(unary_expr(input, allow_struct)?),
2395        })
2396    }
2397
2398    #[cfg(feature = "full")]
2399    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2400    impl Parse for ExprClosure {
2401        fn parse(input: ParseStream) -> Result<Self> {
2402            let allow_struct = AllowStruct(true);
2403            expr_closure(input, allow_struct)
2404        }
2405    }
2406
2407    #[cfg(feature = "full")]
2408    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2409    impl Parse for ExprRawAddr {
2410        fn parse(input: ParseStream) -> Result<Self> {
2411            let allow_struct = AllowStruct(true);
2412            Ok(ExprRawAddr {
2413                attrs: Vec::new(),
2414                and_token: input.parse()?,
2415                raw: input.parse()?,
2416                mutability: input.parse()?,
2417                expr: Box::new(unary_expr(input, allow_struct)?),
2418            })
2419        }
2420    }
2421
2422    #[cfg(feature = "full")]
2423    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2424    impl Parse for ExprReference {
2425        fn parse(input: ParseStream) -> Result<Self> {
2426            let allow_struct = AllowStruct(true);
2427            Ok(ExprReference {
2428                attrs: Vec::new(),
2429                and_token: input.parse()?,
2430                mutability: input.parse()?,
2431                expr: Box::new(unary_expr(input, allow_struct)?),
2432            })
2433        }
2434    }
2435
2436    #[cfg(feature = "full")]
2437    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2438    impl Parse for ExprBreak {
2439        fn parse(input: ParseStream) -> Result<Self> {
2440            let allow_struct = AllowStruct(true);
2441            expr_break(input, allow_struct)
2442        }
2443    }
2444
2445    #[cfg(feature = "full")]
2446    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2447    impl Parse for ExprReturn {
2448        fn parse(input: ParseStream) -> Result<Self> {
2449            Ok(ExprReturn {
2450                attrs: Vec::new(),
2451                return_token: input.parse()?,
2452                expr: {
2453                    if Expr::peek(input) {
2454                        Some(input.parse()?)
2455                    } else {
2456                        None
2457                    }
2458                },
2459            })
2460        }
2461    }
2462
2463    #[cfg(feature = "full")]
2464    fn expr_become(input: ParseStream) -> Result<Expr> {
2465        let begin = input.fork();
2466        input.parse::<Token![become]>()?;
2467        input.parse::<Expr>()?;
2468        Ok(Expr::Verbatim(verbatim::between(&begin, input)))
2469    }
2470
2471    #[cfg(feature = "full")]
2472    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2473    impl Parse for ExprTryBlock {
2474        fn parse(input: ParseStream) -> Result<Self> {
2475            Ok(ExprTryBlock {
2476                attrs: Vec::new(),
2477                try_token: input.parse()?,
2478                block: input.parse()?,
2479            })
2480        }
2481    }
2482
2483    #[cfg(feature = "full")]
2484    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2485    impl Parse for ExprYield {
2486        fn parse(input: ParseStream) -> Result<Self> {
2487            Ok(ExprYield {
2488                attrs: Vec::new(),
2489                yield_token: input.parse()?,
2490                expr: {
2491                    if Expr::peek(input) {
2492                        Some(input.parse()?)
2493                    } else {
2494                        None
2495                    }
2496                },
2497            })
2498        }
2499    }
2500
2501    #[cfg(feature = "full")]
2502    fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
2503        let lifetimes: Option<BoundLifetimes> = input.parse()?;
2504        let constness: Option<Token![const]> = input.parse()?;
2505        let movability: Option<Token![static]> = input.parse()?;
2506        let asyncness: Option<Token![async]> = input.parse()?;
2507        let capture: Option<Token![move]> = input.parse()?;
2508        let or1_token: Token![|] = input.parse()?;
2509
2510        let mut inputs = Punctuated::new();
2511        loop {
2512            if input.peek(Token![|]) {
2513                break;
2514            }
2515            let value = closure_arg(input)?;
2516            inputs.push_value(value);
2517            if input.peek(Token![|]) {
2518                break;
2519            }
2520            let punct: Token![,] = input.parse()?;
2521            inputs.push_punct(punct);
2522        }
2523
2524        let or2_token: Token![|] = input.parse()?;
2525
2526        let (output, body) = if input.peek(Token![->]) {
2527            let arrow_token: Token![->] = input.parse()?;
2528            let ty: Type = input.parse()?;
2529            let body: Block = input.parse()?;
2530            let output = ReturnType::Type(arrow_token, Box::new(ty));
2531            let block = Expr::Block(ExprBlock {
2532                attrs: Vec::new(),
2533                label: None,
2534                block: body,
2535            });
2536            (output, block)
2537        } else {
2538            let body = ambiguous_expr(input, allow_struct)?;
2539            (ReturnType::Default, body)
2540        };
2541
2542        Ok(ExprClosure {
2543            attrs: Vec::new(),
2544            lifetimes,
2545            constness,
2546            movability,
2547            asyncness,
2548            capture,
2549            or1_token,
2550            inputs,
2551            or2_token,
2552            output,
2553            body: Box::new(body),
2554        })
2555    }
2556
2557    #[cfg(feature = "full")]
2558    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2559    impl Parse for ExprAsync {
2560        fn parse(input: ParseStream) -> Result<Self> {
2561            Ok(ExprAsync {
2562                attrs: Vec::new(),
2563                async_token: input.parse()?,
2564                capture: input.parse()?,
2565                block: input.parse()?,
2566            })
2567        }
2568    }
2569
2570    #[cfg(feature = "full")]
2571    fn closure_arg(input: ParseStream) -> Result<Pat> {
2572        let attrs = input.call(Attribute::parse_outer)?;
2573        let mut pat = Pat::parse_single(input)?;
2574
2575        if input.peek(Token![:]) {
2576            Ok(Pat::Type(PatType {
2577                attrs,
2578                pat: Box::new(pat),
2579                colon_token: input.parse()?,
2580                ty: input.parse()?,
2581            }))
2582        } else {
2583            match &mut pat {
2584                Pat::Const(pat) => pat.attrs = attrs,
2585                Pat::Ident(pat) => pat.attrs = attrs,
2586                Pat::Lit(pat) => pat.attrs = attrs,
2587                Pat::Macro(pat) => pat.attrs = attrs,
2588                Pat::Or(pat) => pat.attrs = attrs,
2589                Pat::Paren(pat) => pat.attrs = attrs,
2590                Pat::Path(pat) => pat.attrs = attrs,
2591                Pat::Range(pat) => pat.attrs = attrs,
2592                Pat::Reference(pat) => pat.attrs = attrs,
2593                Pat::Rest(pat) => pat.attrs = attrs,
2594                Pat::Slice(pat) => pat.attrs = attrs,
2595                Pat::Struct(pat) => pat.attrs = attrs,
2596                Pat::Tuple(pat) => pat.attrs = attrs,
2597                Pat::TupleStruct(pat) => pat.attrs = attrs,
2598                Pat::Type(_) => unreachable!(),
2599                Pat::Verbatim(_) => {}
2600                Pat::Wild(pat) => pat.attrs = attrs,
2601            }
2602            Ok(pat)
2603        }
2604    }
2605
2606    #[cfg(feature = "full")]
2607    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2608    impl Parse for ExprWhile {
2609        fn parse(input: ParseStream) -> Result<Self> {
2610            let mut attrs = input.call(Attribute::parse_outer)?;
2611            let label: Option<Label> = input.parse()?;
2612            let while_token: Token![while] = input.parse()?;
2613            let cond = Expr::parse_without_eager_brace(input)?;
2614
2615            let content;
2616            let brace_token = braced!(content in input);
2617            attr::parsing::parse_inner(&content, &mut attrs)?;
2618            let stmts = content.call(Block::parse_within)?;
2619
2620            Ok(ExprWhile {
2621                attrs,
2622                label,
2623                while_token,
2624                cond: Box::new(cond),
2625                body: Block { brace_token, stmts },
2626            })
2627        }
2628    }
2629
2630    #[cfg(feature = "full")]
2631    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2632    impl Parse for ExprConst {
2633        fn parse(input: ParseStream) -> Result<Self> {
2634            let const_token: Token![const] = input.parse()?;
2635
2636            let content;
2637            let brace_token = braced!(content in input);
2638            let inner_attrs = content.call(Attribute::parse_inner)?;
2639            let stmts = content.call(Block::parse_within)?;
2640
2641            Ok(ExprConst {
2642                attrs: inner_attrs,
2643                const_token,
2644                block: Block { brace_token, stmts },
2645            })
2646        }
2647    }
2648
2649    #[cfg(feature = "full")]
2650    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2651    impl Parse for Label {
2652        fn parse(input: ParseStream) -> Result<Self> {
2653            Ok(Label {
2654                name: input.parse()?,
2655                colon_token: input.parse()?,
2656            })
2657        }
2658    }
2659
2660    #[cfg(feature = "full")]
2661    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2662    impl Parse for Option<Label> {
2663        fn parse(input: ParseStream) -> Result<Self> {
2664            if input.peek(Lifetime) {
2665                input.parse().map(Some)
2666            } else {
2667                Ok(None)
2668            }
2669        }
2670    }
2671
2672    #[cfg(feature = "full")]
2673    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2674    impl Parse for ExprContinue {
2675        fn parse(input: ParseStream) -> Result<Self> {
2676            Ok(ExprContinue {
2677                attrs: Vec::new(),
2678                continue_token: input.parse()?,
2679                label: input.parse()?,
2680            })
2681        }
2682    }
2683
2684    #[cfg(feature = "full")]
2685    fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2686        let break_token: Token![break] = input.parse()?;
2687
2688        let ahead = input.fork();
2689        let label: Option<Lifetime> = ahead.parse()?;
2690        if label.is_some() && ahead.peek(Token![:]) {
2691            // Not allowed: `break 'label: loop {...}`
2692            // Parentheses are required. `break ('label: loop {...})`
2693            let _: Expr = input.parse()?;
2694            let start_span = label.unwrap().apostrophe;
2695            let end_span = input.cursor().prev_span();
2696            return Err(crate::error::new2(
2697                start_span,
2698                end_span,
2699                "parentheses required",
2700            ));
2701        }
2702
2703        input.advance_to(&ahead);
2704        let expr = if Expr::peek(input) && (allow_struct.0 || !input.peek(token::Brace)) {
2705            Some(input.parse()?)
2706        } else {
2707            None
2708        };
2709
2710        Ok(ExprBreak {
2711            attrs: Vec::new(),
2712            break_token,
2713            label,
2714            expr,
2715        })
2716    }
2717
2718    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2719    impl Parse for FieldValue {
2720        fn parse(input: ParseStream) -> Result<Self> {
2721            let attrs = input.call(Attribute::parse_outer)?;
2722            let member: Member = input.parse()?;
2723            let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
2724                let colon_token: Token![:] = input.parse()?;
2725                let value: Expr = input.parse()?;
2726                (Some(colon_token), value)
2727            } else if let Member::Named(ident) = &member {
2728                let value = Expr::Path(ExprPath {
2729                    attrs: Vec::new(),
2730                    qself: None,
2731                    path: Path::from(ident.clone()),
2732                });
2733                (None, value)
2734            } else {
2735                unreachable!()
2736            };
2737
2738            Ok(FieldValue {
2739                attrs,
2740                member,
2741                colon_token,
2742                expr: value,
2743            })
2744        }
2745    }
2746
2747    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2748    impl Parse for ExprStruct {
2749        fn parse(input: ParseStream) -> Result<Self> {
2750            let expr_style = true;
2751            let (qself, path) = path::parsing::qpath(input, expr_style)?;
2752            expr_struct_helper(input, qself, path)
2753        }
2754    }
2755
2756    fn expr_struct_helper(
2757        input: ParseStream,
2758        qself: Option<QSelf>,
2759        path: Path,
2760    ) -> Result<ExprStruct> {
2761        let content;
2762        let brace_token = braced!(content in input);
2763
2764        let mut fields = Punctuated::new();
2765        while !content.is_empty() {
2766            if content.peek(Token![..]) {
2767                return Ok(ExprStruct {
2768                    attrs: Vec::new(),
2769                    qself,
2770                    path,
2771                    brace_token,
2772                    fields,
2773                    dot2_token: Some(content.parse()?),
2774                    rest: if content.is_empty() {
2775                        None
2776                    } else {
2777                        Some(Box::new(content.parse()?))
2778                    },
2779                });
2780            }
2781
2782            fields.push(content.parse()?);
2783            if content.is_empty() {
2784                break;
2785            }
2786            let punct: Token![,] = content.parse()?;
2787            fields.push_punct(punct);
2788        }
2789
2790        Ok(ExprStruct {
2791            attrs: Vec::new(),
2792            qself,
2793            path,
2794            brace_token,
2795            fields,
2796            dot2_token: None,
2797            rest: None,
2798        })
2799    }
2800
2801    #[cfg(feature = "full")]
2802    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2803    impl Parse for ExprUnsafe {
2804        fn parse(input: ParseStream) -> Result<Self> {
2805            let unsafe_token: Token![unsafe] = input.parse()?;
2806
2807            let content;
2808            let brace_token = braced!(content in input);
2809            let inner_attrs = content.call(Attribute::parse_inner)?;
2810            let stmts = content.call(Block::parse_within)?;
2811
2812            Ok(ExprUnsafe {
2813                attrs: inner_attrs,
2814                unsafe_token,
2815                block: Block { brace_token, stmts },
2816            })
2817        }
2818    }
2819
2820    #[cfg(feature = "full")]
2821    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2822    impl Parse for ExprBlock {
2823        fn parse(input: ParseStream) -> Result<Self> {
2824            let mut attrs = input.call(Attribute::parse_outer)?;
2825            let label: Option<Label> = input.parse()?;
2826
2827            let content;
2828            let brace_token = braced!(content in input);
2829            attr::parsing::parse_inner(&content, &mut attrs)?;
2830            let stmts = content.call(Block::parse_within)?;
2831
2832            Ok(ExprBlock {
2833                attrs,
2834                label,
2835                block: Block { brace_token, stmts },
2836            })
2837        }
2838    }
2839
2840    #[cfg(feature = "full")]
2841    fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2842        let limits: RangeLimits = input.parse()?;
2843        let end = parse_range_end(input, &limits, allow_struct)?;
2844        Ok(ExprRange {
2845            attrs: Vec::new(),
2846            start: None,
2847            limits,
2848            end,
2849        })
2850    }
2851
2852    #[cfg(feature = "full")]
2853    fn parse_range_end(
2854        input: ParseStream,
2855        limits: &RangeLimits,
2856        allow_struct: AllowStruct,
2857    ) -> Result<Option<Box<Expr>>> {
2858        if matches!(limits, RangeLimits::HalfOpen(_))
2859            && (input.is_empty()
2860                || input.peek(Token![,])
2861                || input.peek(Token![;])
2862                || input.peek(Token![.]) && !input.peek(Token![..])
2863                || !allow_struct.0 && input.peek(token::Brace))
2864        {
2865            Ok(None)
2866        } else {
2867            let end = parse_binop_rhs(input, allow_struct, Precedence::Range)?;
2868            Ok(Some(end))
2869        }
2870    }
2871
2872    #[cfg(feature = "full")]
2873    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2874    impl Parse for RangeLimits {
2875        fn parse(input: ParseStream) -> Result<Self> {
2876            let lookahead = input.lookahead1();
2877            let dot_dot = lookahead.peek(Token![..]);
2878            let dot_dot_eq = dot_dot && lookahead.peek(Token![..=]);
2879            let dot_dot_dot = dot_dot && input.peek(Token![...]);
2880            if dot_dot_eq {
2881                input.parse().map(RangeLimits::Closed)
2882            } else if dot_dot && !dot_dot_dot {
2883                input.parse().map(RangeLimits::HalfOpen)
2884            } else {
2885                Err(lookahead.error())
2886            }
2887        }
2888    }
2889
2890    #[cfg(feature = "full")]
2891    impl RangeLimits {
2892        pub(crate) fn parse_obsolete(input: ParseStream) -> Result<Self> {
2893            let lookahead = input.lookahead1();
2894            let dot_dot = lookahead.peek(Token![..]);
2895            let dot_dot_eq = dot_dot && lookahead.peek(Token![..=]);
2896            let dot_dot_dot = dot_dot && input.peek(Token![...]);
2897            if dot_dot_eq {
2898                input.parse().map(RangeLimits::Closed)
2899            } else if dot_dot_dot {
2900                let dot3: Token![...] = input.parse()?;
2901                Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2902            } else if dot_dot {
2903                input.parse().map(RangeLimits::HalfOpen)
2904            } else {
2905                Err(lookahead.error())
2906            }
2907        }
2908    }
2909
2910    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2911    impl Parse for ExprPath {
2912        fn parse(input: ParseStream) -> Result<Self> {
2913            #[cfg(not(feature = "full"))]
2914            let attrs = Vec::new();
2915            #[cfg(feature = "full")]
2916            let attrs = input.call(Attribute::parse_outer)?;
2917
2918            let expr_style = true;
2919            let (qself, path) = path::parsing::qpath(input, expr_style)?;
2920
2921            Ok(ExprPath { attrs, qself, path })
2922        }
2923    }
2924
2925    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2926    impl Parse for Member {
2927        fn parse(input: ParseStream) -> Result<Self> {
2928            if input.peek(Ident) {
2929                input.parse().map(Member::Named)
2930            } else if input.peek(LitInt) {
2931                input.parse().map(Member::Unnamed)
2932            } else {
2933                Err(input.error("expected identifier or integer"))
2934            }
2935        }
2936    }
2937
2938    #[cfg(feature = "full")]
2939    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2940    impl Parse for Arm {
2941        fn parse(input: ParseStream) -> Result<Arm> {
2942            let requires_comma;
2943            Ok(Arm {
2944                attrs: input.call(Attribute::parse_outer)?,
2945                pat: Pat::parse_multi_with_leading_vert(input)?,
2946                guard: {
2947                    if input.peek(Token![if]) {
2948                        let if_token: Token![if] = input.parse()?;
2949                        let guard: Expr = input.parse()?;
2950                        Some((if_token, Box::new(guard)))
2951                    } else {
2952                        None
2953                    }
2954                },
2955                fat_arrow_token: input.parse()?,
2956                body: {
2957                    let body = Expr::parse_with_earlier_boundary_rule(input)?;
2958                    requires_comma = classify::requires_comma_to_be_match_arm(&body);
2959                    Box::new(body)
2960                },
2961                comma: {
2962                    if requires_comma && !input.is_empty() {
2963                        Some(input.parse()?)
2964                    } else {
2965                        input.parse()?
2966                    }
2967                },
2968            })
2969        }
2970    }
2971
2972    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2973    impl Parse for Index {
2974        fn parse(input: ParseStream) -> Result<Self> {
2975            let lit: LitInt = input.parse()?;
2976            if lit.suffix().is_empty() {
2977                Ok(Index {
2978                    index: lit
2979                        .base10_digits()
2980                        .parse()
2981                        .map_err(|err| Error::new(lit.span(), err))?,
2982                    span: lit.span(),
2983                })
2984            } else {
2985                Err(Error::new(lit.span(), "expected unsuffixed integer"))
2986            }
2987        }
2988    }
2989
2990    fn multi_index(e: &mut Expr, dot_token: &mut Token![.], float: LitFloat) -> Result<bool> {
2991        let float_token = float.token();
2992        let float_span = float_token.span();
2993        let mut float_repr = float_token.to_string();
2994        let trailing_dot = float_repr.ends_with('.');
2995        if trailing_dot {
2996            float_repr.truncate(float_repr.len() - 1);
2997        }
2998
2999        let mut offset = 0;
3000        for part in float_repr.split('.') {
3001            let mut index: Index =
3002                crate::parse_str(part).map_err(|err| Error::new(float_span, err))?;
3003            let part_end = offset + part.len();
3004            index.span = float_token.subspan(offset..part_end).unwrap_or(float_span);
3005
3006            let base = mem::replace(e, Expr::PLACEHOLDER);
3007            *e = Expr::Field(ExprField {
3008                attrs: Vec::new(),
3009                base: Box::new(base),
3010                dot_token: Token![.](dot_token.span),
3011                member: Member::Unnamed(index),
3012            });
3013
3014            let dot_span = float_token
3015                .subspan(part_end..part_end + 1)
3016                .unwrap_or(float_span);
3017            *dot_token = Token![.](dot_span);
3018            offset = part_end + 1;
3019        }
3020
3021        Ok(!trailing_dot)
3022    }
3023
3024    impl Member {
3025        pub(crate) fn is_named(&self) -> bool {
3026            match self {
3027                Member::Named(_) => true,
3028                Member::Unnamed(_) => false,
3029            }
3030        }
3031    }
3032
3033    #[cfg(feature = "full")]
3034    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3035    impl Parse for PointerMutability {
3036        fn parse(input: ParseStream) -> Result<Self> {
3037            let lookahead = input.lookahead1();
3038            if lookahead.peek(Token![const]) {
3039                Ok(PointerMutability::Const(input.parse()?))
3040            } else if lookahead.peek(Token![mut]) {
3041                Ok(PointerMutability::Mut(input.parse()?))
3042            } else {
3043                Err(lookahead.error())
3044            }
3045        }
3046    }
3047
3048    fn check_cast(input: ParseStream) -> Result<()> {
3049        let kind = if input.peek(Token![.]) && !input.peek(Token![..]) {
3050            if input.peek2(Token![await]) {
3051                "`.await`"
3052            } else if input.peek2(Ident) && (input.peek3(token::Paren) || input.peek3(Token![::])) {
3053                "a method call"
3054            } else {
3055                "a field access"
3056            }
3057        } else if input.peek(Token![?]) {
3058            "`?`"
3059        } else if input.peek(token::Bracket) {
3060            "indexing"
3061        } else if input.peek(token::Paren) {
3062            "a function call"
3063        } else {
3064            return Ok(());
3065        };
3066        let msg = format!("casts cannot be followed by {}", kind);
3067        Err(input.error(msg))
3068    }
3069}
3070
3071#[cfg(feature = "printing")]
3072pub(crate) mod printing {
3073    use crate::attr::Attribute;
3074    #[cfg(feature = "full")]
3075    use crate::attr::FilterAttrs;
3076    #[cfg(feature = "full")]
3077    use crate::classify;
3078    #[cfg(feature = "full")]
3079    use crate::expr::{
3080        Arm, ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure,
3081        ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch,
3082        ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprUnsafe,
3083        ExprWhile, ExprYield, Label, PointerMutability, RangeLimits,
3084    };
3085    use crate::expr::{
3086        Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro,
3087        ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprTuple, ExprUnary,
3088        FieldValue, Index, Member,
3089    };
3090    use crate::fixup::FixupContext;
3091    use crate::op::BinOp;
3092    use crate::path;
3093    use crate::path::printing::PathStyle;
3094    use crate::precedence::Precedence;
3095    use crate::token;
3096    #[cfg(feature = "full")]
3097    use crate::ty::ReturnType;
3098    use proc_macro2::{Literal, Span, TokenStream};
3099    use quote::{ToTokens, TokenStreamExt};
3100
3101    #[cfg(feature = "full")]
3102    pub(crate) fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3103        tokens.append_all(attrs.outer());
3104    }
3105
3106    #[cfg(feature = "full")]
3107    fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3108        tokens.append_all(attrs.inner());
3109    }
3110
3111    #[cfg(not(feature = "full"))]
3112    pub(crate) fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3113
3114    #[cfg(feature = "full")]
3115    fn print_condition(expr: &Expr, tokens: &mut TokenStream) {
3116        print_subexpression(
3117            expr,
3118            classify::confusable_with_adjacent_block(expr),
3119            tokens,
3120            FixupContext::new_condition(),
3121        );
3122    }
3123
3124    fn print_subexpression(
3125        expr: &Expr,
3126        needs_group: bool,
3127        tokens: &mut TokenStream,
3128        mut fixup: FixupContext,
3129    ) {
3130        if needs_group {
3131            // If we are surrounding the whole cond in parentheses, such as:
3132            //
3133            //     if (return Struct {}) {}
3134            //
3135            // then there is no need for parenthesizing the individual struct
3136            // expressions within. On the other hand if the whole cond is not
3137            // parenthesized, then print_expr must parenthesize exterior struct
3138            // literals.
3139            //
3140            //     if x == (Struct {}) {}
3141            //
3142            fixup = FixupContext::NONE;
3143        }
3144
3145        let do_print_expr = |tokens: &mut TokenStream| print_expr(expr, tokens, fixup);
3146
3147        if needs_group {
3148            token::Paren::default().surround(tokens, do_print_expr);
3149        } else {
3150            do_print_expr(tokens);
3151        }
3152    }
3153
3154    pub(crate) fn print_expr(expr: &Expr, tokens: &mut TokenStream, mut fixup: FixupContext) {
3155        #[cfg(feature = "full")]
3156        let needs_group = fixup.would_cause_statement_boundary(expr);
3157        #[cfg(not(feature = "full"))]
3158        let needs_group = false;
3159
3160        if needs_group {
3161            fixup = FixupContext::NONE;
3162        }
3163
3164        let do_print_expr = |tokens: &mut TokenStream| match expr {
3165            #[cfg(feature = "full")]
3166            Expr::Array(e) => e.to_tokens(tokens),
3167            #[cfg(feature = "full")]
3168            Expr::Assign(e) => print_expr_assign(e, tokens, fixup),
3169            #[cfg(feature = "full")]
3170            Expr::Async(e) => e.to_tokens(tokens),
3171            #[cfg(feature = "full")]
3172            Expr::Await(e) => print_expr_await(e, tokens, fixup),
3173            Expr::Binary(e) => print_expr_binary(e, tokens, fixup),
3174            #[cfg(feature = "full")]
3175            Expr::Block(e) => e.to_tokens(tokens),
3176            #[cfg(feature = "full")]
3177            Expr::Break(e) => print_expr_break(e, tokens, fixup),
3178            Expr::Call(e) => print_expr_call(e, tokens, fixup),
3179            Expr::Cast(e) => print_expr_cast(e, tokens, fixup),
3180            #[cfg(feature = "full")]
3181            Expr::Closure(e) => e.to_tokens(tokens),
3182            #[cfg(feature = "full")]
3183            Expr::Const(e) => e.to_tokens(tokens),
3184            #[cfg(feature = "full")]
3185            Expr::Continue(e) => e.to_tokens(tokens),
3186            Expr::Field(e) => print_expr_field(e, tokens, fixup),
3187            #[cfg(feature = "full")]
3188            Expr::ForLoop(e) => e.to_tokens(tokens),
3189            Expr::Group(e) => e.to_tokens(tokens),
3190            #[cfg(feature = "full")]
3191            Expr::If(e) => e.to_tokens(tokens),
3192            #[cfg(feature = "full")]
3193            Expr::Index(e) => print_expr_index(e, tokens, fixup),
3194            #[cfg(feature = "full")]
3195            Expr::Infer(e) => e.to_tokens(tokens),
3196            #[cfg(feature = "full")]
3197            Expr::Let(e) => print_expr_let(e, tokens, fixup),
3198            Expr::Lit(e) => e.to_tokens(tokens),
3199            #[cfg(feature = "full")]
3200            Expr::Loop(e) => e.to_tokens(tokens),
3201            Expr::Macro(e) => e.to_tokens(tokens),
3202            #[cfg(feature = "full")]
3203            Expr::Match(e) => e.to_tokens(tokens),
3204            Expr::MethodCall(e) => print_expr_method_call(e, tokens, fixup),
3205            Expr::Paren(e) => e.to_tokens(tokens),
3206            Expr::Path(e) => e.to_tokens(tokens),
3207            #[cfg(feature = "full")]
3208            Expr::Range(e) => print_expr_range(e, tokens, fixup),
3209            #[cfg(feature = "full")]
3210            Expr::RawAddr(e) => print_expr_raw_addr(e, tokens, fixup),
3211            Expr::Reference(e) => print_expr_reference(e, tokens, fixup),
3212            #[cfg(feature = "full")]
3213            Expr::Repeat(e) => e.to_tokens(tokens),
3214            #[cfg(feature = "full")]
3215            Expr::Return(e) => print_expr_return(e, tokens, fixup),
3216            Expr::Struct(e) => e.to_tokens(tokens),
3217            #[cfg(feature = "full")]
3218            Expr::Try(e) => print_expr_try(e, tokens, fixup),
3219            #[cfg(feature = "full")]
3220            Expr::TryBlock(e) => e.to_tokens(tokens),
3221            #[cfg(feature = "full")]
3222            Expr::Tuple(e) => e.to_tokens(tokens),
3223            Expr::Unary(e) => print_expr_unary(e, tokens, fixup),
3224            #[cfg(feature = "full")]
3225            Expr::Unsafe(e) => e.to_tokens(tokens),
3226            Expr::Verbatim(e) => e.to_tokens(tokens),
3227            #[cfg(feature = "full")]
3228            Expr::While(e) => e.to_tokens(tokens),
3229            #[cfg(feature = "full")]
3230            Expr::Yield(e) => print_expr_yield(e, tokens, fixup),
3231
3232            #[cfg(not(feature = "full"))]
3233            _ => unreachable!(),
3234        };
3235
3236        if needs_group {
3237            token::Paren::default().surround(tokens, do_print_expr);
3238        } else {
3239            do_print_expr(tokens);
3240        }
3241    }
3242
3243    #[cfg(feature = "full")]
3244    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3245    impl ToTokens for ExprArray {
3246        fn to_tokens(&self, tokens: &mut TokenStream) {
3247            outer_attrs_to_tokens(&self.attrs, tokens);
3248            self.bracket_token.surround(tokens, |tokens| {
3249                self.elems.to_tokens(tokens);
3250            });
3251        }
3252    }
3253
3254    #[cfg(feature = "full")]
3255    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3256    impl ToTokens for ExprAssign {
3257        fn to_tokens(&self, tokens: &mut TokenStream) {
3258            print_expr_assign(self, tokens, FixupContext::NONE);
3259        }
3260    }
3261
3262    #[cfg(feature = "full")]
3263    fn print_expr_assign(e: &ExprAssign, tokens: &mut TokenStream, fixup: FixupContext) {
3264        outer_attrs_to_tokens(&e.attrs, tokens);
3265        print_subexpression(
3266            &e.left,
3267            Precedence::of(&e.left) <= Precedence::Range,
3268            tokens,
3269            fixup.leftmost_subexpression(),
3270        );
3271        e.eq_token.to_tokens(tokens);
3272        print_subexpression(
3273            &e.right,
3274            fixup.trailing_precedence(&e.right) < Precedence::Assign,
3275            tokens,
3276            fixup.subsequent_subexpression(),
3277        );
3278    }
3279
3280    #[cfg(feature = "full")]
3281    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3282    impl ToTokens for ExprAsync {
3283        fn to_tokens(&self, tokens: &mut TokenStream) {
3284            outer_attrs_to_tokens(&self.attrs, tokens);
3285            self.async_token.to_tokens(tokens);
3286            self.capture.to_tokens(tokens);
3287            self.block.to_tokens(tokens);
3288        }
3289    }
3290
3291    #[cfg(feature = "full")]
3292    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3293    impl ToTokens for ExprAwait {
3294        fn to_tokens(&self, tokens: &mut TokenStream) {
3295            print_expr_await(self, tokens, FixupContext::NONE);
3296        }
3297    }
3298
3299    #[cfg(feature = "full")]
3300    fn print_expr_await(e: &ExprAwait, tokens: &mut TokenStream, fixup: FixupContext) {
3301        outer_attrs_to_tokens(&e.attrs, tokens);
3302        print_subexpression(
3303            &e.base,
3304            Precedence::of(&e.base) < Precedence::Unambiguous,
3305            tokens,
3306            fixup.leftmost_subexpression_with_dot(),
3307        );
3308        e.dot_token.to_tokens(tokens);
3309        e.await_token.to_tokens(tokens);
3310    }
3311
3312    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3313    impl ToTokens for ExprBinary {
3314        fn to_tokens(&self, tokens: &mut TokenStream) {
3315            print_expr_binary(self, tokens, FixupContext::NONE);
3316        }
3317    }
3318
3319    fn print_expr_binary(e: &ExprBinary, tokens: &mut TokenStream, fixup: FixupContext) {
3320        outer_attrs_to_tokens(&e.attrs, tokens);
3321
3322        let left_fixup = fixup.leftmost_subexpression_with_begin_operator(
3323            #[cfg(feature = "full")]
3324            match &e.op {
3325                BinOp::Sub(_)
3326                | BinOp::Mul(_)
3327                | BinOp::And(_)
3328                | BinOp::Or(_)
3329                | BinOp::BitAnd(_)
3330                | BinOp::BitOr(_)
3331                | BinOp::Shl(_)
3332                | BinOp::Lt(_) => true,
3333                _ => false,
3334            },
3335            match &e.op {
3336                BinOp::Shl(_) | BinOp::Lt(_) => true,
3337                _ => false,
3338            },
3339        );
3340
3341        let binop_prec = Precedence::of_binop(&e.op);
3342        let left_prec = left_fixup.leading_precedence(&e.left);
3343        let right_prec = fixup.trailing_precedence(&e.right);
3344        let (left_needs_group, right_needs_group) = match binop_prec {
3345            Precedence::Assign => (left_prec <= Precedence::Range, right_prec < binop_prec),
3346            Precedence::Compare => (left_prec <= binop_prec, right_prec <= binop_prec),
3347            _ => (left_prec < binop_prec, right_prec <= binop_prec),
3348        };
3349
3350        print_subexpression(&e.left, left_needs_group, tokens, left_fixup);
3351        e.op.to_tokens(tokens);
3352        print_subexpression(
3353            &e.right,
3354            right_needs_group,
3355            tokens,
3356            fixup.subsequent_subexpression(),
3357        );
3358    }
3359
3360    #[cfg(feature = "full")]
3361    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3362    impl ToTokens for ExprBlock {
3363        fn to_tokens(&self, tokens: &mut TokenStream) {
3364            outer_attrs_to_tokens(&self.attrs, tokens);
3365            self.label.to_tokens(tokens);
3366            self.block.brace_token.surround(tokens, |tokens| {
3367                inner_attrs_to_tokens(&self.attrs, tokens);
3368                tokens.append_all(&self.block.stmts);
3369            });
3370        }
3371    }
3372
3373    #[cfg(feature = "full")]
3374    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3375    impl ToTokens for ExprBreak {
3376        fn to_tokens(&self, tokens: &mut TokenStream) {
3377            print_expr_break(self, tokens, FixupContext::NONE);
3378        }
3379    }
3380
3381    #[cfg(feature = "full")]
3382    fn print_expr_break(e: &ExprBreak, tokens: &mut TokenStream, fixup: FixupContext) {
3383        outer_attrs_to_tokens(&e.attrs, tokens);
3384        e.break_token.to_tokens(tokens);
3385        e.label.to_tokens(tokens);
3386        if let Some(value) = &e.expr {
3387            print_subexpression(
3388                value,
3389                // Parenthesize `break 'inner: loop { break 'inner 1 } + 1`
3390                //                     ^---------------------------------^
3391                e.label.is_none() && classify::expr_leading_label(value),
3392                tokens,
3393                fixup.subsequent_subexpression(),
3394            );
3395        }
3396    }
3397
3398    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3399    impl ToTokens for ExprCall {
3400        fn to_tokens(&self, tokens: &mut TokenStream) {
3401            print_expr_call(self, tokens, FixupContext::NONE);
3402        }
3403    }
3404
3405    fn print_expr_call(e: &ExprCall, tokens: &mut TokenStream, fixup: FixupContext) {
3406        outer_attrs_to_tokens(&e.attrs, tokens);
3407
3408        let call_precedence = if let Expr::Field(_) = &*e.func {
3409            Precedence::MIN
3410        } else {
3411            Precedence::Unambiguous
3412        };
3413        let func_fixup = fixup.leftmost_subexpression_with_begin_operator(
3414            #[cfg(feature = "full")]
3415            true,
3416            false,
3417        );
3418        print_subexpression(
3419            &e.func,
3420            func_fixup.leading_precedence(&e.func) < call_precedence,
3421            tokens,
3422            func_fixup,
3423        );
3424
3425        e.paren_token.surround(tokens, |tokens| {
3426            e.args.to_tokens(tokens);
3427        });
3428    }
3429
3430    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3431    impl ToTokens for ExprCast {
3432        fn to_tokens(&self, tokens: &mut TokenStream) {
3433            print_expr_cast(self, tokens, FixupContext::NONE);
3434        }
3435    }
3436
3437    fn print_expr_cast(e: &ExprCast, tokens: &mut TokenStream, fixup: FixupContext) {
3438        outer_attrs_to_tokens(&e.attrs, tokens);
3439        print_subexpression(
3440            &e.expr,
3441            Precedence::of(&e.expr) < Precedence::Cast,
3442            tokens,
3443            fixup.leftmost_subexpression(),
3444        );
3445        e.as_token.to_tokens(tokens);
3446        e.ty.to_tokens(tokens);
3447    }
3448
3449    #[cfg(feature = "full")]
3450    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3451    impl ToTokens for ExprClosure {
3452        fn to_tokens(&self, tokens: &mut TokenStream) {
3453            outer_attrs_to_tokens(&self.attrs, tokens);
3454            self.lifetimes.to_tokens(tokens);
3455            self.constness.to_tokens(tokens);
3456            self.movability.to_tokens(tokens);
3457            self.asyncness.to_tokens(tokens);
3458            self.capture.to_tokens(tokens);
3459            self.or1_token.to_tokens(tokens);
3460            self.inputs.to_tokens(tokens);
3461            self.or2_token.to_tokens(tokens);
3462            self.output.to_tokens(tokens);
3463            if matches!(self.output, ReturnType::Default) || matches!(*self.body, Expr::Block(_)) {
3464                self.body.to_tokens(tokens);
3465            } else {
3466                token::Brace::default().surround(tokens, |tokens| {
3467                    print_expr(&self.body, tokens, FixupContext::new_stmt());
3468                });
3469            }
3470        }
3471    }
3472
3473    #[cfg(feature = "full")]
3474    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3475    impl ToTokens for ExprConst {
3476        fn to_tokens(&self, tokens: &mut TokenStream) {
3477            outer_attrs_to_tokens(&self.attrs, tokens);
3478            self.const_token.to_tokens(tokens);
3479            self.block.brace_token.surround(tokens, |tokens| {
3480                inner_attrs_to_tokens(&self.attrs, tokens);
3481                tokens.append_all(&self.block.stmts);
3482            });
3483        }
3484    }
3485
3486    #[cfg(feature = "full")]
3487    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3488    impl ToTokens for ExprContinue {
3489        fn to_tokens(&self, tokens: &mut TokenStream) {
3490            outer_attrs_to_tokens(&self.attrs, tokens);
3491            self.continue_token.to_tokens(tokens);
3492            self.label.to_tokens(tokens);
3493        }
3494    }
3495
3496    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3497    impl ToTokens for ExprField {
3498        fn to_tokens(&self, tokens: &mut TokenStream) {
3499            print_expr_field(self, tokens, FixupContext::NONE);
3500        }
3501    }
3502
3503    fn print_expr_field(e: &ExprField, tokens: &mut TokenStream, fixup: FixupContext) {
3504        outer_attrs_to_tokens(&e.attrs, tokens);
3505        print_subexpression(
3506            &e.base,
3507            Precedence::of(&e.base) < Precedence::Unambiguous,
3508            tokens,
3509            fixup.leftmost_subexpression_with_dot(),
3510        );
3511        e.dot_token.to_tokens(tokens);
3512        e.member.to_tokens(tokens);
3513    }
3514
3515    #[cfg(feature = "full")]
3516    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3517    impl ToTokens for ExprForLoop {
3518        fn to_tokens(&self, tokens: &mut TokenStream) {
3519            outer_attrs_to_tokens(&self.attrs, tokens);
3520            self.label.to_tokens(tokens);
3521            self.for_token.to_tokens(tokens);
3522            self.pat.to_tokens(tokens);
3523            self.in_token.to_tokens(tokens);
3524            print_condition(&self.expr, tokens);
3525            self.body.brace_token.surround(tokens, |tokens| {
3526                inner_attrs_to_tokens(&self.attrs, tokens);
3527                tokens.append_all(&self.body.stmts);
3528            });
3529        }
3530    }
3531
3532    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3533    impl ToTokens for ExprGroup {
3534        fn to_tokens(&self, tokens: &mut TokenStream) {
3535            outer_attrs_to_tokens(&self.attrs, tokens);
3536            self.group_token.surround(tokens, |tokens| {
3537                self.expr.to_tokens(tokens);
3538            });
3539        }
3540    }
3541
3542    #[cfg(feature = "full")]
3543    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3544    impl ToTokens for ExprIf {
3545        fn to_tokens(&self, tokens: &mut TokenStream) {
3546            outer_attrs_to_tokens(&self.attrs, tokens);
3547
3548            let mut expr = self;
3549            loop {
3550                expr.if_token.to_tokens(tokens);
3551                print_condition(&expr.cond, tokens);
3552                expr.then_branch.to_tokens(tokens);
3553
3554                let (else_token, else_) = match &expr.else_branch {
3555                    Some(else_branch) => else_branch,
3556                    None => break,
3557                };
3558
3559                else_token.to_tokens(tokens);
3560                match &**else_ {
3561                    Expr::If(next) => {
3562                        expr = next;
3563                    }
3564                    Expr::Block(last) => {
3565                        last.to_tokens(tokens);
3566                        break;
3567                    }
3568                    // If this is not one of the valid expressions to exist in
3569                    // an else clause, wrap it in a block.
3570                    other => {
3571                        token::Brace::default().surround(tokens, |tokens| {
3572                            print_expr(other, tokens, FixupContext::new_stmt());
3573                        });
3574                        break;
3575                    }
3576                }
3577            }
3578        }
3579    }
3580
3581    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3582    impl ToTokens for ExprIndex {
3583        fn to_tokens(&self, tokens: &mut TokenStream) {
3584            print_expr_index(self, tokens, FixupContext::NONE);
3585        }
3586    }
3587
3588    fn print_expr_index(e: &ExprIndex, tokens: &mut TokenStream, fixup: FixupContext) {
3589        outer_attrs_to_tokens(&e.attrs, tokens);
3590        let obj_fixup = fixup.leftmost_subexpression_with_begin_operator(
3591            #[cfg(feature = "full")]
3592            true,
3593            false,
3594        );
3595        print_subexpression(
3596            &e.expr,
3597            obj_fixup.leading_precedence(&e.expr) < Precedence::Unambiguous,
3598            tokens,
3599            obj_fixup,
3600        );
3601        e.bracket_token.surround(tokens, |tokens| {
3602            e.index.to_tokens(tokens);
3603        });
3604    }
3605
3606    #[cfg(feature = "full")]
3607    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3608    impl ToTokens for ExprInfer {
3609        fn to_tokens(&self, tokens: &mut TokenStream) {
3610            outer_attrs_to_tokens(&self.attrs, tokens);
3611            self.underscore_token.to_tokens(tokens);
3612        }
3613    }
3614
3615    #[cfg(feature = "full")]
3616    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3617    impl ToTokens for ExprLet {
3618        fn to_tokens(&self, tokens: &mut TokenStream) {
3619            print_expr_let(self, tokens, FixupContext::NONE);
3620        }
3621    }
3622
3623    #[cfg(feature = "full")]
3624    fn print_expr_let(e: &ExprLet, tokens: &mut TokenStream, fixup: FixupContext) {
3625        outer_attrs_to_tokens(&e.attrs, tokens);
3626        e.let_token.to_tokens(tokens);
3627        e.pat.to_tokens(tokens);
3628        e.eq_token.to_tokens(tokens);
3629        print_subexpression(
3630            &e.expr,
3631            fixup.needs_group_as_let_scrutinee(&e.expr),
3632            tokens,
3633            FixupContext::NONE,
3634        );
3635    }
3636
3637    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3638    impl ToTokens for ExprLit {
3639        fn to_tokens(&self, tokens: &mut TokenStream) {
3640            outer_attrs_to_tokens(&self.attrs, tokens);
3641            self.lit.to_tokens(tokens);
3642        }
3643    }
3644
3645    #[cfg(feature = "full")]
3646    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3647    impl ToTokens for ExprLoop {
3648        fn to_tokens(&self, tokens: &mut TokenStream) {
3649            outer_attrs_to_tokens(&self.attrs, tokens);
3650            self.label.to_tokens(tokens);
3651            self.loop_token.to_tokens(tokens);
3652            self.body.brace_token.surround(tokens, |tokens| {
3653                inner_attrs_to_tokens(&self.attrs, tokens);
3654                tokens.append_all(&self.body.stmts);
3655            });
3656        }
3657    }
3658
3659    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3660    impl ToTokens for ExprMacro {
3661        fn to_tokens(&self, tokens: &mut TokenStream) {
3662            outer_attrs_to_tokens(&self.attrs, tokens);
3663            self.mac.to_tokens(tokens);
3664        }
3665    }
3666
3667    #[cfg(feature = "full")]
3668    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3669    impl ToTokens for ExprMatch {
3670        fn to_tokens(&self, tokens: &mut TokenStream) {
3671            outer_attrs_to_tokens(&self.attrs, tokens);
3672            self.match_token.to_tokens(tokens);
3673            print_condition(&self.expr, tokens);
3674            self.brace_token.surround(tokens, |tokens| {
3675                inner_attrs_to_tokens(&self.attrs, tokens);
3676                for (i, arm) in self.arms.iter().enumerate() {
3677                    arm.to_tokens(tokens);
3678                    // Ensure that we have a comma after a non-block arm, except
3679                    // for the last one.
3680                    let is_last = i == self.arms.len() - 1;
3681                    if !is_last
3682                        && classify::requires_comma_to_be_match_arm(&arm.body)
3683                        && arm.comma.is_none()
3684                    {
3685                        <Token![,]>::default().to_tokens(tokens);
3686                    }
3687                }
3688            });
3689        }
3690    }
3691
3692    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3693    impl ToTokens for ExprMethodCall {
3694        fn to_tokens(&self, tokens: &mut TokenStream) {
3695            print_expr_method_call(self, tokens, FixupContext::NONE);
3696        }
3697    }
3698
3699    fn print_expr_method_call(e: &ExprMethodCall, tokens: &mut TokenStream, fixup: FixupContext) {
3700        outer_attrs_to_tokens(&e.attrs, tokens);
3701        print_subexpression(
3702            &e.receiver,
3703            Precedence::of(&e.receiver) < Precedence::Unambiguous,
3704            tokens,
3705            fixup.leftmost_subexpression_with_dot(),
3706        );
3707        e.dot_token.to_tokens(tokens);
3708        e.method.to_tokens(tokens);
3709        if let Some(turbofish) = &e.turbofish {
3710            path::printing::print_angle_bracketed_generic_arguments(
3711                tokens,
3712                turbofish,
3713                PathStyle::Expr,
3714            );
3715        }
3716        e.paren_token.surround(tokens, |tokens| {
3717            e.args.to_tokens(tokens);
3718        });
3719    }
3720
3721    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3722    impl ToTokens for ExprParen {
3723        fn to_tokens(&self, tokens: &mut TokenStream) {
3724            outer_attrs_to_tokens(&self.attrs, tokens);
3725            self.paren_token.surround(tokens, |tokens| {
3726                self.expr.to_tokens(tokens);
3727            });
3728        }
3729    }
3730
3731    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3732    impl ToTokens for ExprPath {
3733        fn to_tokens(&self, tokens: &mut TokenStream) {
3734            outer_attrs_to_tokens(&self.attrs, tokens);
3735            path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
3736        }
3737    }
3738
3739    #[cfg(feature = "full")]
3740    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3741    impl ToTokens for ExprRange {
3742        fn to_tokens(&self, tokens: &mut TokenStream) {
3743            print_expr_range(self, tokens, FixupContext::NONE);
3744        }
3745    }
3746
3747    #[cfg(feature = "full")]
3748    fn print_expr_range(e: &ExprRange, tokens: &mut TokenStream, fixup: FixupContext) {
3749        outer_attrs_to_tokens(&e.attrs, tokens);
3750        if let Some(start) = &e.start {
3751            print_subexpression(
3752                start,
3753                Precedence::of(start) <= Precedence::Range,
3754                tokens,
3755                fixup.leftmost_subexpression(),
3756            );
3757        }
3758        e.limits.to_tokens(tokens);
3759        if let Some(end) = &e.end {
3760            print_subexpression(
3761                end,
3762                fixup.trailing_precedence(end) <= Precedence::Range,
3763                tokens,
3764                fixup.subsequent_subexpression(),
3765            );
3766        }
3767    }
3768
3769    #[cfg(feature = "full")]
3770    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3771    impl ToTokens for ExprRawAddr {
3772        fn to_tokens(&self, tokens: &mut TokenStream) {
3773            print_expr_raw_addr(self, tokens, FixupContext::NONE);
3774        }
3775    }
3776
3777    #[cfg(feature = "full")]
3778    fn print_expr_raw_addr(e: &ExprRawAddr, tokens: &mut TokenStream, fixup: FixupContext) {
3779        outer_attrs_to_tokens(&e.attrs, tokens);
3780        e.and_token.to_tokens(tokens);
3781        e.raw.to_tokens(tokens);
3782        e.mutability.to_tokens(tokens);
3783        print_subexpression(
3784            &e.expr,
3785            fixup.trailing_precedence(&e.expr) < Precedence::Prefix,
3786            tokens,
3787            fixup.subsequent_subexpression(),
3788        );
3789    }
3790
3791    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3792    impl ToTokens for ExprReference {
3793        fn to_tokens(&self, tokens: &mut TokenStream) {
3794            print_expr_reference(self, tokens, FixupContext::NONE);
3795        }
3796    }
3797
3798    fn print_expr_reference(e: &ExprReference, tokens: &mut TokenStream, fixup: FixupContext) {
3799        outer_attrs_to_tokens(&e.attrs, tokens);
3800        e.and_token.to_tokens(tokens);
3801        e.mutability.to_tokens(tokens);
3802        print_subexpression(
3803            &e.expr,
3804            fixup.trailing_precedence(&e.expr) < Precedence::Prefix,
3805            tokens,
3806            fixup.subsequent_subexpression(),
3807        );
3808    }
3809
3810    #[cfg(feature = "full")]
3811    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3812    impl ToTokens for ExprRepeat {
3813        fn to_tokens(&self, tokens: &mut TokenStream) {
3814            outer_attrs_to_tokens(&self.attrs, tokens);
3815            self.bracket_token.surround(tokens, |tokens| {
3816                self.expr.to_tokens(tokens);
3817                self.semi_token.to_tokens(tokens);
3818                self.len.to_tokens(tokens);
3819            });
3820        }
3821    }
3822
3823    #[cfg(feature = "full")]
3824    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3825    impl ToTokens for ExprReturn {
3826        fn to_tokens(&self, tokens: &mut TokenStream) {
3827            print_expr_return(self, tokens, FixupContext::NONE);
3828        }
3829    }
3830
3831    #[cfg(feature = "full")]
3832    fn print_expr_return(e: &ExprReturn, tokens: &mut TokenStream, fixup: FixupContext) {
3833        outer_attrs_to_tokens(&e.attrs, tokens);
3834        e.return_token.to_tokens(tokens);
3835        if let Some(expr) = &e.expr {
3836            print_expr(expr, tokens, fixup.subsequent_subexpression());
3837        }
3838    }
3839
3840    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3841    impl ToTokens for ExprStruct {
3842        fn to_tokens(&self, tokens: &mut TokenStream) {
3843            outer_attrs_to_tokens(&self.attrs, tokens);
3844            path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
3845            self.brace_token.surround(tokens, |tokens| {
3846                self.fields.to_tokens(tokens);
3847                if let Some(dot2_token) = &self.dot2_token {
3848                    dot2_token.to_tokens(tokens);
3849                } else if self.rest.is_some() {
3850                    Token![..](Span::call_site()).to_tokens(tokens);
3851                }
3852                self.rest.to_tokens(tokens);
3853            });
3854        }
3855    }
3856
3857    #[cfg(feature = "full")]
3858    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3859    impl ToTokens for ExprTry {
3860        fn to_tokens(&self, tokens: &mut TokenStream) {
3861            print_expr_try(self, tokens, FixupContext::NONE);
3862        }
3863    }
3864
3865    #[cfg(feature = "full")]
3866    fn print_expr_try(e: &ExprTry, tokens: &mut TokenStream, fixup: FixupContext) {
3867        outer_attrs_to_tokens(&e.attrs, tokens);
3868        print_subexpression(
3869            &e.expr,
3870            Precedence::of(&e.expr) < Precedence::Unambiguous,
3871            tokens,
3872            fixup.leftmost_subexpression_with_dot(),
3873        );
3874        e.question_token.to_tokens(tokens);
3875    }
3876
3877    #[cfg(feature = "full")]
3878    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3879    impl ToTokens for ExprTryBlock {
3880        fn to_tokens(&self, tokens: &mut TokenStream) {
3881            outer_attrs_to_tokens(&self.attrs, tokens);
3882            self.try_token.to_tokens(tokens);
3883            self.block.to_tokens(tokens);
3884        }
3885    }
3886
3887    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3888    impl ToTokens for ExprTuple {
3889        fn to_tokens(&self, tokens: &mut TokenStream) {
3890            outer_attrs_to_tokens(&self.attrs, tokens);
3891            self.paren_token.surround(tokens, |tokens| {
3892                self.elems.to_tokens(tokens);
3893                // If we only have one argument, we need a trailing comma to
3894                // distinguish ExprTuple from ExprParen.
3895                if self.elems.len() == 1 && !self.elems.trailing_punct() {
3896                    <Token![,]>::default().to_tokens(tokens);
3897                }
3898            });
3899        }
3900    }
3901
3902    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3903    impl ToTokens for ExprUnary {
3904        fn to_tokens(&self, tokens: &mut TokenStream) {
3905            print_expr_unary(self, tokens, FixupContext::NONE);
3906        }
3907    }
3908
3909    fn print_expr_unary(e: &ExprUnary, tokens: &mut TokenStream, fixup: FixupContext) {
3910        outer_attrs_to_tokens(&e.attrs, tokens);
3911        e.op.to_tokens(tokens);
3912        print_subexpression(
3913            &e.expr,
3914            fixup.trailing_precedence(&e.expr) < Precedence::Prefix,
3915            tokens,
3916            fixup.subsequent_subexpression(),
3917        );
3918    }
3919
3920    #[cfg(feature = "full")]
3921    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3922    impl ToTokens for ExprUnsafe {
3923        fn to_tokens(&self, tokens: &mut TokenStream) {
3924            outer_attrs_to_tokens(&self.attrs, tokens);
3925            self.unsafe_token.to_tokens(tokens);
3926            self.block.brace_token.surround(tokens, |tokens| {
3927                inner_attrs_to_tokens(&self.attrs, tokens);
3928                tokens.append_all(&self.block.stmts);
3929            });
3930        }
3931    }
3932
3933    #[cfg(feature = "full")]
3934    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3935    impl ToTokens for ExprWhile {
3936        fn to_tokens(&self, tokens: &mut TokenStream) {
3937            outer_attrs_to_tokens(&self.attrs, tokens);
3938            self.label.to_tokens(tokens);
3939            self.while_token.to_tokens(tokens);
3940            print_condition(&self.cond, tokens);
3941            self.body.brace_token.surround(tokens, |tokens| {
3942                inner_attrs_to_tokens(&self.attrs, tokens);
3943                tokens.append_all(&self.body.stmts);
3944            });
3945        }
3946    }
3947
3948    #[cfg(feature = "full")]
3949    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3950    impl ToTokens for ExprYield {
3951        fn to_tokens(&self, tokens: &mut TokenStream) {
3952            print_expr_yield(self, tokens, FixupContext::NONE);
3953        }
3954    }
3955
3956    #[cfg(feature = "full")]
3957    fn print_expr_yield(e: &ExprYield, tokens: &mut TokenStream, fixup: FixupContext) {
3958        outer_attrs_to_tokens(&e.attrs, tokens);
3959        e.yield_token.to_tokens(tokens);
3960        if let Some(expr) = &e.expr {
3961            print_expr(expr, tokens, fixup.subsequent_subexpression());
3962        }
3963    }
3964
3965    #[cfg(feature = "full")]
3966    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3967    impl ToTokens for Arm {
3968        fn to_tokens(&self, tokens: &mut TokenStream) {
3969            tokens.append_all(&self.attrs);
3970            self.pat.to_tokens(tokens);
3971            if let Some((if_token, guard)) = &self.guard {
3972                if_token.to_tokens(tokens);
3973                guard.to_tokens(tokens);
3974            }
3975            self.fat_arrow_token.to_tokens(tokens);
3976            print_expr(&self.body, tokens, FixupContext::new_match_arm());
3977            self.comma.to_tokens(tokens);
3978        }
3979    }
3980
3981    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3982    impl ToTokens for FieldValue {
3983        fn to_tokens(&self, tokens: &mut TokenStream) {
3984            outer_attrs_to_tokens(&self.attrs, tokens);
3985            self.member.to_tokens(tokens);
3986            if let Some(colon_token) = &self.colon_token {
3987                colon_token.to_tokens(tokens);
3988                self.expr.to_tokens(tokens);
3989            }
3990        }
3991    }
3992
3993    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3994    impl ToTokens for Index {
3995        fn to_tokens(&self, tokens: &mut TokenStream) {
3996            let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
3997            lit.set_span(self.span);
3998            tokens.append(lit);
3999        }
4000    }
4001
4002    #[cfg(feature = "full")]
4003    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4004    impl ToTokens for Label {
4005        fn to_tokens(&self, tokens: &mut TokenStream) {
4006            self.name.to_tokens(tokens);
4007            self.colon_token.to_tokens(tokens);
4008        }
4009    }
4010
4011    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4012    impl ToTokens for Member {
4013        fn to_tokens(&self, tokens: &mut TokenStream) {
4014            match self {
4015                Member::Named(ident) => ident.to_tokens(tokens),
4016                Member::Unnamed(index) => index.to_tokens(tokens),
4017            }
4018        }
4019    }
4020
4021    #[cfg(feature = "full")]
4022    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4023    impl ToTokens for RangeLimits {
4024        fn to_tokens(&self, tokens: &mut TokenStream) {
4025            match self {
4026                RangeLimits::HalfOpen(t) => t.to_tokens(tokens),
4027                RangeLimits::Closed(t) => t.to_tokens(tokens),
4028            }
4029        }
4030    }
4031
4032    #[cfg(feature = "full")]
4033    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4034    impl ToTokens for PointerMutability {
4035        fn to_tokens(&self, tokens: &mut TokenStream) {
4036            match self {
4037                PointerMutability::Const(const_token) => const_token.to_tokens(tokens),
4038                PointerMutability::Mut(mut_token) => mut_token.to_tokens(tokens),
4039            }
4040        }
4041    }
4042}