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