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