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            #[cfg(feature = "full")]
3222            Expr::Index(e) => print_expr_index(e, tokens, fixup),
3223            #[cfg(feature = "full")]
3224            Expr::Infer(e) => e.to_tokens(tokens),
3225            #[cfg(feature = "full")]
3226            Expr::Let(e) => print_expr_let(e, tokens, fixup),
3227            Expr::Lit(e) => e.to_tokens(tokens),
3228            #[cfg(feature = "full")]
3229            Expr::Loop(e) => e.to_tokens(tokens),
3230            Expr::Macro(e) => e.to_tokens(tokens),
3231            #[cfg(feature = "full")]
3232            Expr::Match(e) => e.to_tokens(tokens),
3233            Expr::MethodCall(e) => print_expr_method_call(e, tokens, fixup),
3234            Expr::Paren(e) => e.to_tokens(tokens),
3235            Expr::Path(e) => e.to_tokens(tokens),
3236            #[cfg(feature = "full")]
3237            Expr::Range(e) => print_expr_range(e, tokens, fixup),
3238            #[cfg(feature = "full")]
3239            Expr::RawAddr(e) => print_expr_raw_addr(e, tokens, fixup),
3240            Expr::Reference(e) => print_expr_reference(e, tokens, fixup),
3241            #[cfg(feature = "full")]
3242            Expr::Repeat(e) => e.to_tokens(tokens),
3243            #[cfg(feature = "full")]
3244            Expr::Return(e) => print_expr_return(e, tokens, fixup),
3245            Expr::Struct(e) => e.to_tokens(tokens),
3246            #[cfg(feature = "full")]
3247            Expr::Try(e) => print_expr_try(e, tokens, fixup),
3248            #[cfg(feature = "full")]
3249            Expr::TryBlock(e) => e.to_tokens(tokens),
3250            #[cfg(feature = "full")]
3251            Expr::Tuple(e) => e.to_tokens(tokens),
3252            Expr::Unary(e) => print_expr_unary(e, tokens, fixup),
3253            #[cfg(feature = "full")]
3254            Expr::Unsafe(e) => e.to_tokens(tokens),
3255            Expr::Verbatim(e) => e.to_tokens(tokens),
3256            #[cfg(feature = "full")]
3257            Expr::While(e) => e.to_tokens(tokens),
3258            #[cfg(feature = "full")]
3259            Expr::Yield(e) => print_expr_yield(e, tokens, fixup),
3260
3261            #[cfg(not(feature = "full"))]
3262            _ => unreachable!(),
3263        };
3264
3265        if needs_group {
3266            token::Paren::default().surround(tokens, do_print_expr);
3267        } else {
3268            do_print_expr(tokens);
3269        }
3270    }
3271
3272    #[cfg(feature = "full")]
3273    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3274    impl ToTokens for ExprArray {
3275        fn to_tokens(&self, tokens: &mut TokenStream) {
3276            outer_attrs_to_tokens(&self.attrs, tokens);
3277            self.bracket_token.surround(tokens, |tokens| {
3278                self.elems.to_tokens(tokens);
3279            });
3280        }
3281    }
3282
3283    #[cfg(feature = "full")]
3284    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3285    impl ToTokens for ExprAssign {
3286        fn to_tokens(&self, tokens: &mut TokenStream) {
3287            print_expr_assign(self, tokens, FixupContext::NONE);
3288        }
3289    }
3290
3291    #[cfg(feature = "full")]
3292    fn print_expr_assign(e: &ExprAssign, tokens: &mut TokenStream, fixup: FixupContext) {
3293        outer_attrs_to_tokens(&e.attrs, tokens);
3294        let (left_prec, left_fixup) =
3295            fixup.leftmost_subexpression_with_operator(&e.left, false, false, Precedence::Assign);
3296        print_subexpression(&e.left, left_prec <= Precedence::Range, tokens, left_fixup);
3297        e.eq_token.to_tokens(tokens);
3298        print_expr(
3299            &e.right,
3300            tokens,
3301            fixup.rightmost_subexpression_fixup(false, false, Precedence::Assign),
3302        );
3303    }
3304
3305    #[cfg(feature = "full")]
3306    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3307    impl ToTokens for ExprAsync {
3308        fn to_tokens(&self, tokens: &mut TokenStream) {
3309            outer_attrs_to_tokens(&self.attrs, tokens);
3310            self.async_token.to_tokens(tokens);
3311            self.capture.to_tokens(tokens);
3312            self.block.to_tokens(tokens);
3313        }
3314    }
3315
3316    #[cfg(feature = "full")]
3317    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3318    impl ToTokens for ExprAwait {
3319        fn to_tokens(&self, tokens: &mut TokenStream) {
3320            print_expr_await(self, tokens, FixupContext::NONE);
3321        }
3322    }
3323
3324    #[cfg(feature = "full")]
3325    fn print_expr_await(e: &ExprAwait, tokens: &mut TokenStream, fixup: FixupContext) {
3326        outer_attrs_to_tokens(&e.attrs, tokens);
3327        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.base);
3328        print_subexpression(
3329            &e.base,
3330            left_prec < Precedence::Unambiguous,
3331            tokens,
3332            left_fixup,
3333        );
3334        e.dot_token.to_tokens(tokens);
3335        e.await_token.to_tokens(tokens);
3336    }
3337
3338    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3339    impl ToTokens for ExprBinary {
3340        fn to_tokens(&self, tokens: &mut TokenStream) {
3341            print_expr_binary(self, tokens, FixupContext::NONE);
3342        }
3343    }
3344
3345    fn print_expr_binary(e: &ExprBinary, tokens: &mut TokenStream, fixup: FixupContext) {
3346        outer_attrs_to_tokens(&e.attrs, tokens);
3347
3348        let binop_prec = Precedence::of_binop(&e.op);
3349        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3350            &e.left,
3351            #[cfg(feature = "full")]
3352            match &e.op {
3353                BinOp::Sub(_)
3354                | BinOp::Mul(_)
3355                | BinOp::And(_)
3356                | BinOp::Or(_)
3357                | BinOp::BitAnd(_)
3358                | BinOp::BitOr(_)
3359                | BinOp::Shl(_)
3360                | BinOp::Lt(_) => true,
3361                _ => false,
3362            },
3363            match &e.op {
3364                BinOp::Shl(_) | BinOp::Lt(_) => true,
3365                _ => false,
3366            },
3367            #[cfg(feature = "full")]
3368            binop_prec,
3369        );
3370        let left_needs_group = match binop_prec {
3371            Precedence::Assign => left_prec <= Precedence::Range,
3372            Precedence::Compare => left_prec <= binop_prec,
3373            _ => left_prec < binop_prec,
3374        };
3375
3376        let right_fixup = fixup.rightmost_subexpression_fixup(
3377            #[cfg(feature = "full")]
3378            false,
3379            #[cfg(feature = "full")]
3380            false,
3381            #[cfg(feature = "full")]
3382            binop_prec,
3383        );
3384        let right_needs_group = binop_prec != Precedence::Assign
3385            && right_fixup.rightmost_subexpression_precedence(&e.right) <= binop_prec;
3386
3387        print_subexpression(&e.left, left_needs_group, tokens, left_fixup);
3388        e.op.to_tokens(tokens);
3389        print_subexpression(&e.right, right_needs_group, tokens, right_fixup);
3390    }
3391
3392    #[cfg(feature = "full")]
3393    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3394    impl ToTokens for ExprBlock {
3395        fn to_tokens(&self, tokens: &mut TokenStream) {
3396            outer_attrs_to_tokens(&self.attrs, tokens);
3397            self.label.to_tokens(tokens);
3398            self.block.brace_token.surround(tokens, |tokens| {
3399                inner_attrs_to_tokens(&self.attrs, tokens);
3400                tokens.append_all(&self.block.stmts);
3401            });
3402        }
3403    }
3404
3405    #[cfg(feature = "full")]
3406    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3407    impl ToTokens for ExprBreak {
3408        fn to_tokens(&self, tokens: &mut TokenStream) {
3409            print_expr_break(self, tokens, FixupContext::NONE);
3410        }
3411    }
3412
3413    #[cfg(feature = "full")]
3414    fn print_expr_break(e: &ExprBreak, tokens: &mut TokenStream, fixup: FixupContext) {
3415        outer_attrs_to_tokens(&e.attrs, tokens);
3416        e.break_token.to_tokens(tokens);
3417        e.label.to_tokens(tokens);
3418        if let Some(value) = &e.expr {
3419            print_subexpression(
3420                value,
3421                // Parenthesize `break 'inner: loop { break 'inner 1 } + 1`
3422                //                     ^---------------------------------^
3423                e.label.is_none() && classify::expr_leading_label(value),
3424                tokens,
3425                fixup.rightmost_subexpression_fixup(true, true, Precedence::Jump),
3426            );
3427        }
3428    }
3429
3430    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3431    impl ToTokens for ExprCall {
3432        fn to_tokens(&self, tokens: &mut TokenStream) {
3433            print_expr_call(self, tokens, FixupContext::NONE);
3434        }
3435    }
3436
3437    fn print_expr_call(e: &ExprCall, tokens: &mut TokenStream, fixup: FixupContext) {
3438        outer_attrs_to_tokens(&e.attrs, tokens);
3439
3440        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3441            &e.func,
3442            #[cfg(feature = "full")]
3443            true,
3444            false,
3445            #[cfg(feature = "full")]
3446            Precedence::Unambiguous,
3447        );
3448        let needs_group = if let Expr::Field(func) = &*e.func {
3449            func.member.is_named()
3450        } else {
3451            left_prec < Precedence::Unambiguous
3452        };
3453        print_subexpression(&e.func, needs_group, tokens, left_fixup);
3454
3455        e.paren_token.surround(tokens, |tokens| {
3456            e.args.to_tokens(tokens);
3457        });
3458    }
3459
3460    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3461    impl ToTokens for ExprCast {
3462        fn to_tokens(&self, tokens: &mut TokenStream) {
3463            print_expr_cast(self, tokens, FixupContext::NONE);
3464        }
3465    }
3466
3467    fn print_expr_cast(e: &ExprCast, tokens: &mut TokenStream, fixup: FixupContext) {
3468        outer_attrs_to_tokens(&e.attrs, tokens);
3469        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3470            &e.expr,
3471            #[cfg(feature = "full")]
3472            false,
3473            false,
3474            #[cfg(feature = "full")]
3475            Precedence::Cast,
3476        );
3477        print_subexpression(&e.expr, left_prec < Precedence::Cast, tokens, left_fixup);
3478        e.as_token.to_tokens(tokens);
3479        e.ty.to_tokens(tokens);
3480    }
3481
3482    #[cfg(feature = "full")]
3483    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3484    impl ToTokens for ExprClosure {
3485        fn to_tokens(&self, tokens: &mut TokenStream) {
3486            print_expr_closure(self, tokens, FixupContext::NONE);
3487        }
3488    }
3489
3490    #[cfg(feature = "full")]
3491    fn print_expr_closure(e: &ExprClosure, tokens: &mut TokenStream, fixup: FixupContext) {
3492        outer_attrs_to_tokens(&e.attrs, tokens);
3493        e.lifetimes.to_tokens(tokens);
3494        e.constness.to_tokens(tokens);
3495        e.movability.to_tokens(tokens);
3496        e.asyncness.to_tokens(tokens);
3497        e.capture.to_tokens(tokens);
3498        e.or1_token.to_tokens(tokens);
3499        e.inputs.to_tokens(tokens);
3500        e.or2_token.to_tokens(tokens);
3501        e.output.to_tokens(tokens);
3502        if matches!(e.output, ReturnType::Default)
3503            || matches!(&*e.body, Expr::Block(body) if body.attrs.is_empty() && body.label.is_none())
3504        {
3505            print_expr(
3506                &e.body,
3507                tokens,
3508                fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump),
3509            );
3510        } else {
3511            token::Brace::default().surround(tokens, |tokens| {
3512                print_expr(&e.body, tokens, FixupContext::new_stmt());
3513            });
3514        }
3515    }
3516
3517    #[cfg(feature = "full")]
3518    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3519    impl ToTokens for ExprConst {
3520        fn to_tokens(&self, tokens: &mut TokenStream) {
3521            outer_attrs_to_tokens(&self.attrs, tokens);
3522            self.const_token.to_tokens(tokens);
3523            self.block.brace_token.surround(tokens, |tokens| {
3524                inner_attrs_to_tokens(&self.attrs, tokens);
3525                tokens.append_all(&self.block.stmts);
3526            });
3527        }
3528    }
3529
3530    #[cfg(feature = "full")]
3531    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3532    impl ToTokens for ExprContinue {
3533        fn to_tokens(&self, tokens: &mut TokenStream) {
3534            outer_attrs_to_tokens(&self.attrs, tokens);
3535            self.continue_token.to_tokens(tokens);
3536            self.label.to_tokens(tokens);
3537        }
3538    }
3539
3540    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3541    impl ToTokens for ExprField {
3542        fn to_tokens(&self, tokens: &mut TokenStream) {
3543            print_expr_field(self, tokens, FixupContext::NONE);
3544        }
3545    }
3546
3547    fn print_expr_field(e: &ExprField, tokens: &mut TokenStream, fixup: FixupContext) {
3548        outer_attrs_to_tokens(&e.attrs, tokens);
3549        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.base);
3550        print_subexpression(
3551            &e.base,
3552            left_prec < Precedence::Unambiguous,
3553            tokens,
3554            left_fixup,
3555        );
3556        e.dot_token.to_tokens(tokens);
3557        e.member.to_tokens(tokens);
3558    }
3559
3560    #[cfg(feature = "full")]
3561    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3562    impl ToTokens for ExprForLoop {
3563        fn to_tokens(&self, tokens: &mut TokenStream) {
3564            outer_attrs_to_tokens(&self.attrs, tokens);
3565            self.label.to_tokens(tokens);
3566            self.for_token.to_tokens(tokens);
3567            self.pat.to_tokens(tokens);
3568            self.in_token.to_tokens(tokens);
3569            print_expr(&self.expr, tokens, FixupContext::new_condition());
3570            self.body.brace_token.surround(tokens, |tokens| {
3571                inner_attrs_to_tokens(&self.attrs, tokens);
3572                tokens.append_all(&self.body.stmts);
3573            });
3574        }
3575    }
3576
3577    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3578    impl ToTokens for ExprGroup {
3579        fn to_tokens(&self, tokens: &mut TokenStream) {
3580            outer_attrs_to_tokens(&self.attrs, tokens);
3581            self.group_token.surround(tokens, |tokens| {
3582                self.expr.to_tokens(tokens);
3583            });
3584        }
3585    }
3586
3587    #[cfg(feature = "full")]
3588    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3589    impl ToTokens for ExprIf {
3590        fn to_tokens(&self, tokens: &mut TokenStream) {
3591            outer_attrs_to_tokens(&self.attrs, tokens);
3592
3593            let mut expr = self;
3594            loop {
3595                expr.if_token.to_tokens(tokens);
3596                print_expr(&expr.cond, tokens, FixupContext::new_condition());
3597                expr.then_branch.to_tokens(tokens);
3598
3599                let (else_token, else_) = match &expr.else_branch {
3600                    Some(else_branch) => else_branch,
3601                    None => break,
3602                };
3603
3604                else_token.to_tokens(tokens);
3605                match &**else_ {
3606                    Expr::If(next) => {
3607                        expr = next;
3608                    }
3609                    Expr::Block(last) => {
3610                        last.to_tokens(tokens);
3611                        break;
3612                    }
3613                    // If this is not one of the valid expressions to exist in
3614                    // an else clause, wrap it in a block.
3615                    other => {
3616                        token::Brace::default().surround(tokens, |tokens| {
3617                            print_expr(other, tokens, FixupContext::new_stmt());
3618                        });
3619                        break;
3620                    }
3621                }
3622            }
3623        }
3624    }
3625
3626    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3627    impl ToTokens for ExprIndex {
3628        fn to_tokens(&self, tokens: &mut TokenStream) {
3629            print_expr_index(self, tokens, FixupContext::NONE);
3630        }
3631    }
3632
3633    fn print_expr_index(e: &ExprIndex, tokens: &mut TokenStream, fixup: FixupContext) {
3634        outer_attrs_to_tokens(&e.attrs, tokens);
3635        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3636            &e.expr,
3637            #[cfg(feature = "full")]
3638            true,
3639            false,
3640            #[cfg(feature = "full")]
3641            Precedence::Unambiguous,
3642        );
3643        print_subexpression(
3644            &e.expr,
3645            left_prec < Precedence::Unambiguous,
3646            tokens,
3647            left_fixup,
3648        );
3649        e.bracket_token.surround(tokens, |tokens| {
3650            e.index.to_tokens(tokens);
3651        });
3652    }
3653
3654    #[cfg(feature = "full")]
3655    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3656    impl ToTokens for ExprInfer {
3657        fn to_tokens(&self, tokens: &mut TokenStream) {
3658            outer_attrs_to_tokens(&self.attrs, tokens);
3659            self.underscore_token.to_tokens(tokens);
3660        }
3661    }
3662
3663    #[cfg(feature = "full")]
3664    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3665    impl ToTokens for ExprLet {
3666        fn to_tokens(&self, tokens: &mut TokenStream) {
3667            print_expr_let(self, tokens, FixupContext::NONE);
3668        }
3669    }
3670
3671    #[cfg(feature = "full")]
3672    fn print_expr_let(e: &ExprLet, tokens: &mut TokenStream, fixup: FixupContext) {
3673        outer_attrs_to_tokens(&e.attrs, tokens);
3674        e.let_token.to_tokens(tokens);
3675        e.pat.to_tokens(tokens);
3676        e.eq_token.to_tokens(tokens);
3677        let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Let);
3678        print_subexpression(&e.expr, right_prec < Precedence::Let, tokens, right_fixup);
3679    }
3680
3681    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3682    impl ToTokens for ExprLit {
3683        fn to_tokens(&self, tokens: &mut TokenStream) {
3684            outer_attrs_to_tokens(&self.attrs, tokens);
3685            self.lit.to_tokens(tokens);
3686        }
3687    }
3688
3689    #[cfg(feature = "full")]
3690    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3691    impl ToTokens for ExprLoop {
3692        fn to_tokens(&self, tokens: &mut TokenStream) {
3693            outer_attrs_to_tokens(&self.attrs, tokens);
3694            self.label.to_tokens(tokens);
3695            self.loop_token.to_tokens(tokens);
3696            self.body.brace_token.surround(tokens, |tokens| {
3697                inner_attrs_to_tokens(&self.attrs, tokens);
3698                tokens.append_all(&self.body.stmts);
3699            });
3700        }
3701    }
3702
3703    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3704    impl ToTokens for ExprMacro {
3705        fn to_tokens(&self, tokens: &mut TokenStream) {
3706            outer_attrs_to_tokens(&self.attrs, tokens);
3707            self.mac.to_tokens(tokens);
3708        }
3709    }
3710
3711    #[cfg(feature = "full")]
3712    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3713    impl ToTokens for ExprMatch {
3714        fn to_tokens(&self, tokens: &mut TokenStream) {
3715            outer_attrs_to_tokens(&self.attrs, tokens);
3716            self.match_token.to_tokens(tokens);
3717            print_expr(&self.expr, tokens, FixupContext::new_condition());
3718            self.brace_token.surround(tokens, |tokens| {
3719                inner_attrs_to_tokens(&self.attrs, tokens);
3720                for (i, arm) in self.arms.iter().enumerate() {
3721                    arm.to_tokens(tokens);
3722                    // Ensure that we have a comma after a non-block arm, except
3723                    // for the last one.
3724                    let is_last = i == self.arms.len() - 1;
3725                    if !is_last
3726                        && classify::requires_comma_to_be_match_arm(&arm.body)
3727                        && arm.comma.is_none()
3728                    {
3729                        <Token![,]>::default().to_tokens(tokens);
3730                    }
3731                }
3732            });
3733        }
3734    }
3735
3736    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3737    impl ToTokens for ExprMethodCall {
3738        fn to_tokens(&self, tokens: &mut TokenStream) {
3739            print_expr_method_call(self, tokens, FixupContext::NONE);
3740        }
3741    }
3742
3743    fn print_expr_method_call(e: &ExprMethodCall, tokens: &mut TokenStream, fixup: FixupContext) {
3744        outer_attrs_to_tokens(&e.attrs, tokens);
3745        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.receiver);
3746        print_subexpression(
3747            &e.receiver,
3748            left_prec < Precedence::Unambiguous,
3749            tokens,
3750            left_fixup,
3751        );
3752        e.dot_token.to_tokens(tokens);
3753        e.method.to_tokens(tokens);
3754        if let Some(turbofish) = &e.turbofish {
3755            path::printing::print_angle_bracketed_generic_arguments(
3756                tokens,
3757                turbofish,
3758                PathStyle::Expr,
3759            );
3760        }
3761        e.paren_token.surround(tokens, |tokens| {
3762            e.args.to_tokens(tokens);
3763        });
3764    }
3765
3766    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3767    impl ToTokens for ExprParen {
3768        fn to_tokens(&self, tokens: &mut TokenStream) {
3769            outer_attrs_to_tokens(&self.attrs, tokens);
3770            self.paren_token.surround(tokens, |tokens| {
3771                self.expr.to_tokens(tokens);
3772            });
3773        }
3774    }
3775
3776    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3777    impl ToTokens for ExprPath {
3778        fn to_tokens(&self, tokens: &mut TokenStream) {
3779            outer_attrs_to_tokens(&self.attrs, tokens);
3780            path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
3781        }
3782    }
3783
3784    #[cfg(feature = "full")]
3785    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3786    impl ToTokens for ExprRange {
3787        fn to_tokens(&self, tokens: &mut TokenStream) {
3788            print_expr_range(self, tokens, FixupContext::NONE);
3789        }
3790    }
3791
3792    #[cfg(feature = "full")]
3793    fn print_expr_range(e: &ExprRange, tokens: &mut TokenStream, fixup: FixupContext) {
3794        outer_attrs_to_tokens(&e.attrs, tokens);
3795        if let Some(start) = &e.start {
3796            let (left_prec, left_fixup) =
3797                fixup.leftmost_subexpression_with_operator(start, true, false, Precedence::Range);
3798            print_subexpression(start, left_prec <= Precedence::Range, tokens, left_fixup);
3799        }
3800        e.limits.to_tokens(tokens);
3801        if let Some(end) = &e.end {
3802            let right_fixup = fixup.rightmost_subexpression_fixup(false, true, Precedence::Range);
3803            let right_prec = right_fixup.rightmost_subexpression_precedence(end);
3804            print_subexpression(end, right_prec <= Precedence::Range, tokens, right_fixup);
3805        }
3806    }
3807
3808    #[cfg(feature = "full")]
3809    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3810    impl ToTokens for ExprRawAddr {
3811        fn to_tokens(&self, tokens: &mut TokenStream) {
3812            print_expr_raw_addr(self, tokens, FixupContext::NONE);
3813        }
3814    }
3815
3816    #[cfg(feature = "full")]
3817    fn print_expr_raw_addr(e: &ExprRawAddr, tokens: &mut TokenStream, fixup: FixupContext) {
3818        outer_attrs_to_tokens(&e.attrs, tokens);
3819        e.and_token.to_tokens(tokens);
3820        e.raw.to_tokens(tokens);
3821        e.mutability.to_tokens(tokens);
3822        let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Prefix);
3823        print_subexpression(
3824            &e.expr,
3825            right_prec < Precedence::Prefix,
3826            tokens,
3827            right_fixup,
3828        );
3829    }
3830
3831    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3832    impl ToTokens for ExprReference {
3833        fn to_tokens(&self, tokens: &mut TokenStream) {
3834            print_expr_reference(self, tokens, FixupContext::NONE);
3835        }
3836    }
3837
3838    fn print_expr_reference(e: &ExprReference, tokens: &mut TokenStream, fixup: FixupContext) {
3839        outer_attrs_to_tokens(&e.attrs, tokens);
3840        e.and_token.to_tokens(tokens);
3841        e.mutability.to_tokens(tokens);
3842        let (right_prec, right_fixup) = fixup.rightmost_subexpression(
3843            &e.expr,
3844            #[cfg(feature = "full")]
3845            Precedence::Prefix,
3846        );
3847        print_subexpression(
3848            &e.expr,
3849            right_prec < Precedence::Prefix,
3850            tokens,
3851            right_fixup,
3852        );
3853    }
3854
3855    #[cfg(feature = "full")]
3856    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3857    impl ToTokens for ExprRepeat {
3858        fn to_tokens(&self, tokens: &mut TokenStream) {
3859            outer_attrs_to_tokens(&self.attrs, tokens);
3860            self.bracket_token.surround(tokens, |tokens| {
3861                self.expr.to_tokens(tokens);
3862                self.semi_token.to_tokens(tokens);
3863                self.len.to_tokens(tokens);
3864            });
3865        }
3866    }
3867
3868    #[cfg(feature = "full")]
3869    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3870    impl ToTokens for ExprReturn {
3871        fn to_tokens(&self, tokens: &mut TokenStream) {
3872            print_expr_return(self, tokens, FixupContext::NONE);
3873        }
3874    }
3875
3876    #[cfg(feature = "full")]
3877    fn print_expr_return(e: &ExprReturn, tokens: &mut TokenStream, fixup: FixupContext) {
3878        outer_attrs_to_tokens(&e.attrs, tokens);
3879        e.return_token.to_tokens(tokens);
3880        if let Some(expr) = &e.expr {
3881            print_expr(
3882                expr,
3883                tokens,
3884                fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
3885            );
3886        }
3887    }
3888
3889    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3890    impl ToTokens for ExprStruct {
3891        fn to_tokens(&self, tokens: &mut TokenStream) {
3892            outer_attrs_to_tokens(&self.attrs, tokens);
3893            path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
3894            self.brace_token.surround(tokens, |tokens| {
3895                self.fields.to_tokens(tokens);
3896                if let Some(dot2_token) = &self.dot2_token {
3897                    dot2_token.to_tokens(tokens);
3898                } else if self.rest.is_some() {
3899                    Token![..](Span::call_site()).to_tokens(tokens);
3900                }
3901                self.rest.to_tokens(tokens);
3902            });
3903        }
3904    }
3905
3906    #[cfg(feature = "full")]
3907    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3908    impl ToTokens for ExprTry {
3909        fn to_tokens(&self, tokens: &mut TokenStream) {
3910            print_expr_try(self, tokens, FixupContext::NONE);
3911        }
3912    }
3913
3914    #[cfg(feature = "full")]
3915    fn print_expr_try(e: &ExprTry, tokens: &mut TokenStream, fixup: FixupContext) {
3916        outer_attrs_to_tokens(&e.attrs, tokens);
3917        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.expr);
3918        print_subexpression(
3919            &e.expr,
3920            left_prec < Precedence::Unambiguous,
3921            tokens,
3922            left_fixup,
3923        );
3924        e.question_token.to_tokens(tokens);
3925    }
3926
3927    #[cfg(feature = "full")]
3928    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3929    impl ToTokens for ExprTryBlock {
3930        fn to_tokens(&self, tokens: &mut TokenStream) {
3931            outer_attrs_to_tokens(&self.attrs, tokens);
3932            self.try_token.to_tokens(tokens);
3933            self.block.to_tokens(tokens);
3934        }
3935    }
3936
3937    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3938    impl ToTokens for ExprTuple {
3939        fn to_tokens(&self, tokens: &mut TokenStream) {
3940            outer_attrs_to_tokens(&self.attrs, tokens);
3941            self.paren_token.surround(tokens, |tokens| {
3942                self.elems.to_tokens(tokens);
3943                // If we only have one argument, we need a trailing comma to
3944                // distinguish ExprTuple from ExprParen.
3945                if self.elems.len() == 1 && !self.elems.trailing_punct() {
3946                    <Token![,]>::default().to_tokens(tokens);
3947                }
3948            });
3949        }
3950    }
3951
3952    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3953    impl ToTokens for ExprUnary {
3954        fn to_tokens(&self, tokens: &mut TokenStream) {
3955            print_expr_unary(self, tokens, FixupContext::NONE);
3956        }
3957    }
3958
3959    fn print_expr_unary(e: &ExprUnary, tokens: &mut TokenStream, fixup: FixupContext) {
3960        outer_attrs_to_tokens(&e.attrs, tokens);
3961        e.op.to_tokens(tokens);
3962        let (right_prec, right_fixup) = fixup.rightmost_subexpression(
3963            &e.expr,
3964            #[cfg(feature = "full")]
3965            Precedence::Prefix,
3966        );
3967        print_subexpression(
3968            &e.expr,
3969            right_prec < Precedence::Prefix,
3970            tokens,
3971            right_fixup,
3972        );
3973    }
3974
3975    #[cfg(feature = "full")]
3976    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3977    impl ToTokens for ExprUnsafe {
3978        fn to_tokens(&self, tokens: &mut TokenStream) {
3979            outer_attrs_to_tokens(&self.attrs, tokens);
3980            self.unsafe_token.to_tokens(tokens);
3981            self.block.brace_token.surround(tokens, |tokens| {
3982                inner_attrs_to_tokens(&self.attrs, tokens);
3983                tokens.append_all(&self.block.stmts);
3984            });
3985        }
3986    }
3987
3988    #[cfg(feature = "full")]
3989    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3990    impl ToTokens for ExprWhile {
3991        fn to_tokens(&self, tokens: &mut TokenStream) {
3992            outer_attrs_to_tokens(&self.attrs, tokens);
3993            self.label.to_tokens(tokens);
3994            self.while_token.to_tokens(tokens);
3995            print_expr(&self.cond, tokens, FixupContext::new_condition());
3996            self.body.brace_token.surround(tokens, |tokens| {
3997                inner_attrs_to_tokens(&self.attrs, tokens);
3998                tokens.append_all(&self.body.stmts);
3999            });
4000        }
4001    }
4002
4003    #[cfg(feature = "full")]
4004    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4005    impl ToTokens for ExprYield {
4006        fn to_tokens(&self, tokens: &mut TokenStream) {
4007            print_expr_yield(self, tokens, FixupContext::NONE);
4008        }
4009    }
4010
4011    #[cfg(feature = "full")]
4012    fn print_expr_yield(e: &ExprYield, tokens: &mut TokenStream, fixup: FixupContext) {
4013        outer_attrs_to_tokens(&e.attrs, tokens);
4014        e.yield_token.to_tokens(tokens);
4015        if let Some(expr) = &e.expr {
4016            print_expr(
4017                expr,
4018                tokens,
4019                fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
4020            );
4021        }
4022    }
4023
4024    #[cfg(feature = "full")]
4025    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4026    impl ToTokens for Arm {
4027        fn to_tokens(&self, tokens: &mut TokenStream) {
4028            tokens.append_all(&self.attrs);
4029            self.pat.to_tokens(tokens);
4030            if let Some((if_token, guard)) = &self.guard {
4031                if_token.to_tokens(tokens);
4032                guard.to_tokens(tokens);
4033            }
4034            self.fat_arrow_token.to_tokens(tokens);
4035            print_expr(&self.body, tokens, FixupContext::new_match_arm());
4036            self.comma.to_tokens(tokens);
4037        }
4038    }
4039
4040    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4041    impl ToTokens for FieldValue {
4042        fn to_tokens(&self, tokens: &mut TokenStream) {
4043            outer_attrs_to_tokens(&self.attrs, tokens);
4044            self.member.to_tokens(tokens);
4045            if let Some(colon_token) = &self.colon_token {
4046                colon_token.to_tokens(tokens);
4047                self.expr.to_tokens(tokens);
4048            }
4049        }
4050    }
4051
4052    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4053    impl ToTokens for Index {
4054        fn to_tokens(&self, tokens: &mut TokenStream) {
4055            let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
4056            lit.set_span(self.span);
4057            tokens.append(lit);
4058        }
4059    }
4060
4061    #[cfg(feature = "full")]
4062    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4063    impl ToTokens for Label {
4064        fn to_tokens(&self, tokens: &mut TokenStream) {
4065            self.name.to_tokens(tokens);
4066            self.colon_token.to_tokens(tokens);
4067        }
4068    }
4069
4070    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4071    impl ToTokens for Member {
4072        fn to_tokens(&self, tokens: &mut TokenStream) {
4073            match self {
4074                Member::Named(ident) => ident.to_tokens(tokens),
4075                Member::Unnamed(index) => index.to_tokens(tokens),
4076            }
4077        }
4078    }
4079
4080    #[cfg(feature = "full")]
4081    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4082    impl ToTokens for RangeLimits {
4083        fn to_tokens(&self, tokens: &mut TokenStream) {
4084            match self {
4085                RangeLimits::HalfOpen(t) => t.to_tokens(tokens),
4086                RangeLimits::Closed(t) => t.to_tokens(tokens),
4087            }
4088        }
4089    }
4090
4091    #[cfg(feature = "full")]
4092    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4093    impl ToTokens for PointerMutability {
4094        fn to_tokens(&self, tokens: &mut TokenStream) {
4095            match self {
4096                PointerMutability::Const(const_token) => const_token.to_tokens(tokens),
4097                PointerMutability::Mut(mut_token) => mut_token.to_tokens(tokens),
4098            }
4099        }
4100    }
4101}