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                    continue;
2247                } else if lookahead.peek(token::Brace) {
2248                    expr.else_branch = Some((
2249                        else_token,
2250                        Box::new(Expr::Block(ExprBlock {
2251                            attrs: Vec::new(),
2252                            label: None,
2253                            block: input.parse()?,
2254                        })),
2255                    ));
2256                    break;
2257                } else {
2258                    return Err(lookahead.error());
2259                }
2260            }
2261
2262            while let Some(mut prev) = clauses.pop() {
2263                *prev.else_branch.as_mut().unwrap().1 = Expr::If(expr);
2264                expr = prev;
2265            }
2266            expr.attrs = attrs;
2267            Ok(expr)
2268        }
2269    }
2270
2271    #[cfg(feature = "full")]
2272    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2273    impl Parse for ExprInfer {
2274        fn parse(input: ParseStream) -> Result<Self> {
2275            Ok(ExprInfer {
2276                attrs: input.call(Attribute::parse_outer)?,
2277                underscore_token: input.parse()?,
2278            })
2279        }
2280    }
2281
2282    #[cfg(feature = "full")]
2283    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2284    impl Parse for ExprForLoop {
2285        fn parse(input: ParseStream) -> Result<Self> {
2286            let mut attrs = input.call(Attribute::parse_outer)?;
2287            let label: Option<Label> = input.parse()?;
2288            let for_token: Token![for] = input.parse()?;
2289
2290            let pat = Pat::parse_multi_with_leading_vert(input)?;
2291
2292            let in_token: Token![in] = input.parse()?;
2293            let expr: Expr = input.call(Expr::parse_without_eager_brace)?;
2294
2295            let content;
2296            let brace_token = braced!(content in input);
2297            attr::parsing::parse_inner(&content, &mut attrs)?;
2298            let stmts = content.call(Block::parse_within)?;
2299
2300            Ok(ExprForLoop {
2301                attrs,
2302                label,
2303                for_token,
2304                pat: Box::new(pat),
2305                in_token,
2306                expr: Box::new(expr),
2307                body: Block { brace_token, stmts },
2308            })
2309        }
2310    }
2311
2312    #[cfg(feature = "full")]
2313    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2314    impl Parse for ExprLoop {
2315        fn parse(input: ParseStream) -> Result<Self> {
2316            let mut attrs = input.call(Attribute::parse_outer)?;
2317            let label: Option<Label> = input.parse()?;
2318            let loop_token: Token![loop] = input.parse()?;
2319
2320            let content;
2321            let brace_token = braced!(content in input);
2322            attr::parsing::parse_inner(&content, &mut attrs)?;
2323            let stmts = content.call(Block::parse_within)?;
2324
2325            Ok(ExprLoop {
2326                attrs,
2327                label,
2328                loop_token,
2329                body: Block { brace_token, stmts },
2330            })
2331        }
2332    }
2333
2334    #[cfg(feature = "full")]
2335    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2336    impl Parse for ExprMatch {
2337        fn parse(input: ParseStream) -> Result<Self> {
2338            let mut attrs = input.call(Attribute::parse_outer)?;
2339            let match_token: Token![match] = input.parse()?;
2340            let expr = Expr::parse_without_eager_brace(input)?;
2341
2342            let content;
2343            let brace_token = braced!(content in input);
2344            attr::parsing::parse_inner(&content, &mut attrs)?;
2345
2346            let arms = Arm::parse_multiple(&content)?;
2347
2348            Ok(ExprMatch {
2349                attrs,
2350                match_token,
2351                expr: Box::new(expr),
2352                brace_token,
2353                arms,
2354            })
2355        }
2356    }
2357
2358    macro_rules! impl_by_parsing_expr {
2359        (
2360            $(
2361                $expr_type:ty, $variant:ident, $msg:expr,
2362            )*
2363        ) => {
2364            $(
2365                #[cfg(all(feature = "full", feature = "printing"))]
2366                #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2367                impl Parse for $expr_type {
2368                    fn parse(input: ParseStream) -> Result<Self> {
2369                        let mut expr: Expr = input.parse()?;
2370                        loop {
2371                            match expr {
2372                                Expr::$variant(inner) => return Ok(inner),
2373                                Expr::Group(next) => expr = *next.expr,
2374                                _ => return Err(Error::new_spanned(expr, $msg)),
2375                            }
2376                        }
2377                    }
2378                }
2379            )*
2380        };
2381    }
2382
2383    impl_by_parsing_expr! {
2384        ExprAssign, Assign, "expected assignment expression",
2385        ExprAwait, Await, "expected await expression",
2386        ExprBinary, Binary, "expected binary operation",
2387        ExprCall, Call, "expected function call expression",
2388        ExprCast, Cast, "expected cast expression",
2389        ExprField, Field, "expected struct field access",
2390        ExprIndex, Index, "expected indexing expression",
2391        ExprMethodCall, MethodCall, "expected method call expression",
2392        ExprRange, Range, "expected range expression",
2393        ExprTry, Try, "expected try expression",
2394        ExprTuple, Tuple, "expected tuple expression",
2395    }
2396
2397    #[cfg(feature = "full")]
2398    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2399    impl Parse for ExprUnary {
2400        fn parse(input: ParseStream) -> Result<Self> {
2401            let attrs = Vec::new();
2402            let allow_struct = AllowStruct(true);
2403            expr_unary(input, attrs, allow_struct)
2404        }
2405    }
2406
2407    #[cfg(feature = "full")]
2408    fn expr_unary(
2409        input: ParseStream,
2410        attrs: Vec<Attribute>,
2411        allow_struct: AllowStruct,
2412    ) -> Result<ExprUnary> {
2413        Ok(ExprUnary {
2414            attrs,
2415            op: input.parse()?,
2416            expr: Box::new(unary_expr(input, allow_struct)?),
2417        })
2418    }
2419
2420    #[cfg(feature = "full")]
2421    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2422    impl Parse for ExprClosure {
2423        fn parse(input: ParseStream) -> Result<Self> {
2424            let allow_struct = AllowStruct(true);
2425            expr_closure(input, allow_struct)
2426        }
2427    }
2428
2429    #[cfg(feature = "full")]
2430    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2431    impl Parse for ExprRawAddr {
2432        fn parse(input: ParseStream) -> Result<Self> {
2433            let allow_struct = AllowStruct(true);
2434            Ok(ExprRawAddr {
2435                attrs: Vec::new(),
2436                and_token: input.parse()?,
2437                raw: input.parse()?,
2438                mutability: input.parse()?,
2439                expr: Box::new(unary_expr(input, allow_struct)?),
2440            })
2441        }
2442    }
2443
2444    #[cfg(feature = "full")]
2445    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2446    impl Parse for ExprReference {
2447        fn parse(input: ParseStream) -> Result<Self> {
2448            let allow_struct = AllowStruct(true);
2449            Ok(ExprReference {
2450                attrs: Vec::new(),
2451                and_token: input.parse()?,
2452                mutability: input.parse()?,
2453                expr: Box::new(unary_expr(input, allow_struct)?),
2454            })
2455        }
2456    }
2457
2458    #[cfg(feature = "full")]
2459    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2460    impl Parse for ExprBreak {
2461        fn parse(input: ParseStream) -> Result<Self> {
2462            let allow_struct = AllowStruct(true);
2463            expr_break(input, allow_struct)
2464        }
2465    }
2466
2467    #[cfg(feature = "full")]
2468    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2469    impl Parse for ExprReturn {
2470        fn parse(input: ParseStream) -> Result<Self> {
2471            Ok(ExprReturn {
2472                attrs: Vec::new(),
2473                return_token: input.parse()?,
2474                expr: {
2475                    if Expr::peek(input) {
2476                        Some(input.parse()?)
2477                    } else {
2478                        None
2479                    }
2480                },
2481            })
2482        }
2483    }
2484
2485    #[cfg(feature = "full")]
2486    fn expr_become(input: ParseStream) -> Result<Expr> {
2487        let begin = input.fork();
2488        input.parse::<Token![become]>()?;
2489        input.parse::<Expr>()?;
2490        Ok(Expr::Verbatim(verbatim::between(&begin, input)))
2491    }
2492
2493    #[cfg(feature = "full")]
2494    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2495    impl Parse for ExprTryBlock {
2496        fn parse(input: ParseStream) -> Result<Self> {
2497            Ok(ExprTryBlock {
2498                attrs: Vec::new(),
2499                try_token: input.parse()?,
2500                block: input.parse()?,
2501            })
2502        }
2503    }
2504
2505    #[cfg(feature = "full")]
2506    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2507    impl Parse for ExprYield {
2508        fn parse(input: ParseStream) -> Result<Self> {
2509            Ok(ExprYield {
2510                attrs: Vec::new(),
2511                yield_token: input.parse()?,
2512                expr: {
2513                    if Expr::peek(input) {
2514                        Some(input.parse()?)
2515                    } else {
2516                        None
2517                    }
2518                },
2519            })
2520        }
2521    }
2522
2523    #[cfg(feature = "full")]
2524    fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
2525        let lifetimes: Option<BoundLifetimes> = input.parse()?;
2526        let constness: Option<Token![const]> = input.parse()?;
2527        let movability: Option<Token![static]> = input.parse()?;
2528        let asyncness: Option<Token![async]> = input.parse()?;
2529        let capture: Option<Token![move]> = input.parse()?;
2530        let or1_token: Token![|] = input.parse()?;
2531
2532        let mut inputs = Punctuated::new();
2533        loop {
2534            if input.peek(Token![|]) {
2535                break;
2536            }
2537            let value = closure_arg(input)?;
2538            inputs.push_value(value);
2539            if input.peek(Token![|]) {
2540                break;
2541            }
2542            let punct: Token![,] = input.parse()?;
2543            inputs.push_punct(punct);
2544        }
2545
2546        let or2_token: Token![|] = input.parse()?;
2547
2548        let (output, body) = if input.peek(Token![->]) {
2549            let arrow_token: Token![->] = input.parse()?;
2550            let ty: Type = input.parse()?;
2551            let body: Block = input.parse()?;
2552            let output = ReturnType::Type(arrow_token, Box::new(ty));
2553            let block = Expr::Block(ExprBlock {
2554                attrs: Vec::new(),
2555                label: None,
2556                block: body,
2557            });
2558            (output, block)
2559        } else {
2560            let body = ambiguous_expr(input, allow_struct)?;
2561            (ReturnType::Default, body)
2562        };
2563
2564        Ok(ExprClosure {
2565            attrs: Vec::new(),
2566            lifetimes,
2567            constness,
2568            movability,
2569            asyncness,
2570            capture,
2571            or1_token,
2572            inputs,
2573            or2_token,
2574            output,
2575            body: Box::new(body),
2576        })
2577    }
2578
2579    #[cfg(feature = "full")]
2580    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2581    impl Parse for ExprAsync {
2582        fn parse(input: ParseStream) -> Result<Self> {
2583            Ok(ExprAsync {
2584                attrs: Vec::new(),
2585                async_token: input.parse()?,
2586                capture: input.parse()?,
2587                block: input.parse()?,
2588            })
2589        }
2590    }
2591
2592    #[cfg(feature = "full")]
2593    fn closure_arg(input: ParseStream) -> Result<Pat> {
2594        let attrs = input.call(Attribute::parse_outer)?;
2595        let mut pat = Pat::parse_single(input)?;
2596
2597        if input.peek(Token![:]) {
2598            Ok(Pat::Type(PatType {
2599                attrs,
2600                pat: Box::new(pat),
2601                colon_token: input.parse()?,
2602                ty: input.parse()?,
2603            }))
2604        } else {
2605            match &mut pat {
2606                Pat::Const(pat) => pat.attrs = attrs,
2607                Pat::Ident(pat) => pat.attrs = attrs,
2608                Pat::Lit(pat) => pat.attrs = attrs,
2609                Pat::Macro(pat) => pat.attrs = attrs,
2610                Pat::Or(pat) => pat.attrs = attrs,
2611                Pat::Paren(pat) => pat.attrs = attrs,
2612                Pat::Path(pat) => pat.attrs = attrs,
2613                Pat::Range(pat) => pat.attrs = attrs,
2614                Pat::Reference(pat) => pat.attrs = attrs,
2615                Pat::Rest(pat) => pat.attrs = attrs,
2616                Pat::Slice(pat) => pat.attrs = attrs,
2617                Pat::Struct(pat) => pat.attrs = attrs,
2618                Pat::Tuple(pat) => pat.attrs = attrs,
2619                Pat::TupleStruct(pat) => pat.attrs = attrs,
2620                Pat::Type(_) => unreachable!(),
2621                Pat::Verbatim(_) => {}
2622                Pat::Wild(pat) => pat.attrs = attrs,
2623            }
2624            Ok(pat)
2625        }
2626    }
2627
2628    #[cfg(feature = "full")]
2629    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2630    impl Parse for ExprWhile {
2631        fn parse(input: ParseStream) -> Result<Self> {
2632            let mut attrs = input.call(Attribute::parse_outer)?;
2633            let label: Option<Label> = input.parse()?;
2634            let while_token: Token![while] = input.parse()?;
2635            let cond = Expr::parse_without_eager_brace(input)?;
2636
2637            let content;
2638            let brace_token = braced!(content in input);
2639            attr::parsing::parse_inner(&content, &mut attrs)?;
2640            let stmts = content.call(Block::parse_within)?;
2641
2642            Ok(ExprWhile {
2643                attrs,
2644                label,
2645                while_token,
2646                cond: Box::new(cond),
2647                body: Block { brace_token, stmts },
2648            })
2649        }
2650    }
2651
2652    #[cfg(feature = "full")]
2653    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2654    impl Parse for ExprConst {
2655        fn parse(input: ParseStream) -> Result<Self> {
2656            let const_token: Token![const] = input.parse()?;
2657
2658            let content;
2659            let brace_token = braced!(content in input);
2660            let inner_attrs = content.call(Attribute::parse_inner)?;
2661            let stmts = content.call(Block::parse_within)?;
2662
2663            Ok(ExprConst {
2664                attrs: inner_attrs,
2665                const_token,
2666                block: Block { brace_token, stmts },
2667            })
2668        }
2669    }
2670
2671    #[cfg(feature = "full")]
2672    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2673    impl Parse for Label {
2674        fn parse(input: ParseStream) -> Result<Self> {
2675            Ok(Label {
2676                name: input.parse()?,
2677                colon_token: input.parse()?,
2678            })
2679        }
2680    }
2681
2682    #[cfg(feature = "full")]
2683    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2684    impl Parse for Option<Label> {
2685        fn parse(input: ParseStream) -> Result<Self> {
2686            if input.peek(Lifetime) {
2687                input.parse().map(Some)
2688            } else {
2689                Ok(None)
2690            }
2691        }
2692    }
2693
2694    #[cfg(feature = "full")]
2695    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2696    impl Parse for ExprContinue {
2697        fn parse(input: ParseStream) -> Result<Self> {
2698            Ok(ExprContinue {
2699                attrs: Vec::new(),
2700                continue_token: input.parse()?,
2701                label: input.parse()?,
2702            })
2703        }
2704    }
2705
2706    #[cfg(feature = "full")]
2707    fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2708        let break_token: Token![break] = input.parse()?;
2709
2710        let ahead = input.fork();
2711        let label: Option<Lifetime> = ahead.parse()?;
2712        if label.is_some() && ahead.peek(Token![:]) {
2713            // Not allowed: `break 'label: loop {...}`
2714            // Parentheses are required. `break ('label: loop {...})`
2715            let _: Expr = input.parse()?;
2716            let start_span = label.unwrap().apostrophe;
2717            let end_span = input.cursor().prev_span();
2718            return Err(crate::error::new2(
2719                start_span,
2720                end_span,
2721                "parentheses required",
2722            ));
2723        }
2724
2725        input.advance_to(&ahead);
2726        let expr = if Expr::peek(input) && (allow_struct.0 || !input.peek(token::Brace)) {
2727            Some(input.parse()?)
2728        } else {
2729            None
2730        };
2731
2732        Ok(ExprBreak {
2733            attrs: Vec::new(),
2734            break_token,
2735            label,
2736            expr,
2737        })
2738    }
2739
2740    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2741    impl Parse for FieldValue {
2742        fn parse(input: ParseStream) -> Result<Self> {
2743            let attrs = input.call(Attribute::parse_outer)?;
2744            let member: Member = input.parse()?;
2745            let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
2746                let colon_token: Token![:] = input.parse()?;
2747                let value: Expr = input.parse()?;
2748                (Some(colon_token), value)
2749            } else if let Member::Named(ident) = &member {
2750                let value = Expr::Path(ExprPath {
2751                    attrs: Vec::new(),
2752                    qself: None,
2753                    path: Path::from(ident.clone()),
2754                });
2755                (None, value)
2756            } else {
2757                unreachable!()
2758            };
2759
2760            Ok(FieldValue {
2761                attrs,
2762                member,
2763                colon_token,
2764                expr: value,
2765            })
2766        }
2767    }
2768
2769    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2770    impl Parse for ExprStruct {
2771        fn parse(input: ParseStream) -> Result<Self> {
2772            let expr_style = true;
2773            let (qself, path) = path::parsing::qpath(input, expr_style)?;
2774            expr_struct_helper(input, qself, path)
2775        }
2776    }
2777
2778    fn expr_struct_helper(
2779        input: ParseStream,
2780        qself: Option<QSelf>,
2781        path: Path,
2782    ) -> Result<ExprStruct> {
2783        let content;
2784        let brace_token = braced!(content in input);
2785
2786        let mut fields = Punctuated::new();
2787        while !content.is_empty() {
2788            if content.peek(Token![..]) {
2789                return Ok(ExprStruct {
2790                    attrs: Vec::new(),
2791                    qself,
2792                    path,
2793                    brace_token,
2794                    fields,
2795                    dot2_token: Some(content.parse()?),
2796                    rest: if content.is_empty() {
2797                        None
2798                    } else {
2799                        Some(Box::new(content.parse()?))
2800                    },
2801                });
2802            }
2803
2804            fields.push(content.parse()?);
2805            if content.is_empty() {
2806                break;
2807            }
2808            let punct: Token![,] = content.parse()?;
2809            fields.push_punct(punct);
2810        }
2811
2812        Ok(ExprStruct {
2813            attrs: Vec::new(),
2814            qself,
2815            path,
2816            brace_token,
2817            fields,
2818            dot2_token: None,
2819            rest: None,
2820        })
2821    }
2822
2823    #[cfg(feature = "full")]
2824    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2825    impl Parse for ExprUnsafe {
2826        fn parse(input: ParseStream) -> Result<Self> {
2827            let unsafe_token: Token![unsafe] = input.parse()?;
2828
2829            let content;
2830            let brace_token = braced!(content in input);
2831            let inner_attrs = content.call(Attribute::parse_inner)?;
2832            let stmts = content.call(Block::parse_within)?;
2833
2834            Ok(ExprUnsafe {
2835                attrs: inner_attrs,
2836                unsafe_token,
2837                block: Block { brace_token, stmts },
2838            })
2839        }
2840    }
2841
2842    #[cfg(feature = "full")]
2843    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2844    impl Parse for ExprBlock {
2845        fn parse(input: ParseStream) -> Result<Self> {
2846            let mut attrs = input.call(Attribute::parse_outer)?;
2847            let label: Option<Label> = input.parse()?;
2848
2849            let content;
2850            let brace_token = braced!(content in input);
2851            attr::parsing::parse_inner(&content, &mut attrs)?;
2852            let stmts = content.call(Block::parse_within)?;
2853
2854            Ok(ExprBlock {
2855                attrs,
2856                label,
2857                block: Block { brace_token, stmts },
2858            })
2859        }
2860    }
2861
2862    #[cfg(feature = "full")]
2863    fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2864        let limits: RangeLimits = input.parse()?;
2865        let end = parse_range_end(input, &limits, allow_struct)?;
2866        Ok(ExprRange {
2867            attrs: Vec::new(),
2868            start: None,
2869            limits,
2870            end,
2871        })
2872    }
2873
2874    #[cfg(feature = "full")]
2875    fn parse_range_end(
2876        input: ParseStream,
2877        limits: &RangeLimits,
2878        allow_struct: AllowStruct,
2879    ) -> Result<Option<Box<Expr>>> {
2880        if matches!(limits, RangeLimits::HalfOpen(_))
2881            && (input.is_empty()
2882                || input.peek(Token![,])
2883                || input.peek(Token![;])
2884                || input.peek(Token![.]) && !input.peek(Token![..])
2885                || input.peek(Token![?])
2886                || input.peek(Token![=>])
2887                || !allow_struct.0 && input.peek(token::Brace)
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![<<=])
2901                || input.peek(Token![as]))
2902        {
2903            Ok(None)
2904        } else {
2905            let end = parse_binop_rhs(input, allow_struct, Precedence::Range)?;
2906            Ok(Some(end))
2907        }
2908    }
2909
2910    #[cfg(feature = "full")]
2911    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2912    impl Parse for RangeLimits {
2913        fn parse(input: ParseStream) -> Result<Self> {
2914            let lookahead = input.lookahead1();
2915            let dot_dot = lookahead.peek(Token![..]);
2916            let dot_dot_eq = dot_dot && lookahead.peek(Token![..=]);
2917            let dot_dot_dot = dot_dot && input.peek(Token![...]);
2918            if dot_dot_eq {
2919                input.parse().map(RangeLimits::Closed)
2920            } else if dot_dot && !dot_dot_dot {
2921                input.parse().map(RangeLimits::HalfOpen)
2922            } else {
2923                Err(lookahead.error())
2924            }
2925        }
2926    }
2927
2928    #[cfg(feature = "full")]
2929    impl RangeLimits {
2930        pub(crate) fn parse_obsolete(input: ParseStream) -> Result<Self> {
2931            let lookahead = input.lookahead1();
2932            let dot_dot = lookahead.peek(Token![..]);
2933            let dot_dot_eq = dot_dot && lookahead.peek(Token![..=]);
2934            let dot_dot_dot = dot_dot && input.peek(Token![...]);
2935            if dot_dot_eq {
2936                input.parse().map(RangeLimits::Closed)
2937            } else if dot_dot_dot {
2938                let dot3: Token![...] = input.parse()?;
2939                Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2940            } else if dot_dot {
2941                input.parse().map(RangeLimits::HalfOpen)
2942            } else {
2943                Err(lookahead.error())
2944            }
2945        }
2946    }
2947
2948    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2949    impl Parse for ExprPath {
2950        fn parse(input: ParseStream) -> Result<Self> {
2951            #[cfg(not(feature = "full"))]
2952            let attrs = Vec::new();
2953            #[cfg(feature = "full")]
2954            let attrs = input.call(Attribute::parse_outer)?;
2955
2956            let expr_style = true;
2957            let (qself, path) = path::parsing::qpath(input, expr_style)?;
2958
2959            Ok(ExprPath { attrs, qself, path })
2960        }
2961    }
2962
2963    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2964    impl Parse for Member {
2965        fn parse(input: ParseStream) -> Result<Self> {
2966            if input.peek(Ident) {
2967                input.parse().map(Member::Named)
2968            } else if input.peek(LitInt) {
2969                input.parse().map(Member::Unnamed)
2970            } else {
2971                Err(input.error("expected identifier or integer"))
2972            }
2973        }
2974    }
2975
2976    #[cfg(feature = "full")]
2977    impl Arm {
2978        pub(crate) fn parse_multiple(input: ParseStream) -> Result<Vec<Self>> {
2979            let mut arms = Vec::new();
2980            while !input.is_empty() {
2981                arms.push(input.call(Arm::parse)?);
2982            }
2983            Ok(arms)
2984        }
2985    }
2986
2987    #[cfg(feature = "full")]
2988    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2989    impl Parse for Arm {
2990        fn parse(input: ParseStream) -> Result<Arm> {
2991            let requires_comma;
2992            Ok(Arm {
2993                attrs: input.call(Attribute::parse_outer)?,
2994                pat: Pat::parse_multi_with_leading_vert(input)?,
2995                guard: {
2996                    if input.peek(Token![if]) {
2997                        let if_token: Token![if] = input.parse()?;
2998                        let guard: Expr = input.parse()?;
2999                        Some((if_token, Box::new(guard)))
3000                    } else {
3001                        None
3002                    }
3003                },
3004                fat_arrow_token: input.parse()?,
3005                body: {
3006                    let body = Expr::parse_with_earlier_boundary_rule(input)?;
3007                    requires_comma = classify::requires_comma_to_be_match_arm(&body);
3008                    Box::new(body)
3009                },
3010                comma: {
3011                    if requires_comma && !input.is_empty() {
3012                        Some(input.parse()?)
3013                    } else {
3014                        input.parse()?
3015                    }
3016                },
3017            })
3018        }
3019    }
3020
3021    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3022    impl Parse for Index {
3023        fn parse(input: ParseStream) -> Result<Self> {
3024            let lit: LitInt = input.parse()?;
3025            if lit.suffix().is_empty() {
3026                Ok(Index {
3027                    index: lit
3028                        .base10_digits()
3029                        .parse()
3030                        .map_err(|err| Error::new(lit.span(), err))?,
3031                    span: lit.span(),
3032                })
3033            } else {
3034                Err(Error::new(lit.span(), "expected unsuffixed integer"))
3035            }
3036        }
3037    }
3038
3039    fn multi_index(e: &mut Expr, dot_token: &mut Token![.], float: LitFloat) -> Result<bool> {
3040        let float_token = float.token();
3041        let float_span = float_token.span();
3042        let mut float_repr = float_token.to_string();
3043        let trailing_dot = float_repr.ends_with('.');
3044        if trailing_dot {
3045            float_repr.truncate(float_repr.len() - 1);
3046        }
3047
3048        let mut offset = 0;
3049        for part in float_repr.split('.') {
3050            let mut index: Index =
3051                crate::parse_str(part).map_err(|err| Error::new(float_span, err))?;
3052            let part_end = offset + part.len();
3053            index.span = float_token.subspan(offset..part_end).unwrap_or(float_span);
3054
3055            let base = mem::replace(e, Expr::PLACEHOLDER);
3056            *e = Expr::Field(ExprField {
3057                attrs: Vec::new(),
3058                base: Box::new(base),
3059                dot_token: Token![.](dot_token.span),
3060                member: Member::Unnamed(index),
3061            });
3062
3063            let dot_span = float_token
3064                .subspan(part_end..part_end + 1)
3065                .unwrap_or(float_span);
3066            *dot_token = Token![.](dot_span);
3067            offset = part_end + 1;
3068        }
3069
3070        Ok(!trailing_dot)
3071    }
3072
3073    #[cfg(feature = "full")]
3074    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3075    impl Parse for PointerMutability {
3076        fn parse(input: ParseStream) -> Result<Self> {
3077            let lookahead = input.lookahead1();
3078            if lookahead.peek(Token![const]) {
3079                Ok(PointerMutability::Const(input.parse()?))
3080            } else if lookahead.peek(Token![mut]) {
3081                Ok(PointerMutability::Mut(input.parse()?))
3082            } else {
3083                Err(lookahead.error())
3084            }
3085        }
3086    }
3087
3088    fn check_cast(input: ParseStream) -> Result<()> {
3089        let kind = if input.peek(Token![.]) && !input.peek(Token![..]) {
3090            if input.peek2(Token![await]) {
3091                "`.await`"
3092            } else if input.peek2(Ident) && (input.peek3(token::Paren) || input.peek3(Token![::])) {
3093                "a method call"
3094            } else {
3095                "a field access"
3096            }
3097        } else if input.peek(Token![?]) {
3098            "`?`"
3099        } else if input.peek(token::Bracket) {
3100            "indexing"
3101        } else if input.peek(token::Paren) {
3102            "a function call"
3103        } else {
3104            return Ok(());
3105        };
3106        let msg = format!("casts cannot be followed by {}", kind);
3107        Err(input.error(msg))
3108    }
3109}
3110
3111#[cfg(feature = "printing")]
3112pub(crate) mod printing {
3113    use crate::attr::Attribute;
3114    #[cfg(feature = "full")]
3115    use crate::attr::FilterAttrs;
3116    #[cfg(feature = "full")]
3117    use crate::classify;
3118    #[cfg(feature = "full")]
3119    use crate::expr::{
3120        Arm, ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure,
3121        ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch,
3122        ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprUnsafe,
3123        ExprWhile, ExprYield, Label, PointerMutability, RangeLimits,
3124    };
3125    use crate::expr::{
3126        Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro,
3127        ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprTuple, ExprUnary,
3128        FieldValue, Index, Member,
3129    };
3130    use crate::fixup::FixupContext;
3131    use crate::op::BinOp;
3132    use crate::path;
3133    use crate::path::printing::PathStyle;
3134    use crate::precedence::Precedence;
3135    use crate::token;
3136    #[cfg(feature = "full")]
3137    use crate::ty::ReturnType;
3138    use proc_macro2::{Literal, Span, TokenStream};
3139    use quote::{ToTokens, TokenStreamExt};
3140
3141    #[cfg(feature = "full")]
3142    pub(crate) fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3143        tokens.append_all(attrs.outer());
3144    }
3145
3146    #[cfg(feature = "full")]
3147    fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3148        tokens.append_all(attrs.inner());
3149    }
3150
3151    #[cfg(not(feature = "full"))]
3152    pub(crate) fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3153
3154    pub(crate) fn print_subexpression(
3155        expr: &Expr,
3156        needs_group: bool,
3157        tokens: &mut TokenStream,
3158        mut fixup: FixupContext,
3159    ) {
3160        if needs_group {
3161            // If we are surrounding the whole cond in parentheses, such as:
3162            //
3163            //     if (return Struct {}) {}
3164            //
3165            // then there is no need for parenthesizing the individual struct
3166            // expressions within. On the other hand if the whole cond is not
3167            // parenthesized, then print_expr must parenthesize exterior struct
3168            // literals.
3169            //
3170            //     if x == (Struct {}) {}
3171            //
3172            fixup = FixupContext::NONE;
3173        }
3174
3175        let do_print_expr = |tokens: &mut TokenStream| print_expr(expr, tokens, fixup);
3176
3177        if needs_group {
3178            token::Paren::default().surround(tokens, do_print_expr);
3179        } else {
3180            do_print_expr(tokens);
3181        }
3182    }
3183
3184    pub(crate) fn print_expr(expr: &Expr, tokens: &mut TokenStream, mut fixup: FixupContext) {
3185        #[cfg(feature = "full")]
3186        let needs_group = fixup.parenthesize(expr);
3187        #[cfg(not(feature = "full"))]
3188        let needs_group = false;
3189
3190        if needs_group {
3191            fixup = FixupContext::NONE;
3192        }
3193
3194        let do_print_expr = |tokens: &mut TokenStream| match expr {
3195            #[cfg(feature = "full")]
3196            Expr::Array(e) => e.to_tokens(tokens),
3197            #[cfg(feature = "full")]
3198            Expr::Assign(e) => print_expr_assign(e, tokens, fixup),
3199            #[cfg(feature = "full")]
3200            Expr::Async(e) => e.to_tokens(tokens),
3201            #[cfg(feature = "full")]
3202            Expr::Await(e) => print_expr_await(e, tokens, fixup),
3203            Expr::Binary(e) => print_expr_binary(e, tokens, fixup),
3204            #[cfg(feature = "full")]
3205            Expr::Block(e) => e.to_tokens(tokens),
3206            #[cfg(feature = "full")]
3207            Expr::Break(e) => print_expr_break(e, tokens, fixup),
3208            Expr::Call(e) => print_expr_call(e, tokens, fixup),
3209            Expr::Cast(e) => print_expr_cast(e, tokens, fixup),
3210            #[cfg(feature = "full")]
3211            Expr::Closure(e) => print_expr_closure(e, tokens, fixup),
3212            #[cfg(feature = "full")]
3213            Expr::Const(e) => e.to_tokens(tokens),
3214            #[cfg(feature = "full")]
3215            Expr::Continue(e) => e.to_tokens(tokens),
3216            Expr::Field(e) => print_expr_field(e, tokens, fixup),
3217            #[cfg(feature = "full")]
3218            Expr::ForLoop(e) => e.to_tokens(tokens),
3219            Expr::Group(e) => e.to_tokens(tokens),
3220            #[cfg(feature = "full")]
3221            Expr::If(e) => e.to_tokens(tokens),
3222            #[cfg(feature = "full")]
3223            Expr::Index(e) => print_expr_index(e, tokens, fixup),
3224            #[cfg(feature = "full")]
3225            Expr::Infer(e) => e.to_tokens(tokens),
3226            #[cfg(feature = "full")]
3227            Expr::Let(e) => print_expr_let(e, tokens, fixup),
3228            Expr::Lit(e) => e.to_tokens(tokens),
3229            #[cfg(feature = "full")]
3230            Expr::Loop(e) => e.to_tokens(tokens),
3231            Expr::Macro(e) => e.to_tokens(tokens),
3232            #[cfg(feature = "full")]
3233            Expr::Match(e) => e.to_tokens(tokens),
3234            Expr::MethodCall(e) => print_expr_method_call(e, tokens, fixup),
3235            Expr::Paren(e) => e.to_tokens(tokens),
3236            Expr::Path(e) => e.to_tokens(tokens),
3237            #[cfg(feature = "full")]
3238            Expr::Range(e) => print_expr_range(e, tokens, fixup),
3239            #[cfg(feature = "full")]
3240            Expr::RawAddr(e) => print_expr_raw_addr(e, tokens, fixup),
3241            Expr::Reference(e) => print_expr_reference(e, tokens, fixup),
3242            #[cfg(feature = "full")]
3243            Expr::Repeat(e) => e.to_tokens(tokens),
3244            #[cfg(feature = "full")]
3245            Expr::Return(e) => print_expr_return(e, tokens, fixup),
3246            Expr::Struct(e) => e.to_tokens(tokens),
3247            #[cfg(feature = "full")]
3248            Expr::Try(e) => print_expr_try(e, tokens, fixup),
3249            #[cfg(feature = "full")]
3250            Expr::TryBlock(e) => e.to_tokens(tokens),
3251            #[cfg(feature = "full")]
3252            Expr::Tuple(e) => e.to_tokens(tokens),
3253            Expr::Unary(e) => print_expr_unary(e, tokens, fixup),
3254            #[cfg(feature = "full")]
3255            Expr::Unsafe(e) => e.to_tokens(tokens),
3256            Expr::Verbatim(e) => e.to_tokens(tokens),
3257            #[cfg(feature = "full")]
3258            Expr::While(e) => e.to_tokens(tokens),
3259            #[cfg(feature = "full")]
3260            Expr::Yield(e) => print_expr_yield(e, tokens, fixup),
3261
3262            #[cfg(not(feature = "full"))]
3263            _ => unreachable!(),
3264        };
3265
3266        if needs_group {
3267            token::Paren::default().surround(tokens, do_print_expr);
3268        } else {
3269            do_print_expr(tokens);
3270        }
3271    }
3272
3273    #[cfg(feature = "full")]
3274    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3275    impl ToTokens for ExprArray {
3276        fn to_tokens(&self, tokens: &mut TokenStream) {
3277            outer_attrs_to_tokens(&self.attrs, tokens);
3278            self.bracket_token.surround(tokens, |tokens| {
3279                self.elems.to_tokens(tokens);
3280            });
3281        }
3282    }
3283
3284    #[cfg(feature = "full")]
3285    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3286    impl ToTokens for ExprAssign {
3287        fn to_tokens(&self, tokens: &mut TokenStream) {
3288            print_expr_assign(self, tokens, FixupContext::NONE);
3289        }
3290    }
3291
3292    #[cfg(feature = "full")]
3293    fn print_expr_assign(e: &ExprAssign, tokens: &mut TokenStream, fixup: FixupContext) {
3294        outer_attrs_to_tokens(&e.attrs, tokens);
3295        let (left_prec, left_fixup) =
3296            fixup.leftmost_subexpression_with_operator(&e.left, false, false, Precedence::Assign);
3297        print_subexpression(&e.left, left_prec <= Precedence::Range, tokens, left_fixup);
3298        e.eq_token.to_tokens(tokens);
3299        print_expr(
3300            &e.right,
3301            tokens,
3302            fixup.rightmost_subexpression_fixup(false, false, Precedence::Assign),
3303        );
3304    }
3305
3306    #[cfg(feature = "full")]
3307    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3308    impl ToTokens for ExprAsync {
3309        fn to_tokens(&self, tokens: &mut TokenStream) {
3310            outer_attrs_to_tokens(&self.attrs, tokens);
3311            self.async_token.to_tokens(tokens);
3312            self.capture.to_tokens(tokens);
3313            self.block.to_tokens(tokens);
3314        }
3315    }
3316
3317    #[cfg(feature = "full")]
3318    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3319    impl ToTokens for ExprAwait {
3320        fn to_tokens(&self, tokens: &mut TokenStream) {
3321            print_expr_await(self, tokens, FixupContext::NONE);
3322        }
3323    }
3324
3325    #[cfg(feature = "full")]
3326    fn print_expr_await(e: &ExprAwait, tokens: &mut TokenStream, fixup: FixupContext) {
3327        outer_attrs_to_tokens(&e.attrs, tokens);
3328        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.base);
3329        print_subexpression(
3330            &e.base,
3331            left_prec < Precedence::Unambiguous,
3332            tokens,
3333            left_fixup,
3334        );
3335        e.dot_token.to_tokens(tokens);
3336        e.await_token.to_tokens(tokens);
3337    }
3338
3339    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3340    impl ToTokens for ExprBinary {
3341        fn to_tokens(&self, tokens: &mut TokenStream) {
3342            print_expr_binary(self, tokens, FixupContext::NONE);
3343        }
3344    }
3345
3346    fn print_expr_binary(e: &ExprBinary, tokens: &mut TokenStream, fixup: FixupContext) {
3347        outer_attrs_to_tokens(&e.attrs, tokens);
3348
3349        let binop_prec = Precedence::of_binop(&e.op);
3350        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3351            &e.left,
3352            #[cfg(feature = "full")]
3353            match &e.op {
3354                BinOp::Sub(_)
3355                | BinOp::Mul(_)
3356                | BinOp::And(_)
3357                | BinOp::Or(_)
3358                | BinOp::BitAnd(_)
3359                | BinOp::BitOr(_)
3360                | BinOp::Shl(_)
3361                | BinOp::Lt(_) => true,
3362                _ => false,
3363            },
3364            match &e.op {
3365                BinOp::Shl(_) | BinOp::Lt(_) => true,
3366                _ => false,
3367            },
3368            #[cfg(feature = "full")]
3369            binop_prec,
3370        );
3371        let left_needs_group = match binop_prec {
3372            Precedence::Assign => left_prec <= Precedence::Range,
3373            Precedence::Compare => left_prec <= binop_prec,
3374            _ => left_prec < binop_prec,
3375        };
3376
3377        let right_fixup = fixup.rightmost_subexpression_fixup(
3378            #[cfg(feature = "full")]
3379            false,
3380            #[cfg(feature = "full")]
3381            false,
3382            #[cfg(feature = "full")]
3383            binop_prec,
3384        );
3385        let right_needs_group = binop_prec != Precedence::Assign
3386            && right_fixup.rightmost_subexpression_precedence(&e.right) <= binop_prec;
3387
3388        print_subexpression(&e.left, left_needs_group, tokens, left_fixup);
3389        e.op.to_tokens(tokens);
3390        print_subexpression(&e.right, right_needs_group, tokens, right_fixup);
3391    }
3392
3393    #[cfg(feature = "full")]
3394    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3395    impl ToTokens for ExprBlock {
3396        fn to_tokens(&self, tokens: &mut TokenStream) {
3397            outer_attrs_to_tokens(&self.attrs, tokens);
3398            self.label.to_tokens(tokens);
3399            self.block.brace_token.surround(tokens, |tokens| {
3400                inner_attrs_to_tokens(&self.attrs, tokens);
3401                tokens.append_all(&self.block.stmts);
3402            });
3403        }
3404    }
3405
3406    #[cfg(feature = "full")]
3407    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3408    impl ToTokens for ExprBreak {
3409        fn to_tokens(&self, tokens: &mut TokenStream) {
3410            print_expr_break(self, tokens, FixupContext::NONE);
3411        }
3412    }
3413
3414    #[cfg(feature = "full")]
3415    fn print_expr_break(e: &ExprBreak, tokens: &mut TokenStream, fixup: FixupContext) {
3416        outer_attrs_to_tokens(&e.attrs, tokens);
3417        e.break_token.to_tokens(tokens);
3418        e.label.to_tokens(tokens);
3419        if let Some(value) = &e.expr {
3420            print_subexpression(
3421                value,
3422                // Parenthesize `break 'inner: loop { break 'inner 1 } + 1`
3423                //                     ^---------------------------------^
3424                e.label.is_none() && classify::expr_leading_label(value),
3425                tokens,
3426                fixup.rightmost_subexpression_fixup(true, true, Precedence::Jump),
3427            );
3428        }
3429    }
3430
3431    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3432    impl ToTokens for ExprCall {
3433        fn to_tokens(&self, tokens: &mut TokenStream) {
3434            print_expr_call(self, tokens, FixupContext::NONE);
3435        }
3436    }
3437
3438    fn print_expr_call(e: &ExprCall, tokens: &mut TokenStream, fixup: FixupContext) {
3439        outer_attrs_to_tokens(&e.attrs, tokens);
3440
3441        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3442            &e.func,
3443            #[cfg(feature = "full")]
3444            true,
3445            false,
3446            #[cfg(feature = "full")]
3447            Precedence::Unambiguous,
3448        );
3449        let needs_group = if let Expr::Field(func) = &*e.func {
3450            func.member.is_named()
3451        } else {
3452            left_prec < Precedence::Unambiguous
3453        };
3454        print_subexpression(&e.func, needs_group, tokens, left_fixup);
3455
3456        e.paren_token.surround(tokens, |tokens| {
3457            e.args.to_tokens(tokens);
3458        });
3459    }
3460
3461    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3462    impl ToTokens for ExprCast {
3463        fn to_tokens(&self, tokens: &mut TokenStream) {
3464            print_expr_cast(self, tokens, FixupContext::NONE);
3465        }
3466    }
3467
3468    fn print_expr_cast(e: &ExprCast, tokens: &mut TokenStream, fixup: FixupContext) {
3469        outer_attrs_to_tokens(&e.attrs, tokens);
3470        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3471            &e.expr,
3472            #[cfg(feature = "full")]
3473            false,
3474            false,
3475            #[cfg(feature = "full")]
3476            Precedence::Cast,
3477        );
3478        print_subexpression(&e.expr, left_prec < Precedence::Cast, tokens, left_fixup);
3479        e.as_token.to_tokens(tokens);
3480        e.ty.to_tokens(tokens);
3481    }
3482
3483    #[cfg(feature = "full")]
3484    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3485    impl ToTokens for ExprClosure {
3486        fn to_tokens(&self, tokens: &mut TokenStream) {
3487            print_expr_closure(self, tokens, FixupContext::NONE);
3488        }
3489    }
3490
3491    #[cfg(feature = "full")]
3492    fn print_expr_closure(e: &ExprClosure, tokens: &mut TokenStream, fixup: FixupContext) {
3493        outer_attrs_to_tokens(&e.attrs, tokens);
3494        e.lifetimes.to_tokens(tokens);
3495        e.constness.to_tokens(tokens);
3496        e.movability.to_tokens(tokens);
3497        e.asyncness.to_tokens(tokens);
3498        e.capture.to_tokens(tokens);
3499        e.or1_token.to_tokens(tokens);
3500        e.inputs.to_tokens(tokens);
3501        e.or2_token.to_tokens(tokens);
3502        e.output.to_tokens(tokens);
3503        if matches!(e.output, ReturnType::Default)
3504            || matches!(&*e.body, Expr::Block(body) if body.attrs.is_empty() && body.label.is_none())
3505        {
3506            print_expr(
3507                &e.body,
3508                tokens,
3509                fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump),
3510            );
3511        } else {
3512            token::Brace::default().surround(tokens, |tokens| {
3513                print_expr(&e.body, tokens, FixupContext::new_stmt());
3514            });
3515        }
3516    }
3517
3518    #[cfg(feature = "full")]
3519    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3520    impl ToTokens for ExprConst {
3521        fn to_tokens(&self, tokens: &mut TokenStream) {
3522            outer_attrs_to_tokens(&self.attrs, tokens);
3523            self.const_token.to_tokens(tokens);
3524            self.block.brace_token.surround(tokens, |tokens| {
3525                inner_attrs_to_tokens(&self.attrs, tokens);
3526                tokens.append_all(&self.block.stmts);
3527            });
3528        }
3529    }
3530
3531    #[cfg(feature = "full")]
3532    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3533    impl ToTokens for ExprContinue {
3534        fn to_tokens(&self, tokens: &mut TokenStream) {
3535            outer_attrs_to_tokens(&self.attrs, tokens);
3536            self.continue_token.to_tokens(tokens);
3537            self.label.to_tokens(tokens);
3538        }
3539    }
3540
3541    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3542    impl ToTokens for ExprField {
3543        fn to_tokens(&self, tokens: &mut TokenStream) {
3544            print_expr_field(self, tokens, FixupContext::NONE);
3545        }
3546    }
3547
3548    fn print_expr_field(e: &ExprField, tokens: &mut TokenStream, fixup: FixupContext) {
3549        outer_attrs_to_tokens(&e.attrs, tokens);
3550        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.base);
3551        print_subexpression(
3552            &e.base,
3553            left_prec < Precedence::Unambiguous,
3554            tokens,
3555            left_fixup,
3556        );
3557        e.dot_token.to_tokens(tokens);
3558        e.member.to_tokens(tokens);
3559    }
3560
3561    #[cfg(feature = "full")]
3562    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3563    impl ToTokens for ExprForLoop {
3564        fn to_tokens(&self, tokens: &mut TokenStream) {
3565            outer_attrs_to_tokens(&self.attrs, tokens);
3566            self.label.to_tokens(tokens);
3567            self.for_token.to_tokens(tokens);
3568            self.pat.to_tokens(tokens);
3569            self.in_token.to_tokens(tokens);
3570            print_expr(&self.expr, tokens, FixupContext::new_condition());
3571            self.body.brace_token.surround(tokens, |tokens| {
3572                inner_attrs_to_tokens(&self.attrs, tokens);
3573                tokens.append_all(&self.body.stmts);
3574            });
3575        }
3576    }
3577
3578    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3579    impl ToTokens for ExprGroup {
3580        fn to_tokens(&self, tokens: &mut TokenStream) {
3581            outer_attrs_to_tokens(&self.attrs, tokens);
3582            self.group_token.surround(tokens, |tokens| {
3583                self.expr.to_tokens(tokens);
3584            });
3585        }
3586    }
3587
3588    #[cfg(feature = "full")]
3589    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3590    impl ToTokens for ExprIf {
3591        fn to_tokens(&self, tokens: &mut TokenStream) {
3592            outer_attrs_to_tokens(&self.attrs, tokens);
3593
3594            let mut expr = self;
3595            loop {
3596                expr.if_token.to_tokens(tokens);
3597                print_expr(&expr.cond, tokens, FixupContext::new_condition());
3598                expr.then_branch.to_tokens(tokens);
3599
3600                let (else_token, else_) = match &expr.else_branch {
3601                    Some(else_branch) => else_branch,
3602                    None => break,
3603                };
3604
3605                else_token.to_tokens(tokens);
3606                match &**else_ {
3607                    Expr::If(next) => {
3608                        expr = next;
3609                    }
3610                    Expr::Block(last) => {
3611                        last.to_tokens(tokens);
3612                        break;
3613                    }
3614                    // If this is not one of the valid expressions to exist in
3615                    // an else clause, wrap it in a block.
3616                    other => {
3617                        token::Brace::default().surround(tokens, |tokens| {
3618                            print_expr(other, tokens, FixupContext::new_stmt());
3619                        });
3620                        break;
3621                    }
3622                }
3623            }
3624        }
3625    }
3626
3627    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3628    impl ToTokens for ExprIndex {
3629        fn to_tokens(&self, tokens: &mut TokenStream) {
3630            print_expr_index(self, tokens, FixupContext::NONE);
3631        }
3632    }
3633
3634    fn print_expr_index(e: &ExprIndex, tokens: &mut TokenStream, fixup: FixupContext) {
3635        outer_attrs_to_tokens(&e.attrs, tokens);
3636        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3637            &e.expr,
3638            #[cfg(feature = "full")]
3639            true,
3640            false,
3641            #[cfg(feature = "full")]
3642            Precedence::Unambiguous,
3643        );
3644        print_subexpression(
3645            &e.expr,
3646            left_prec < Precedence::Unambiguous,
3647            tokens,
3648            left_fixup,
3649        );
3650        e.bracket_token.surround(tokens, |tokens| {
3651            e.index.to_tokens(tokens);
3652        });
3653    }
3654
3655    #[cfg(feature = "full")]
3656    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3657    impl ToTokens for ExprInfer {
3658        fn to_tokens(&self, tokens: &mut TokenStream) {
3659            outer_attrs_to_tokens(&self.attrs, tokens);
3660            self.underscore_token.to_tokens(tokens);
3661        }
3662    }
3663
3664    #[cfg(feature = "full")]
3665    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3666    impl ToTokens for ExprLet {
3667        fn to_tokens(&self, tokens: &mut TokenStream) {
3668            print_expr_let(self, tokens, FixupContext::NONE);
3669        }
3670    }
3671
3672    #[cfg(feature = "full")]
3673    fn print_expr_let(e: &ExprLet, tokens: &mut TokenStream, fixup: FixupContext) {
3674        outer_attrs_to_tokens(&e.attrs, tokens);
3675        e.let_token.to_tokens(tokens);
3676        e.pat.to_tokens(tokens);
3677        e.eq_token.to_tokens(tokens);
3678        let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Let);
3679        print_subexpression(&e.expr, right_prec < Precedence::Let, tokens, right_fixup);
3680    }
3681
3682    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3683    impl ToTokens for ExprLit {
3684        fn to_tokens(&self, tokens: &mut TokenStream) {
3685            outer_attrs_to_tokens(&self.attrs, tokens);
3686            self.lit.to_tokens(tokens);
3687        }
3688    }
3689
3690    #[cfg(feature = "full")]
3691    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3692    impl ToTokens for ExprLoop {
3693        fn to_tokens(&self, tokens: &mut TokenStream) {
3694            outer_attrs_to_tokens(&self.attrs, tokens);
3695            self.label.to_tokens(tokens);
3696            self.loop_token.to_tokens(tokens);
3697            self.body.brace_token.surround(tokens, |tokens| {
3698                inner_attrs_to_tokens(&self.attrs, tokens);
3699                tokens.append_all(&self.body.stmts);
3700            });
3701        }
3702    }
3703
3704    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3705    impl ToTokens for ExprMacro {
3706        fn to_tokens(&self, tokens: &mut TokenStream) {
3707            outer_attrs_to_tokens(&self.attrs, tokens);
3708            self.mac.to_tokens(tokens);
3709        }
3710    }
3711
3712    #[cfg(feature = "full")]
3713    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3714    impl ToTokens for ExprMatch {
3715        fn to_tokens(&self, tokens: &mut TokenStream) {
3716            outer_attrs_to_tokens(&self.attrs, tokens);
3717            self.match_token.to_tokens(tokens);
3718            print_expr(&self.expr, tokens, FixupContext::new_condition());
3719            self.brace_token.surround(tokens, |tokens| {
3720                inner_attrs_to_tokens(&self.attrs, tokens);
3721                for (i, arm) in self.arms.iter().enumerate() {
3722                    arm.to_tokens(tokens);
3723                    // Ensure that we have a comma after a non-block arm, except
3724                    // for the last one.
3725                    let is_last = i == self.arms.len() - 1;
3726                    if !is_last
3727                        && classify::requires_comma_to_be_match_arm(&arm.body)
3728                        && arm.comma.is_none()
3729                    {
3730                        <Token![,]>::default().to_tokens(tokens);
3731                    }
3732                }
3733            });
3734        }
3735    }
3736
3737    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3738    impl ToTokens for ExprMethodCall {
3739        fn to_tokens(&self, tokens: &mut TokenStream) {
3740            print_expr_method_call(self, tokens, FixupContext::NONE);
3741        }
3742    }
3743
3744    fn print_expr_method_call(e: &ExprMethodCall, tokens: &mut TokenStream, fixup: FixupContext) {
3745        outer_attrs_to_tokens(&e.attrs, tokens);
3746        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.receiver);
3747        print_subexpression(
3748            &e.receiver,
3749            left_prec < Precedence::Unambiguous,
3750            tokens,
3751            left_fixup,
3752        );
3753        e.dot_token.to_tokens(tokens);
3754        e.method.to_tokens(tokens);
3755        if let Some(turbofish) = &e.turbofish {
3756            path::printing::print_angle_bracketed_generic_arguments(
3757                tokens,
3758                turbofish,
3759                PathStyle::Expr,
3760            );
3761        }
3762        e.paren_token.surround(tokens, |tokens| {
3763            e.args.to_tokens(tokens);
3764        });
3765    }
3766
3767    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3768    impl ToTokens for ExprParen {
3769        fn to_tokens(&self, tokens: &mut TokenStream) {
3770            outer_attrs_to_tokens(&self.attrs, tokens);
3771            self.paren_token.surround(tokens, |tokens| {
3772                self.expr.to_tokens(tokens);
3773            });
3774        }
3775    }
3776
3777    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3778    impl ToTokens for ExprPath {
3779        fn to_tokens(&self, tokens: &mut TokenStream) {
3780            outer_attrs_to_tokens(&self.attrs, tokens);
3781            path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
3782        }
3783    }
3784
3785    #[cfg(feature = "full")]
3786    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3787    impl ToTokens for ExprRange {
3788        fn to_tokens(&self, tokens: &mut TokenStream) {
3789            print_expr_range(self, tokens, FixupContext::NONE);
3790        }
3791    }
3792
3793    #[cfg(feature = "full")]
3794    fn print_expr_range(e: &ExprRange, tokens: &mut TokenStream, fixup: FixupContext) {
3795        outer_attrs_to_tokens(&e.attrs, tokens);
3796        if let Some(start) = &e.start {
3797            let (left_prec, left_fixup) =
3798                fixup.leftmost_subexpression_with_operator(start, true, false, Precedence::Range);
3799            print_subexpression(start, left_prec <= Precedence::Range, tokens, left_fixup);
3800        }
3801        e.limits.to_tokens(tokens);
3802        if let Some(end) = &e.end {
3803            let right_fixup = fixup.rightmost_subexpression_fixup(false, true, Precedence::Range);
3804            let right_prec = right_fixup.rightmost_subexpression_precedence(end);
3805            print_subexpression(end, right_prec <= Precedence::Range, tokens, right_fixup);
3806        }
3807    }
3808
3809    #[cfg(feature = "full")]
3810    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3811    impl ToTokens for ExprRawAddr {
3812        fn to_tokens(&self, tokens: &mut TokenStream) {
3813            print_expr_raw_addr(self, tokens, FixupContext::NONE);
3814        }
3815    }
3816
3817    #[cfg(feature = "full")]
3818    fn print_expr_raw_addr(e: &ExprRawAddr, tokens: &mut TokenStream, fixup: FixupContext) {
3819        outer_attrs_to_tokens(&e.attrs, tokens);
3820        e.and_token.to_tokens(tokens);
3821        e.raw.to_tokens(tokens);
3822        e.mutability.to_tokens(tokens);
3823        let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Prefix);
3824        print_subexpression(
3825            &e.expr,
3826            right_prec < Precedence::Prefix,
3827            tokens,
3828            right_fixup,
3829        );
3830    }
3831
3832    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3833    impl ToTokens for ExprReference {
3834        fn to_tokens(&self, tokens: &mut TokenStream) {
3835            print_expr_reference(self, tokens, FixupContext::NONE);
3836        }
3837    }
3838
3839    fn print_expr_reference(e: &ExprReference, tokens: &mut TokenStream, fixup: FixupContext) {
3840        outer_attrs_to_tokens(&e.attrs, tokens);
3841        e.and_token.to_tokens(tokens);
3842        e.mutability.to_tokens(tokens);
3843        let (right_prec, right_fixup) = fixup.rightmost_subexpression(
3844            &e.expr,
3845            #[cfg(feature = "full")]
3846            Precedence::Prefix,
3847        );
3848        print_subexpression(
3849            &e.expr,
3850            right_prec < Precedence::Prefix,
3851            tokens,
3852            right_fixup,
3853        );
3854    }
3855
3856    #[cfg(feature = "full")]
3857    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3858    impl ToTokens for ExprRepeat {
3859        fn to_tokens(&self, tokens: &mut TokenStream) {
3860            outer_attrs_to_tokens(&self.attrs, tokens);
3861            self.bracket_token.surround(tokens, |tokens| {
3862                self.expr.to_tokens(tokens);
3863                self.semi_token.to_tokens(tokens);
3864                self.len.to_tokens(tokens);
3865            });
3866        }
3867    }
3868
3869    #[cfg(feature = "full")]
3870    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3871    impl ToTokens for ExprReturn {
3872        fn to_tokens(&self, tokens: &mut TokenStream) {
3873            print_expr_return(self, tokens, FixupContext::NONE);
3874        }
3875    }
3876
3877    #[cfg(feature = "full")]
3878    fn print_expr_return(e: &ExprReturn, tokens: &mut TokenStream, fixup: FixupContext) {
3879        outer_attrs_to_tokens(&e.attrs, tokens);
3880        e.return_token.to_tokens(tokens);
3881        if let Some(expr) = &e.expr {
3882            print_expr(
3883                expr,
3884                tokens,
3885                fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
3886            );
3887        }
3888    }
3889
3890    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3891    impl ToTokens for ExprStruct {
3892        fn to_tokens(&self, tokens: &mut TokenStream) {
3893            outer_attrs_to_tokens(&self.attrs, tokens);
3894            path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
3895            self.brace_token.surround(tokens, |tokens| {
3896                self.fields.to_tokens(tokens);
3897                if let Some(dot2_token) = &self.dot2_token {
3898                    dot2_token.to_tokens(tokens);
3899                } else if self.rest.is_some() {
3900                    Token![..](Span::call_site()).to_tokens(tokens);
3901                }
3902                self.rest.to_tokens(tokens);
3903            });
3904        }
3905    }
3906
3907    #[cfg(feature = "full")]
3908    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3909    impl ToTokens for ExprTry {
3910        fn to_tokens(&self, tokens: &mut TokenStream) {
3911            print_expr_try(self, tokens, FixupContext::NONE);
3912        }
3913    }
3914
3915    #[cfg(feature = "full")]
3916    fn print_expr_try(e: &ExprTry, tokens: &mut TokenStream, fixup: FixupContext) {
3917        outer_attrs_to_tokens(&e.attrs, tokens);
3918        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.expr);
3919        print_subexpression(
3920            &e.expr,
3921            left_prec < Precedence::Unambiguous,
3922            tokens,
3923            left_fixup,
3924        );
3925        e.question_token.to_tokens(tokens);
3926    }
3927
3928    #[cfg(feature = "full")]
3929    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3930    impl ToTokens for ExprTryBlock {
3931        fn to_tokens(&self, tokens: &mut TokenStream) {
3932            outer_attrs_to_tokens(&self.attrs, tokens);
3933            self.try_token.to_tokens(tokens);
3934            self.block.to_tokens(tokens);
3935        }
3936    }
3937
3938    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3939    impl ToTokens for ExprTuple {
3940        fn to_tokens(&self, tokens: &mut TokenStream) {
3941            outer_attrs_to_tokens(&self.attrs, tokens);
3942            self.paren_token.surround(tokens, |tokens| {
3943                self.elems.to_tokens(tokens);
3944                // If we only have one argument, we need a trailing comma to
3945                // distinguish ExprTuple from ExprParen.
3946                if self.elems.len() == 1 && !self.elems.trailing_punct() {
3947                    <Token![,]>::default().to_tokens(tokens);
3948                }
3949            });
3950        }
3951    }
3952
3953    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3954    impl ToTokens for ExprUnary {
3955        fn to_tokens(&self, tokens: &mut TokenStream) {
3956            print_expr_unary(self, tokens, FixupContext::NONE);
3957        }
3958    }
3959
3960    fn print_expr_unary(e: &ExprUnary, tokens: &mut TokenStream, fixup: FixupContext) {
3961        outer_attrs_to_tokens(&e.attrs, tokens);
3962        e.op.to_tokens(tokens);
3963        let (right_prec, right_fixup) = fixup.rightmost_subexpression(
3964            &e.expr,
3965            #[cfg(feature = "full")]
3966            Precedence::Prefix,
3967        );
3968        print_subexpression(
3969            &e.expr,
3970            right_prec < Precedence::Prefix,
3971            tokens,
3972            right_fixup,
3973        );
3974    }
3975
3976    #[cfg(feature = "full")]
3977    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3978    impl ToTokens for ExprUnsafe {
3979        fn to_tokens(&self, tokens: &mut TokenStream) {
3980            outer_attrs_to_tokens(&self.attrs, tokens);
3981            self.unsafe_token.to_tokens(tokens);
3982            self.block.brace_token.surround(tokens, |tokens| {
3983                inner_attrs_to_tokens(&self.attrs, tokens);
3984                tokens.append_all(&self.block.stmts);
3985            });
3986        }
3987    }
3988
3989    #[cfg(feature = "full")]
3990    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3991    impl ToTokens for ExprWhile {
3992        fn to_tokens(&self, tokens: &mut TokenStream) {
3993            outer_attrs_to_tokens(&self.attrs, tokens);
3994            self.label.to_tokens(tokens);
3995            self.while_token.to_tokens(tokens);
3996            print_expr(&self.cond, tokens, FixupContext::new_condition());
3997            self.body.brace_token.surround(tokens, |tokens| {
3998                inner_attrs_to_tokens(&self.attrs, tokens);
3999                tokens.append_all(&self.body.stmts);
4000            });
4001        }
4002    }
4003
4004    #[cfg(feature = "full")]
4005    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4006    impl ToTokens for ExprYield {
4007        fn to_tokens(&self, tokens: &mut TokenStream) {
4008            print_expr_yield(self, tokens, FixupContext::NONE);
4009        }
4010    }
4011
4012    #[cfg(feature = "full")]
4013    fn print_expr_yield(e: &ExprYield, tokens: &mut TokenStream, fixup: FixupContext) {
4014        outer_attrs_to_tokens(&e.attrs, tokens);
4015        e.yield_token.to_tokens(tokens);
4016        if let Some(expr) = &e.expr {
4017            print_expr(
4018                expr,
4019                tokens,
4020                fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
4021            );
4022        }
4023    }
4024
4025    #[cfg(feature = "full")]
4026    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4027    impl ToTokens for Arm {
4028        fn to_tokens(&self, tokens: &mut TokenStream) {
4029            tokens.append_all(&self.attrs);
4030            self.pat.to_tokens(tokens);
4031            if let Some((if_token, guard)) = &self.guard {
4032                if_token.to_tokens(tokens);
4033                guard.to_tokens(tokens);
4034            }
4035            self.fat_arrow_token.to_tokens(tokens);
4036            print_expr(&self.body, tokens, FixupContext::new_match_arm());
4037            self.comma.to_tokens(tokens);
4038        }
4039    }
4040
4041    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4042    impl ToTokens for FieldValue {
4043        fn to_tokens(&self, tokens: &mut TokenStream) {
4044            outer_attrs_to_tokens(&self.attrs, tokens);
4045            self.member.to_tokens(tokens);
4046            if let Some(colon_token) = &self.colon_token {
4047                colon_token.to_tokens(tokens);
4048                self.expr.to_tokens(tokens);
4049            }
4050        }
4051    }
4052
4053    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4054    impl ToTokens for Index {
4055        fn to_tokens(&self, tokens: &mut TokenStream) {
4056            let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
4057            lit.set_span(self.span);
4058            tokens.append(lit);
4059        }
4060    }
4061
4062    #[cfg(feature = "full")]
4063    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4064    impl ToTokens for Label {
4065        fn to_tokens(&self, tokens: &mut TokenStream) {
4066            self.name.to_tokens(tokens);
4067            self.colon_token.to_tokens(tokens);
4068        }
4069    }
4070
4071    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4072    impl ToTokens for Member {
4073        fn to_tokens(&self, tokens: &mut TokenStream) {
4074            match self {
4075                Member::Named(ident) => ident.to_tokens(tokens),
4076                Member::Unnamed(index) => index.to_tokens(tokens),
4077            }
4078        }
4079    }
4080
4081    #[cfg(feature = "full")]
4082    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4083    impl ToTokens for RangeLimits {
4084        fn to_tokens(&self, tokens: &mut TokenStream) {
4085            match self {
4086                RangeLimits::HalfOpen(t) => t.to_tokens(tokens),
4087                RangeLimits::Closed(t) => t.to_tokens(tokens),
4088            }
4089        }
4090    }
4091
4092    #[cfg(feature = "full")]
4093    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4094    impl ToTokens for PointerMutability {
4095        fn to_tokens(&self, tokens: &mut TokenStream) {
4096            match self {
4097                PointerMutability::Const(const_token) => const_token.to_tokens(tokens),
4098                PointerMutability::Mut(mut_token) => mut_token.to_tokens(tokens),
4099            }
4100        }
4101    }
4102}