Skip to main content

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;
23use crate::ty::Type;
24#[cfg(feature = "full")]
25use crate::ty::{PointerMutability, ReturnType};
26use alloc::boxed::Box;
27use alloc::vec::Vec;
28#[cfg(feature = "printing")]
29use core::fmt::{self, Display};
30use core::hash::{Hash, Hasher};
31#[cfg(all(feature = "parsing", feature = "full"))]
32use core::mem;
33use proc_macro2::{Span, TokenStream};
34#[cfg(feature = "printing")]
35use quote::IdentFragment;
36
37ast_enum_of_structs! {
38    /// A Rust expression.
39    ///
40    /// *This type is available only if Syn is built with the `"derive"` or `"full"`
41    /// feature, but most of the variants are not available unless "full" is enabled.*
42    ///
43    /// # Syntax tree enums
44    ///
45    /// This type is a syntax tree enum. In Syn this and other syntax tree enums
46    /// are designed to be traversed using the following rebinding idiom.
47    ///
48    /// ```
49    /// # use syn::Expr;
50    /// #
51    /// # fn example(expr: Expr) {
52    /// # const IGNORE: &str = stringify! {
53    /// let expr: Expr = /* ... */;
54    /// # };
55    /// match expr {
56    ///     Expr::MethodCall(expr) => {
57    ///         /* ... */
58    ///     }
59    ///     Expr::Cast(expr) => {
60    ///         /* ... */
61    ///     }
62    ///     Expr::If(expr) => {
63    ///         /* ... */
64    ///     }
65    ///
66    ///     /* ... */
67    ///     # _ => {}
68    /// # }
69    /// # }
70    /// ```
71    ///
72    /// We begin with a variable `expr` of type `Expr` that has no fields
73    /// (because it is an enum), and by matching on it and rebinding a variable
74    /// with the same name `expr` we effectively imbue our variable with all of
75    /// the data fields provided by the variant that it turned out to be. So for
76    /// example above if we ended up in the `MethodCall` case then we get to use
77    /// `expr.receiver`, `expr.args` etc; if we ended up in the `If` case we get
78    /// to use `expr.cond`, `expr.then_branch`, `expr.else_branch`.
79    ///
80    /// This approach avoids repeating the variant names twice on every line.
81    ///
82    /// ```
83    /// # use syn::{Expr, ExprMethodCall};
84    /// #
85    /// # fn example(expr: Expr) {
86    /// // Repetitive; recommend not doing this.
87    /// match expr {
88    ///     Expr::MethodCall(ExprMethodCall { method, args, .. }) => {
89    /// # }
90    /// # _ => {}
91    /// # }
92    /// # }
93    /// ```
94    ///
95    /// In general, the name to which a syntax tree enum variant is bound should
96    /// be a suitable name for the complete syntax tree enum type.
97    ///
98    /// ```
99    /// # use syn::{Expr, ExprField};
100    /// #
101    /// # fn example(discriminant: ExprField) {
102    /// // Binding is called `base` which is the name I would use if I were
103    /// // assigning `*discriminant.base` without an `if let`.
104    /// if let Expr::Tuple(base) = *discriminant.base {
105    /// # }
106    /// # }
107    /// ```
108    ///
109    /// A sign that you may not be choosing the right variable names is if you
110    /// see names getting repeated in your code, like accessing
111    /// `receiver.receiver` or `pat.pat` or `cond.cond`.
112    ///
113    /// # Exhaustive matching
114    ///
115    /// For testing exhaustiveness in downstream code, use the following idiom:
116    ///
117    /// ```
118    /// # use syn::Expr;
119    /// #
120    /// # fn example(expr: Expr) {
121    /// match expr {
122    ///     #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
123    ///
124    ///     Expr::Array(expr) => { /*...*/ }
125    ///     Expr::Assign(expr) => { /*...*/ }
126    #[cfg_attr(not(doctest), doc = "     ...")]
127    ///     Expr::Yield(expr) => { /*...*/ }
128    ///
129    ///     _ => { /* some sane fallback */ }
130    /// }
131    /// # }
132    /// ```
133    ///
134    /// This way we fail your tests but don't break your library when adding a
135    /// variant. You will be notified by a test failure when a variant is added,
136    /// so that you can add code to handle it, but your library will continue to
137    /// compile and work for downstream users in the interim.
138    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
139    #[non_exhaustive]
140    pub enum Expr {
141        /// A slice literal expression: `[a, b, c, d]`.
142        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
143        Array(ExprArray),
144
145        /// An assignment expression: `a = compute()`.
146        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
147        Assign(ExprAssign),
148
149        /// An async block: `async { ... }`.
150        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
151        Async(ExprAsync),
152
153        /// An await expression: `fut.await`.
154        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
155        Await(ExprAwait),
156
157        /// A binary operation: `a + b`, `a += b`.
158        Binary(ExprBinary),
159
160        /// A braced block: `{ ... }`.
161        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
162        Block(ExprBlock),
163
164        /// A `break`, with an optional label to break and an optional
165        /// expression.
166        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
167        Break(ExprBreak),
168
169        /// A function call expression: `invoke(a, b)`.
170        Call(ExprCall),
171
172        /// A cast expression: `foo as f64`.
173        Cast(ExprCast),
174
175        /// A closure expression: `|a, b| a + b`.
176        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
177        Closure(ExprClosure),
178
179        /// A const block: `const { ... }`.
180        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
181        Const(ExprConst),
182
183        /// A `continue`, with an optional label.
184        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
185        Continue(ExprContinue),
186
187        /// Access of a named struct field (`obj.k`) or unnamed tuple struct
188        /// field (`obj.0`).
189        Field(ExprField),
190
191        /// A for loop: `for pat in expr { ... }`.
192        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
193        ForLoop(ExprForLoop),
194
195        /// An expression contained within invisible delimiters.
196        ///
197        /// This variant is important for faithfully representing the precedence
198        /// of expressions and is related to `None`-delimited spans in a
199        /// `TokenStream`.
200        Group(ExprGroup),
201
202        /// An `if` expression with an optional `else` block: `if expr { ... }
203        /// else { ... }`.
204        ///
205        /// The `else` branch expression may only be an `If` or `Block`
206        /// expression, not any of the other types of expression.
207        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
208        If(ExprIf),
209
210        /// A square bracketed indexing expression: `vector[2]`.
211        Index(ExprIndex),
212
213        /// The inferred value of a const generic argument, denoted `_`.
214        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
215        Infer(ExprInfer),
216
217        /// A pattern application: `let Some(x) = opt`.
218        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
219        Let(ExprLet),
220
221        /// A literal in place of an expression: `1`, `"foo"`.
222        Lit(ExprLit),
223
224        /// Conditionless loop: `loop { ... }`.
225        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
226        Loop(ExprLoop),
227
228        /// A macro invocation expression: `format!("{}", q)`.
229        Macro(ExprMacro),
230
231        /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
232        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
233        Match(ExprMatch),
234
235        /// A method call expression: `x.foo::<T>(a, b)`.
236        MethodCall(ExprMethodCall),
237
238        /// A parenthesized expression: `(a + b)`.
239        Paren(ExprParen),
240
241        /// A path like `core::mem::replace` possibly containing generic
242        /// parameters and a qualified self-type.
243        ///
244        /// A plain identifier like `x` is a path of length 1.
245        Path(ExprPath),
246
247        /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
248        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
249        Range(ExprRange),
250
251        /// Address-of operation: `&raw const place` or `&raw mut place`.
252        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
253        RawAddr(ExprRawAddr),
254
255        /// A referencing operation: `&a` or `&mut a`.
256        Reference(ExprReference),
257
258        /// An array literal constructed from one repeated element: `[0u8; N]`.
259        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
260        Repeat(ExprRepeat),
261
262        /// A `return`, with an optional value to be returned.
263        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
264        Return(ExprReturn),
265
266        /// A struct literal expression: `Point { x: 1, y: 1 }`.
267        ///
268        /// The `rest` provides the value of the remaining fields as in `S { a:
269        /// 1, b: 1, ..rest }`.
270        Struct(ExprStruct),
271
272        /// A try-expression: `expr?`.
273        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
274        Try(ExprTry),
275
276        /// A try block: `try { ... }`.
277        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
278        TryBlock(ExprTryBlock),
279
280        /// A tuple expression: `(a, b, c, d)`.
281        Tuple(ExprTuple),
282
283        /// A unary operation: `!x`, `*x`, `-x`.
284        Unary(ExprUnary),
285
286        /// An unsafe block: `unsafe { ... }`.
287        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
288        Unsafe(ExprUnsafe),
289
290        /// Tokens in expression position not interpreted by Syn.
291        ///
292        /// <div class="warning">
293        ///
294        /// Important: see [Compatibility notes][crate#verbatim-variants].
295        ///
296        /// </div>
297        Verbatim(TokenStream),
298
299        /// A while loop: `while expr { ... }`.
300        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
301        While(ExprWhile),
302
303        /// A yield expression: `yield expr`.
304        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
305        Yield(ExprYield),
306    }
307}
308
309ast_struct! {
310    /// A slice literal expression: `[a, b, c, d]`.
311    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
312    pub struct ExprArray #full {
313        pub attrs: Vec<Attribute>,
314        pub bracket_token: token::Bracket,
315        pub elems: Punctuated<Expr, Token![,]>,
316    }
317}
318
319ast_struct! {
320    /// An assignment expression: `a = compute()`.
321    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
322    pub struct ExprAssign #full {
323        pub attrs: Vec<Attribute>,
324        pub left: Box<Expr>,
325        pub eq_token: Token![=],
326        pub right: Box<Expr>,
327    }
328}
329
330ast_struct! {
331    /// An async block: `async { ... }`.
332    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
333    pub struct ExprAsync #full {
334        pub attrs: Vec<Attribute>,
335        pub async_token: Token![async],
336        pub capture: Option<Token![move]>,
337        /// (Non-exhaustive) Additional optional information about a block.
338        pub modifiers: BlockModifiers,
339        pub block: Block,
340    }
341}
342
343ast_struct! {
344    /// An await expression: `fut.await`.
345    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
346    pub struct ExprAwait #full {
347        pub attrs: Vec<Attribute>,
348        pub base: Box<Expr>,
349        pub dot_token: Token![.],
350        pub await_token: Token![await],
351    }
352}
353
354ast_struct! {
355    /// A binary operation: `a + b`, `a += b`.
356    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
357    pub struct ExprBinary {
358        pub attrs: Vec<Attribute>,
359        pub left: Box<Expr>,
360        pub op: BinOp,
361        pub right: Box<Expr>,
362    }
363}
364
365ast_struct! {
366    /// A braced block: `{ ... }`.
367    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
368    pub struct ExprBlock #full {
369        pub attrs: Vec<Attribute>,
370        pub label: Option<Label>,
371        pub block: Block,
372    }
373}
374
375ast_struct! {
376    /// A `break`, with an optional label to break and an optional
377    /// expression.
378    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
379    pub struct ExprBreak #full {
380        pub attrs: Vec<Attribute>,
381        pub break_token: Token![break],
382        pub label: Option<Lifetime>,
383        pub expr: Option<Box<Expr>>,
384    }
385}
386
387ast_struct! {
388    /// A function call expression: `invoke(a, b)`.
389    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
390    pub struct ExprCall {
391        pub attrs: Vec<Attribute>,
392        pub func: Box<Expr>,
393        pub paren_token: token::Paren,
394        pub args: Punctuated<Expr, Token![,]>,
395    }
396}
397
398ast_struct! {
399    /// A cast expression: `foo as f64`.
400    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
401    pub struct ExprCast {
402        pub attrs: Vec<Attribute>,
403        pub expr: Box<Expr>,
404        pub as_token: Token![as],
405        pub ty: Box<Type>,
406    }
407}
408
409ast_struct! {
410    /// A closure expression: `|a, b| a + b`.
411    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
412    pub struct ExprClosure #full {
413        pub attrs: Vec<Attribute>,
414        pub lifetimes: Option<BoundLifetimes>,
415        /// (Non-exhaustive) Additional optional information about a closure.
416        pub modifiers: ClosureModifiers,
417        pub constness: Option<Token![const]>,
418        pub asyncness: Option<Token![async]>,
419        pub capture: Option<Token![move]>,
420        pub inputs_begin: Token![|],
421        pub inputs: Punctuated<Pat, Token![,]>,
422        pub inputs_end: Token![|],
423        pub output: ReturnType,
424        pub body: Box<Expr>,
425    }
426}
427
428#[cfg(feature = "full")]
429ast_struct! {
430    /// Additional optional information about a closure.
431    ///
432    /// This data structure may grow to accommodate future Rust language
433    /// changes, including the following in-progress RFCs:
434    ///
435    /// - [RFC 2033] "Coroutines" (`static || ...`)
436    /// - [RFC 3680] "Simplify lightweight clones" (`use || ...`)
437    ///
438    /// [RFC 2033]: https://github.com/rust-lang/rust/issues/43122
439    /// [RFC 3680]: https://github.com/rust-lang/rust/issues/132290
440    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
441    #[non_exhaustive]
442    pub struct ClosureModifiers {}
443}
444
445#[cfg(feature = "full")]
446impl Default for ClosureModifiers {
447    fn default() -> Self {
448        ClosureModifiers {}
449    }
450}
451
452#[cfg(feature = "full")]
453impl ClosureModifiers {
454    #[cfg(feature = "parsing")]
455    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
456    pub fn require_empty(&self) -> Result<()> {
457        Ok(())
458    }
459}
460
461ast_struct! {
462    /// A const block: `const { ... }`.
463    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
464    pub struct ExprConst #full {
465        pub attrs: Vec<Attribute>,
466        pub const_token: Token![const],
467        /// (Non-exhaustive) Additional optional information about a block.
468        pub modifiers: BlockModifiers,
469        pub block: Block,
470    }
471}
472
473ast_struct! {
474    /// A `continue`, with an optional label.
475    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
476    pub struct ExprContinue #full {
477        pub attrs: Vec<Attribute>,
478        pub continue_token: Token![continue],
479        pub label: Option<Lifetime>,
480    }
481}
482
483ast_struct! {
484    /// Access of a named struct field (`obj.k`) or unnamed tuple struct
485    /// field (`obj.0`).
486    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
487    pub struct ExprField {
488        pub attrs: Vec<Attribute>,
489        pub base: Box<Expr>,
490        pub dot_token: Token![.],
491        pub member: Member,
492    }
493}
494
495ast_struct! {
496    /// A for loop: `for pat in expr { ... }`.
497    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
498    pub struct ExprForLoop #full {
499        pub attrs: Vec<Attribute>,
500        pub label: Option<Label>,
501        pub for_token: Token![for],
502        pub pat: Box<Pat>,
503        pub in_token: Token![in],
504        pub expr: Box<Expr>,
505        pub body: Block,
506    }
507}
508
509ast_struct! {
510    /// An expression contained within invisible delimiters.
511    ///
512    /// This variant is important for faithfully representing the precedence
513    /// of expressions and is related to `None`-delimited spans in a
514    /// `TokenStream`.
515    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
516    pub struct ExprGroup {
517        pub attrs: Vec<Attribute>,
518        pub group_token: token::Group,
519        pub expr: Box<Expr>,
520    }
521}
522
523ast_struct! {
524    /// An `if` expression with an optional `else` block: `if expr { ... }
525    /// else { ... }`.
526    ///
527    /// The `else` branch expression may only be an `If` or `Block`
528    /// expression, not any of the other types of expression.
529    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
530    pub struct ExprIf #full {
531        pub attrs: Vec<Attribute>,
532        pub if_token: Token![if],
533        pub cond: Box<Expr>,
534        pub then_branch: Block,
535        pub else_branch: Option<(Token![else], Box<Expr>)>,
536    }
537}
538
539ast_struct! {
540    /// A square bracketed indexing expression: `vector[2]`.
541    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
542    pub struct ExprIndex {
543        pub attrs: Vec<Attribute>,
544        pub expr: Box<Expr>,
545        pub bracket_token: token::Bracket,
546        pub index: Box<Expr>,
547    }
548}
549
550ast_struct! {
551    /// The inferred value of a const generic argument, denoted `_`.
552    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
553    pub struct ExprInfer #full {
554        pub attrs: Vec<Attribute>,
555        pub underscore_token: Token![_],
556    }
557}
558
559ast_struct! {
560    /// A pattern application: `let Some(x) = opt`.
561    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
562    pub struct ExprLet #full {
563        pub attrs: Vec<Attribute>,
564        pub let_token: Token![let],
565        pub pat: Box<Pat>,
566        pub eq_token: Token![=],
567        pub expr: Box<Expr>,
568    }
569}
570
571ast_struct! {
572    /// A literal in place of an expression: `1`, `"foo"`.
573    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
574    pub struct ExprLit {
575        pub attrs: Vec<Attribute>,
576        pub lit: Lit,
577    }
578}
579
580ast_struct! {
581    /// Conditionless loop: `loop { ... }`.
582    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
583    pub struct ExprLoop #full {
584        pub attrs: Vec<Attribute>,
585        pub label: Option<Label>,
586        pub loop_token: Token![loop],
587        pub body: Block,
588    }
589}
590
591ast_struct! {
592    /// A macro invocation expression: `format!("{}", q)`.
593    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
594    pub struct ExprMacro {
595        pub attrs: Vec<Attribute>,
596        pub mac: Macro,
597    }
598}
599
600ast_struct! {
601    /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
602    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
603    pub struct ExprMatch #full {
604        pub attrs: Vec<Attribute>,
605        pub match_token: Token![match],
606        pub expr: Box<Expr>,
607        pub brace_token: token::Brace,
608        pub arms: Vec<Arm>,
609    }
610}
611
612ast_struct! {
613    /// A method call expression: `x.foo::<T>(a, b)`.
614    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
615    pub struct ExprMethodCall {
616        pub attrs: Vec<Attribute>,
617        pub receiver: Box<Expr>,
618        pub dot_token: Token![.],
619        pub method: Ident,
620        pub turbofish: Option<AngleBracketedGenericArguments>,
621        pub paren_token: token::Paren,
622        pub args: Punctuated<Expr, Token![,]>,
623    }
624}
625
626ast_struct! {
627    /// A parenthesized expression: `(a + b)`.
628    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
629    pub struct ExprParen {
630        pub attrs: Vec<Attribute>,
631        pub paren_token: token::Paren,
632        pub expr: Box<Expr>,
633    }
634}
635
636ast_struct! {
637    /// A path like `core::mem::replace` possibly containing generic
638    /// parameters and a qualified self-type.
639    ///
640    /// A plain identifier like `x` is a path of length 1.
641    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
642    pub struct ExprPath {
643        pub attrs: Vec<Attribute>,
644        pub qself: Option<QSelf>,
645        pub path: Path,
646    }
647}
648
649ast_struct! {
650    /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
651    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
652    pub struct ExprRange #full {
653        pub attrs: Vec<Attribute>,
654        pub start: Option<Box<Expr>>,
655        pub limits: RangeLimits,
656        pub end: Option<Box<Expr>>,
657    }
658}
659
660ast_struct! {
661    /// Address-of operation: `&raw const place` or `&raw mut place`.
662    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
663    pub struct ExprRawAddr #full {
664        pub attrs: Vec<Attribute>,
665        pub and_token: Token![&],
666        pub raw: Token![raw],
667        pub mutability: PointerMutability,
668        pub expr: Box<Expr>,
669    }
670}
671
672ast_struct! {
673    /// A referencing operation: `&a` or `&mut a`.
674    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
675    pub struct ExprReference {
676        pub attrs: Vec<Attribute>,
677        pub and_token: Token![&],
678        pub mutability: Option<Token![mut]>,
679        pub expr: Box<Expr>,
680    }
681}
682
683ast_struct! {
684    /// An array literal constructed from one repeated element: `[0u8; N]`.
685    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
686    pub struct ExprRepeat #full {
687        pub attrs: Vec<Attribute>,
688        pub bracket_token: token::Bracket,
689        pub expr: Box<Expr>,
690        pub semi_token: Token![;],
691        pub len: Box<Expr>,
692    }
693}
694
695ast_struct! {
696    /// A `return`, with an optional value to be returned.
697    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
698    pub struct ExprReturn #full {
699        pub attrs: Vec<Attribute>,
700        pub return_token: Token![return],
701        pub expr: Option<Box<Expr>>,
702    }
703}
704
705ast_struct! {
706    /// A struct literal expression: `Point { x: 1, y: 1 }`.
707    ///
708    /// The `rest` provides the value of the remaining fields as in `S { a:
709    /// 1, b: 1, ..rest }`.
710    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
711    pub struct ExprStruct {
712        pub attrs: Vec<Attribute>,
713        pub qself: Option<QSelf>,
714        pub path: Path,
715        pub brace_token: token::Brace,
716        pub fields: Punctuated<FieldValue, Token![,]>,
717        pub dot2_token: Option<Token![..]>,
718        pub rest: Option<Box<Expr>>,
719    }
720}
721
722ast_struct! {
723    /// A try-expression: `expr?`.
724    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
725    pub struct ExprTry #full {
726        pub attrs: Vec<Attribute>,
727        pub expr: Box<Expr>,
728        pub question_token: Token![?],
729    }
730}
731
732ast_struct! {
733    /// A try block: `try { ... }`.
734    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
735    pub struct ExprTryBlock #full {
736        pub attrs: Vec<Attribute>,
737        pub try_token: Token![try],
738        /// (Non-exhaustive) Additional optional information about a block.
739        pub modifiers: BlockModifiers,
740        pub block: Block,
741    }
742}
743
744ast_struct! {
745    /// A tuple expression: `(a, b, c, d)`.
746    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
747    pub struct ExprTuple {
748        pub attrs: Vec<Attribute>,
749        pub paren_token: token::Paren,
750        pub elems: Punctuated<Expr, Token![,]>,
751    }
752}
753
754ast_struct! {
755    /// A unary operation: `!x`, `*x`, `-x`.
756    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
757    pub struct ExprUnary {
758        pub attrs: Vec<Attribute>,
759        pub op: UnOp,
760        pub expr: Box<Expr>,
761    }
762}
763
764ast_struct! {
765    /// An unsafe block: `unsafe { ... }`.
766    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
767    pub struct ExprUnsafe #full {
768        pub attrs: Vec<Attribute>,
769        pub unsafe_token: Token![unsafe],
770        pub block: Block,
771    }
772}
773
774ast_struct! {
775    /// A while loop: `while expr { ... }`.
776    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
777    pub struct ExprWhile #full {
778        pub attrs: Vec<Attribute>,
779        pub label: Option<Label>,
780        pub while_token: Token![while],
781        pub cond: Box<Expr>,
782        pub body: Block,
783    }
784}
785
786ast_struct! {
787    /// A yield expression: `yield expr`.
788    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
789    pub struct ExprYield #full {
790        pub attrs: Vec<Attribute>,
791        pub yield_token: Token![yield],
792        pub expr: Option<Box<Expr>>,
793    }
794}
795
796impl Expr {
797    /// An unspecified invalid expression.
798    ///
799    /// ```
800    /// use core::mem;
801    /// use quote::ToTokens;
802    /// use syn::{parse_quote, Expr};
803    ///
804    /// fn unparenthesize(e: &mut Expr) {
805    ///     while let Expr::Paren(paren) = e {
806    ///         *e = mem::replace(&mut *paren.expr, Expr::PLACEHOLDER);
807    ///     }
808    /// }
809    ///
810    /// fn main() {
811    ///     let mut e: Expr = parse_quote! { ((1 + 1)) };
812    ///     unparenthesize(&mut e);
813    ///     assert_eq!("1 + 1", e.to_token_stream().to_string());
814    /// }
815    /// ```
816    pub const PLACEHOLDER: Self = Expr::Path(ExprPath {
817        attrs: Vec::new(),
818        qself: None,
819        path: Path {
820            leading_colon: None,
821            segments: Punctuated::new(),
822        },
823    });
824
825    /// An alternative to the primary `Expr::parse` parser (from the [`Parse`]
826    /// trait) for ambiguous syntactic positions in which a trailing brace
827    /// should not be taken as part of the expression.
828    ///
829    /// [`Parse`]: crate::parse::Parse
830    ///
831    /// Rust grammar has an ambiguity where braces sometimes turn a path
832    /// expression into a struct initialization and sometimes do not. In the
833    /// following code, the expression `S {}` is one expression. Presumably
834    /// there is an empty struct `struct S {}` defined somewhere which it is
835    /// instantiating.
836    ///
837    /// ```
838    /// # struct S;
839    /// # impl core::ops::Deref for S {
840    /// #     type Target = bool;
841    /// #     fn deref(&self) -> &Self::Target {
842    /// #         &true
843    /// #     }
844    /// # }
845    /// let _ = *S {};
846    ///
847    /// // parsed by rustc as: `*(S {})`
848    /// ```
849    ///
850    /// We would want to parse the above using `Expr::parse` after the `=`
851    /// token.
852    ///
853    /// But in the following, `S {}` is *not* a struct init expression.
854    ///
855    /// ```
856    /// # const S: &bool = &true;
857    /// if *S {} {}
858    ///
859    /// // parsed by rustc as:
860    /// //
861    /// //    if (*S) {
862    /// //        /* empty block */
863    /// //    }
864    /// //    {
865    /// //        /* another empty block */
866    /// //    }
867    /// ```
868    ///
869    /// For that reason we would want to parse if-conditions using
870    /// `Expr::parse_without_eager_brace` after the `if` token. Same for similar
871    /// syntactic positions such as the condition expr after a `while` token or
872    /// the expr at the top of a `match`.
873    ///
874    /// The Rust grammar's choices around which way this ambiguity is resolved
875    /// at various syntactic positions is fairly arbitrary. Really either parse
876    /// behavior could work in most positions, and language designers just
877    /// decide each case based on which is more likely to be what the programmer
878    /// had in mind most of the time.
879    ///
880    /// ```
881    /// # struct S;
882    /// # fn doc() -> S {
883    /// if return S {} {}
884    /// # unreachable!()
885    /// # }
886    ///
887    /// // parsed by rustc as:
888    /// //
889    /// //    if (return (S {})) {
890    /// //    }
891    /// //
892    /// // but could equally well have been this other arbitrary choice:
893    /// //
894    /// //    if (return S) {
895    /// //    }
896    /// //    {}
897    /// ```
898    ///
899    /// Note the grammar ambiguity on trailing braces is distinct from
900    /// precedence and is not captured by assigning a precedence level to the
901    /// braced struct init expr in relation to other operators. This can be
902    /// illustrated by `return 0..S {}` vs `match 0..S {}`. The former parses as
903    /// `return (0..(S {}))` implying tighter precedence for struct init than
904    /// `..`, while the latter parses as `match (0..S) {}` implying tighter
905    /// precedence for `..` than struct init, a contradiction.
906    #[cfg(all(feature = "full", feature = "parsing"))]
907    #[cfg_attr(docsrs, doc(cfg(all(feature = "full", feature = "parsing"))))]
908    pub fn parse_without_eager_brace(input: ParseStream) -> Result<Expr> {
909        parsing::ambiguous_expr(input, parsing::AllowStruct(false))
910    }
911
912    /// An alternative to the primary `Expr::parse` parser (from the [`Parse`]
913    /// trait) for syntactic positions in which expression boundaries are placed
914    /// more eagerly than done by the typical expression grammar. This includes
915    /// expressions at the head of a statement or in the right-hand side of a
916    /// `match` arm.
917    ///
918    /// [`Parse`]: crate::parse::Parse
919    ///
920    /// Compare the following cases:
921    ///
922    /// 1.
923    ///   ```
924    ///   # let result = ();
925    ///   # let guard = false;
926    ///   # let cond = true;
927    ///   # let f = true;
928    ///   # let g = f;
929    ///   #
930    ///   let _ = match result {
931    ///       () if guard => if cond { f } else { g }
932    ///       () => false,
933    ///   };
934    ///   ```
935    ///
936    /// 2.
937    ///   ```
938    ///   # let cond = true;
939    ///   # let f = ();
940    ///   # let g = f;
941    ///   #
942    ///   let _ = || {
943    ///       if cond { f } else { g }
944    ///       ()
945    ///   };
946    ///   ```
947    ///
948    /// 3.
949    ///   ```
950    ///   # let cond = true;
951    ///   # let f = || ();
952    ///   # let g = f;
953    ///   #
954    ///   let _ = [if cond { f } else { g } ()];
955    ///   ```
956    ///
957    /// The same sequence of tokens `if cond { f } else { g } ()` appears in
958    /// expression position 3 times. The first two syntactic positions use eager
959    /// placement of expression boundaries, and parse as `Expr::If`, with the
960    /// adjacent `()` becoming `Pat::Tuple` or `Expr::Tuple`. In contrast, the
961    /// third case uses standard expression boundaries and parses as
962    /// `Expr::Call`.
963    ///
964    /// As with [`parse_without_eager_brace`], this ambiguity in the Rust
965    /// grammar is independent of precedence.
966    ///
967    /// [`parse_without_eager_brace`]: Self::parse_without_eager_brace
968    #[cfg(all(feature = "full", feature = "parsing"))]
969    #[cfg_attr(docsrs, doc(cfg(all(feature = "full", feature = "parsing"))))]
970    pub fn parse_with_earlier_boundary_rule(input: ParseStream) -> Result<Expr> {
971        parsing::parse_with_earlier_boundary_rule(input)
972    }
973
974    /// Returns whether the next token in the parse stream is one that might
975    /// possibly form the beginning of an expr.
976    ///
977    /// This classification is a load-bearing part of the grammar of some Rust
978    /// expressions, notably `return` and `break`. For example `return < …` will
979    /// never parse `<` as a binary operator regardless of what comes after,
980    /// because `<` is a legal starting token for an expression and so it's
981    /// required to be continued as a return value, such as `return <Struct as
982    /// Trait>::CONST`. Meanwhile `return > …` treats the `>` as a binary
983    /// operator because it cannot be a starting token for any Rust expression.
984    #[cfg(feature = "parsing")]
985    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
986    pub fn peek(input: ParseStream) -> bool {
987        input.peek(Ident::peek_any) && !input.peek(Token![as]) // value name or keyword
988            || input.peek(token::Paren) // tuple
989            || input.peek(token::Bracket) // array
990            || input.peek(token::Brace) // block
991            || input.peek(Lit) // literal
992            || input.peek(Token![!]) && !input.peek(Token![!=]) // operator not
993            || input.peek(Token![-]) && !input.peek(Token![-=]) && !input.peek(Token![->]) // unary minus
994            || input.peek(Token![*]) && !input.peek(Token![*=]) // dereference
995            || input.peek(Token![|]) && !input.peek(Token![|=]) // closure
996            || input.peek(Token![&]) && !input.peek(Token![&=]) // reference
997            || input.peek(Token![..]) // range
998            || input.peek(Token![<]) && !input.peek(Token![<=]) && !input.peek(Token![<<=]) // associated path
999            || input.peek(Token![::]) // absolute path
1000            || input.peek(Lifetime) // labeled loop
1001            || input.peek(Token![#]) // expression attributes
1002    }
1003
1004    #[cfg(all(feature = "parsing", feature = "full"))]
1005    pub(crate) fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
1006        match self {
1007            Expr::Array(ExprArray { attrs, .. })
1008            | Expr::Assign(ExprAssign { attrs, .. })
1009            | Expr::Async(ExprAsync { attrs, .. })
1010            | Expr::Await(ExprAwait { attrs, .. })
1011            | Expr::Binary(ExprBinary { attrs, .. })
1012            | Expr::Block(ExprBlock { attrs, .. })
1013            | Expr::Break(ExprBreak { attrs, .. })
1014            | Expr::Call(ExprCall { attrs, .. })
1015            | Expr::Cast(ExprCast { attrs, .. })
1016            | Expr::Closure(ExprClosure { attrs, .. })
1017            | Expr::Const(ExprConst { attrs, .. })
1018            | Expr::Continue(ExprContinue { attrs, .. })
1019            | Expr::Field(ExprField { attrs, .. })
1020            | Expr::ForLoop(ExprForLoop { attrs, .. })
1021            | Expr::Group(ExprGroup { attrs, .. })
1022            | Expr::If(ExprIf { attrs, .. })
1023            | Expr::Index(ExprIndex { attrs, .. })
1024            | Expr::Infer(ExprInfer { attrs, .. })
1025            | Expr::Let(ExprLet { attrs, .. })
1026            | Expr::Lit(ExprLit { attrs, .. })
1027            | Expr::Loop(ExprLoop { attrs, .. })
1028            | Expr::Macro(ExprMacro { attrs, .. })
1029            | Expr::Match(ExprMatch { attrs, .. })
1030            | Expr::MethodCall(ExprMethodCall { attrs, .. })
1031            | Expr::Paren(ExprParen { attrs, .. })
1032            | Expr::Path(ExprPath { attrs, .. })
1033            | Expr::Range(ExprRange { attrs, .. })
1034            | Expr::RawAddr(ExprRawAddr { attrs, .. })
1035            | Expr::Reference(ExprReference { attrs, .. })
1036            | Expr::Repeat(ExprRepeat { attrs, .. })
1037            | Expr::Return(ExprReturn { attrs, .. })
1038            | Expr::Struct(ExprStruct { attrs, .. })
1039            | Expr::Try(ExprTry { attrs, .. })
1040            | Expr::TryBlock(ExprTryBlock { attrs, .. })
1041            | Expr::Tuple(ExprTuple { attrs, .. })
1042            | Expr::Unary(ExprUnary { attrs, .. })
1043            | Expr::Unsafe(ExprUnsafe { attrs, .. })
1044            | Expr::While(ExprWhile { attrs, .. })
1045            | Expr::Yield(ExprYield { attrs, .. }) => mem::replace(attrs, new),
1046            Expr::Verbatim(_) => Vec::new(),
1047        }
1048    }
1049}
1050
1051ast_enum! {
1052    /// A struct or tuple struct field accessed in a struct literal or field
1053    /// expression.
1054    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
1055    pub enum Member {
1056        /// A named field like `self.x`.
1057        Named(Ident),
1058        /// An unnamed field like `self.0`.
1059        Unnamed(Index),
1060    }
1061}
1062
1063impl From<Ident> for Member {
1064    fn from(ident: Ident) -> Member {
1065        Member::Named(ident)
1066    }
1067}
1068
1069impl From<Index> for Member {
1070    fn from(index: Index) -> Member {
1071        Member::Unnamed(index)
1072    }
1073}
1074
1075impl From<usize> for Member {
1076    fn from(index: usize) -> Member {
1077        Member::Unnamed(Index::from(index))
1078    }
1079}
1080
1081impl Eq for Member {}
1082
1083impl PartialEq for Member {
1084    fn eq(&self, other: &Self) -> bool {
1085        match (self, other) {
1086            (Member::Named(this), Member::Named(other)) => this == other,
1087            (Member::Unnamed(this), Member::Unnamed(other)) => this == other,
1088            _ => false,
1089        }
1090    }
1091}
1092
1093impl Hash for Member {
1094    fn hash<H: Hasher>(&self, state: &mut H) {
1095        match self {
1096            Member::Named(m) => m.hash(state),
1097            Member::Unnamed(m) => m.hash(state),
1098        }
1099    }
1100}
1101
1102#[cfg(feature = "printing")]
1103impl IdentFragment for Member {
1104    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1105        match self {
1106            Member::Named(m) => Display::fmt(m, formatter),
1107            Member::Unnamed(m) => Display::fmt(&m.index, formatter),
1108        }
1109    }
1110
1111    fn span(&self) -> Option<Span> {
1112        match self {
1113            Member::Named(m) => Some(m.span()),
1114            Member::Unnamed(m) => Some(m.span),
1115        }
1116    }
1117}
1118
1119#[cfg(any(feature = "parsing", feature = "printing"))]
1120impl Member {
1121    pub(crate) fn is_named(&self) -> bool {
1122        match self {
1123            Member::Named(_) => true,
1124            Member::Unnamed(_) => false,
1125        }
1126    }
1127}
1128
1129ast_struct! {
1130    /// The index of an unnamed tuple struct field.
1131    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
1132    pub struct Index {
1133        pub index: u32,
1134        pub span: Span,
1135    }
1136}
1137
1138impl From<usize> for Index {
1139    fn from(index: usize) -> Index {
1140        assert!(index < u32::MAX as usize);
1141        Index {
1142            index: index as u32,
1143            span: Span::call_site(),
1144        }
1145    }
1146}
1147
1148impl Eq for Index {}
1149
1150impl PartialEq for Index {
1151    fn eq(&self, other: &Self) -> bool {
1152        self.index == other.index
1153    }
1154}
1155
1156impl Hash for Index {
1157    fn hash<H: Hasher>(&self, state: &mut H) {
1158        self.index.hash(state);
1159    }
1160}
1161
1162#[cfg(feature = "printing")]
1163impl IdentFragment for Index {
1164    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1165        Display::fmt(&self.index, formatter)
1166    }
1167
1168    fn span(&self) -> Option<Span> {
1169        Some(self.span)
1170    }
1171}
1172
1173ast_struct! {
1174    /// A field-value pair in a struct literal.
1175    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
1176    pub struct FieldValue {
1177        pub attrs: Vec<Attribute>,
1178        pub member: Member,
1179
1180        /// The colon in `Struct { x: x }`. If written in shorthand like
1181        /// `Struct { x }`, there is no colon.
1182        pub colon_token: Option<Token![:]>,
1183
1184        pub expr: Expr,
1185    }
1186}
1187
1188#[cfg(feature = "full")]
1189ast_struct! {
1190    /// A lifetime labeling a `for`, `while`, or `loop`.
1191    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
1192    pub struct Label {
1193        pub name: Lifetime,
1194        pub colon_token: Token![:],
1195    }
1196}
1197
1198#[cfg(feature = "full")]
1199ast_struct! {
1200    /// One arm of a `match` expression: `0..=10 => { return true; }`.
1201    ///
1202    /// As in:
1203    ///
1204    /// ```
1205    /// # fn f() -> bool {
1206    /// #     let n = 0;
1207    /// match n {
1208    ///     0..=10 => {
1209    ///         return true;
1210    ///     }
1211    ///     // ...
1212    ///     # _ => {}
1213    /// }
1214    /// #   false
1215    /// # }
1216    /// ```
1217    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
1218    pub struct Arm {
1219        pub attrs: Vec<Attribute>,
1220        pub pat: Pat,
1221        pub fat_arrow_token: Token![=>],
1222        pub body: Box<Expr>,
1223        pub comma: Option<Token![,]>,
1224    }
1225}
1226
1227#[cfg(feature = "full")]
1228ast_struct! {
1229    /// Additional optional information about a block.
1230    ///
1231    /// This data structure may grow to accommodate future Rust language
1232    /// changes, including the following in-progress RFCs:
1233    ///
1234    /// - [RFC 3680] "Simplify lightweight clones" (`async use { ... }`)
1235    /// - [#149488] "Heterogeneous try blocks" (`try bikeshed Option<_> { ... }`)
1236    ///
1237    /// [RFC 3680]: https://github.com/rust-lang/rust/issues/132290
1238    /// [#149488]: https://github.com/rust-lang/rust/issues/149488
1239    #[non_exhaustive]
1240    pub struct BlockModifiers {}
1241}
1242
1243#[cfg(feature = "full")]
1244impl Default for BlockModifiers {
1245    fn default() -> Self {
1246        BlockModifiers {}
1247    }
1248}
1249
1250#[cfg(feature = "full")]
1251impl BlockModifiers {
1252    #[cfg(feature = "parsing")]
1253    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1254    pub fn require_empty(&self) -> Result<()> {
1255        Ok(())
1256    }
1257}
1258
1259#[cfg(feature = "full")]
1260ast_enum! {
1261    /// Limit types of a range, inclusive or exclusive.
1262    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
1263    pub enum RangeLimits {
1264        /// Inclusive at the beginning, exclusive at the end.
1265        HalfOpen(Token![..]),
1266        /// Inclusive at the beginning and end.
1267        Closed(Token![..=]),
1268    }
1269}
1270
1271#[cfg(feature = "parsing")]
1272pub(crate) mod parsing {
1273    #[cfg(feature = "full")]
1274    use crate::attr;
1275    use crate::attr::Attribute;
1276    #[cfg(feature = "full")]
1277    use crate::buffer::Cursor;
1278    #[cfg(feature = "full")]
1279    use crate::classify;
1280    use crate::error::{Error, Result};
1281    #[cfg(feature = "full")]
1282    use crate::expr::{
1283        Arm, BlockModifiers, ClosureModifiers, ExprArray, ExprAssign, ExprAsync, ExprAwait,
1284        ExprBlock, ExprBreak, ExprClosure, ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer,
1285        ExprLet, ExprLoop, ExprMatch, ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry,
1286        ExprTryBlock, ExprUnsafe, ExprWhile, ExprYield, Label, RangeLimits,
1287    };
1288    use crate::expr::{
1289        Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro,
1290        ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprTuple, ExprUnary,
1291        FieldValue, Index, Member,
1292    };
1293    #[cfg(feature = "full")]
1294    use crate::generics::{self, BoundLifetimes};
1295    use crate::ident::Ident;
1296    use crate::lifetime::Lifetime;
1297    use crate::lit::{Lit, LitFloat, LitInt};
1298    use crate::mac::{self, Macro};
1299    use crate::op::BinOp;
1300    use crate::parse::discouraged::Speculative as _;
1301    use crate::parse::{End, Parse, ParseStream};
1302    #[cfg(feature = "full")]
1303    use crate::pat::{Pat, PatType};
1304    use crate::path::{self, AngleBracketedGenericArguments, Path, QSelf};
1305    use crate::precedence::Precedence;
1306    use crate::punctuated::Punctuated;
1307    #[cfg(feature = "full")]
1308    use crate::stmt::Block;
1309    use crate::token;
1310    use crate::ty;
1311    #[cfg(feature = "full")]
1312    use crate::ty::{PointerMutability, ReturnType, Type};
1313    use crate::verbatim;
1314    use alloc::boxed::Box;
1315    use alloc::format;
1316    use alloc::string::ToString;
1317    use alloc::vec::Vec;
1318    use core::mem;
1319    #[cfg(feature = "full")]
1320    use proc_macro2::{Span, TokenStream};
1321
1322    // When we're parsing expressions which occur before blocks, like in an if
1323    // statement's condition, we cannot parse a struct literal.
1324    //
1325    // Struct literals are ambiguous in certain positions
1326    // https://github.com/rust-lang/rfcs/pull/92
1327    #[cfg(feature = "full")]
1328    pub(super) struct AllowStruct(pub bool);
1329
1330    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1331    impl Parse for Expr {
1332        fn parse(input: ParseStream) -> Result<Self> {
1333            ambiguous_expr(
1334                input,
1335                #[cfg(feature = "full")]
1336                AllowStruct(true),
1337            )
1338        }
1339    }
1340
1341    #[cfg(feature = "full")]
1342    pub(super) fn parse_with_earlier_boundary_rule(input: ParseStream) -> Result<Expr> {
1343        let mut attrs = input.call(expr_attrs)?;
1344        let mut expr = if input.peek(token::Group) && {
1345            let group = crate::group::parse_group(&input.fork())?;
1346            !(group.content.peek(Lifetime) && group.content.peek2(End))
1347        } {
1348            let allow_struct = AllowStruct(true);
1349            let atom = expr_group(input, allow_struct)?;
1350            if continue_parsing_early(&atom) {
1351                trailer_helper(input, atom)?
1352            } else {
1353                atom
1354            }
1355        } else if input.peek(Token![if]) {
1356            Expr::If(input.parse()?)
1357        } else if input.peek(Token![while]) {
1358            Expr::While(input.parse()?)
1359        } else if input.peek(Token![for])
1360            && !generics::parsing::choose_generics_over_qpath_after_keyword(input)
1361        {
1362            Expr::ForLoop(input.parse()?)
1363        } else if input.peek(Token![loop]) {
1364            Expr::Loop(input.parse()?)
1365        } else if input.peek(Token![match]) {
1366            Expr::Match(input.parse()?)
1367        } else if input.peek(Token![try]) && input.peek2(token::Brace) {
1368            Expr::TryBlock(input.parse()?)
1369        } else if input.peek(Token![unsafe]) {
1370            Expr::Unsafe(input.parse()?)
1371        } else if input.peek(Token![const]) && input.peek2(token::Brace) {
1372            Expr::Const(input.parse()?)
1373        } else if input.peek(token::Brace) {
1374            Expr::Block(input.parse()?)
1375        } else if input.peek(Lifetime) {
1376            atom_labeled(input)?
1377        } else {
1378            let allow_struct = AllowStruct(true);
1379            unary_expr(input, allow_struct)?
1380        };
1381
1382        if continue_parsing_early(&expr) {
1383            attrs.extend(expr.replace_attrs(Vec::new()));
1384            expr.replace_attrs(attrs);
1385
1386            let allow_struct = AllowStruct(true);
1387            return parse_expr(input, expr, allow_struct, Precedence::MIN);
1388        }
1389
1390        if input.peek(Token![.]) && !input.peek(Token![..]) || input.peek(Token![?]) {
1391            expr = trailer_helper(input, expr)?;
1392
1393            attrs.extend(expr.replace_attrs(Vec::new()));
1394            expr.replace_attrs(attrs);
1395
1396            let allow_struct = AllowStruct(true);
1397            return parse_expr(input, expr, allow_struct, Precedence::MIN);
1398        }
1399
1400        attrs.extend(expr.replace_attrs(Vec::new()));
1401        expr.replace_attrs(attrs);
1402        Ok(expr)
1403    }
1404
1405    #[cfg(feature = "full")]
1406    impl Copy for AllowStruct {}
1407
1408    #[cfg(feature = "full")]
1409    impl Clone for AllowStruct {
1410        fn clone(&self) -> Self {
1411            *self
1412        }
1413    }
1414
1415    #[cfg(feature = "full")]
1416    fn parse_expr(
1417        input: ParseStream,
1418        mut lhs: Expr,
1419        allow_struct: AllowStruct,
1420        base: Precedence,
1421    ) -> Result<Expr> {
1422        loop {
1423            let ahead = input.fork();
1424            if let Expr::Range(_) = lhs {
1425                // A range cannot be the left-hand side of another binary operator.
1426                break;
1427            } else if let Ok(op) = ahead.parse::<BinOp>() {
1428                let precedence = Precedence::of_binop(&op);
1429                if precedence < base {
1430                    break;
1431                }
1432                if precedence == Precedence::Assign {
1433                    if let Expr::Range(_) = lhs {
1434                        break;
1435                    }
1436                }
1437                if precedence == Precedence::Compare {
1438                    if let Expr::Binary(lhs) = &lhs {
1439                        if Precedence::of_binop(&lhs.op) == Precedence::Compare {
1440                            return Err(input.error("comparison operators cannot be chained"));
1441                        }
1442                    }
1443                }
1444                input.advance_to(&ahead);
1445                let right = parse_binop_rhs(input, allow_struct, precedence)?;
1446                lhs = Expr::Binary(ExprBinary {
1447                    attrs: Vec::new(),
1448                    left: Box::new(lhs),
1449                    op,
1450                    right,
1451                });
1452            } else if Precedence::Assign >= base
1453                && input.peek(Token![=])
1454                && !input.peek(Token![=>])
1455                && match lhs {
1456                    Expr::Range(_) => false,
1457                    _ => true,
1458                }
1459            {
1460                let eq_token: Token![=] = input.parse()?;
1461                let right = parse_binop_rhs(input, allow_struct, Precedence::Assign)?;
1462                lhs = Expr::Assign(ExprAssign {
1463                    attrs: Vec::new(),
1464                    left: Box::new(lhs),
1465                    eq_token,
1466                    right,
1467                });
1468            } else if Precedence::Range >= base && input.peek(Token![..]) {
1469                let limits: RangeLimits = input.parse()?;
1470                let end = parse_range_end(input, &limits, allow_struct)?;
1471                lhs = Expr::Range(ExprRange {
1472                    attrs: Vec::new(),
1473                    start: Some(Box::new(lhs)),
1474                    limits,
1475                    end,
1476                });
1477            } else if Precedence::Cast >= base && input.peek(Token![as]) {
1478                let as_token: Token![as] = input.parse()?;
1479                let allow_plus = false;
1480                let allow_group_generic = false;
1481                let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
1482                check_cast(input)?;
1483                lhs = Expr::Cast(ExprCast {
1484                    attrs: Vec::new(),
1485                    expr: Box::new(lhs),
1486                    as_token,
1487                    ty: Box::new(ty),
1488                });
1489            } else if input.peek(Token![<-]) {
1490                return Err(input.error("unexpected operator `<-`, if this is intended to be a comparison against a negative then a space is required: `< -`"));
1491            } else {
1492                break;
1493            }
1494        }
1495        Ok(lhs)
1496    }
1497
1498    #[cfg(not(feature = "full"))]
1499    fn parse_expr(input: ParseStream, mut lhs: Expr, base: Precedence) -> Result<Expr> {
1500        loop {
1501            let ahead = input.fork();
1502            if let Ok(op) = ahead.parse::<BinOp>() {
1503                let precedence = Precedence::of_binop(&op);
1504                if precedence < base {
1505                    break;
1506                }
1507                if precedence == Precedence::Compare {
1508                    if let Expr::Binary(lhs) = &lhs {
1509                        if Precedence::of_binop(&lhs.op) == Precedence::Compare {
1510                            return Err(input.error("comparison operators cannot be chained"));
1511                        }
1512                    }
1513                }
1514                input.advance_to(&ahead);
1515                let right = parse_binop_rhs(input, precedence)?;
1516                lhs = Expr::Binary(ExprBinary {
1517                    attrs: Vec::new(),
1518                    left: Box::new(lhs),
1519                    op,
1520                    right,
1521                });
1522            } else if Precedence::Cast >= base && input.peek(Token![as]) {
1523                let as_token: Token![as] = input.parse()?;
1524                let allow_plus = false;
1525                let allow_group_generic = false;
1526                let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
1527                check_cast(input)?;
1528                lhs = Expr::Cast(ExprCast {
1529                    attrs: Vec::new(),
1530                    expr: Box::new(lhs),
1531                    as_token,
1532                    ty: Box::new(ty),
1533                });
1534            } else if input.peek(Token![<-]) {
1535                return Err(input.error("unexpected operator `<-`, if this is intended to be a comparison against a negative then a space is required: `< -`"));
1536            } else {
1537                break;
1538            }
1539        }
1540        Ok(lhs)
1541    }
1542
1543    fn parse_binop_rhs(
1544        input: ParseStream,
1545        #[cfg(feature = "full")] allow_struct: AllowStruct,
1546        precedence: Precedence,
1547    ) -> Result<Box<Expr>> {
1548        let mut rhs = unary_expr(
1549            input,
1550            #[cfg(feature = "full")]
1551            allow_struct,
1552        )?;
1553        loop {
1554            let next = peek_precedence(input);
1555            if next > precedence || next == precedence && precedence == Precedence::Assign {
1556                let cursor = input.cursor();
1557                rhs = parse_expr(
1558                    input,
1559                    rhs,
1560                    #[cfg(feature = "full")]
1561                    allow_struct,
1562                    next,
1563                )?;
1564                if cursor == input.cursor() {
1565                    // Bespoke grammar restrictions separate from precedence can
1566                    // cause parsing to not advance, such as `..a` being
1567                    // disallowed in the left-hand side of binary operators,
1568                    // even ones that have lower precedence than `..`.
1569                    break;
1570                }
1571            } else {
1572                break;
1573            }
1574        }
1575        Ok(Box::new(rhs))
1576    }
1577
1578    fn peek_precedence(input: ParseStream) -> Precedence {
1579        if let Ok(op) = input.fork().parse() {
1580            Precedence::of_binop(&op)
1581        } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
1582            Precedence::Assign
1583        } else if input.peek(Token![..]) {
1584            Precedence::Range
1585        } else if input.peek(Token![as]) {
1586            Precedence::Cast
1587        } else {
1588            Precedence::MIN
1589        }
1590    }
1591
1592    // Parse an arbitrary expression.
1593    pub(super) fn ambiguous_expr(
1594        input: ParseStream,
1595        #[cfg(feature = "full")] allow_struct: AllowStruct,
1596    ) -> Result<Expr> {
1597        let lhs = unary_expr(
1598            input,
1599            #[cfg(feature = "full")]
1600            allow_struct,
1601        )?;
1602        parse_expr(
1603            input,
1604            lhs,
1605            #[cfg(feature = "full")]
1606            allow_struct,
1607            Precedence::MIN,
1608        )
1609    }
1610
1611    #[cfg(feature = "full")]
1612    fn expr_attrs(input: ParseStream) -> Result<Vec<Attribute>> {
1613        let mut attrs = Vec::new();
1614        while !input.peek(token::Group) && input.peek(Token![#]) {
1615            attrs.push(input.call(attr::parsing::single_parse_outer)?);
1616        }
1617        Ok(attrs)
1618    }
1619
1620    // <UnOp> <trailer>
1621    // & <trailer>
1622    // &mut <trailer>
1623    // box <trailer>
1624    #[cfg(feature = "full")]
1625    fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1626        let begin = input.cursor();
1627        let attrs = input.call(expr_attrs)?;
1628        if input.peek(token::Group) {
1629            return trailer_expr(begin, attrs, input, allow_struct);
1630        }
1631
1632        if input.peek(Token![&]) {
1633            let and_token: Token![&] = input.parse()?;
1634            let raw: Option<Token![raw]> = if input.peek(Token![raw])
1635                && (input.peek2(Token![mut]) || input.peek2(Token![const]))
1636            {
1637                Some(input.parse()?)
1638            } else {
1639                None
1640            };
1641            let mutability: Option<Token![mut]> = input.parse()?;
1642            let const_token: Option<Token![const]> = if raw.is_some() && mutability.is_none() {
1643                Some(input.parse()?)
1644            } else {
1645                None
1646            };
1647            let expr = Box::new(unary_expr(input, allow_struct)?);
1648            if let Some(raw) = raw {
1649                Ok(Expr::RawAddr(ExprRawAddr {
1650                    attrs,
1651                    and_token,
1652                    raw,
1653                    mutability: match mutability {
1654                        Some(mut_token) => PointerMutability::Mut(mut_token),
1655                        None => PointerMutability::Const(const_token.unwrap()),
1656                    },
1657                    expr,
1658                }))
1659            } else {
1660                Ok(Expr::Reference(ExprReference {
1661                    attrs,
1662                    and_token,
1663                    mutability,
1664                    expr,
1665                }))
1666            }
1667        } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
1668            expr_unary(input, attrs, allow_struct).map(Expr::Unary)
1669        } else {
1670            trailer_expr(begin, attrs, input, allow_struct)
1671        }
1672    }
1673
1674    #[cfg(not(feature = "full"))]
1675    fn unary_expr(input: ParseStream) -> Result<Expr> {
1676        if input.peek(Token![&]) {
1677            Ok(Expr::Reference(ExprReference {
1678                attrs: Vec::new(),
1679                and_token: input.parse()?,
1680                mutability: input.parse()?,
1681                expr: Box::new(unary_expr(input)?),
1682            }))
1683        } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
1684            Ok(Expr::Unary(ExprUnary {
1685                attrs: Vec::new(),
1686                op: input.parse()?,
1687                expr: Box::new(unary_expr(input)?),
1688            }))
1689        } else {
1690            trailer_expr(input)
1691        }
1692    }
1693
1694    // <atom> (..<args>) ...
1695    // <atom> . <ident> (..<args>) ...
1696    // <atom> . <ident> ...
1697    // <atom> . <lit> ...
1698    // <atom> [ <expr> ] ...
1699    // <atom> ? ...
1700    #[cfg(feature = "full")]
1701    fn trailer_expr(
1702        begin: Cursor,
1703        mut attrs: Vec<Attribute>,
1704        input: ParseStream,
1705        allow_struct: AllowStruct,
1706    ) -> Result<Expr> {
1707        let atom = atom_expr(input, allow_struct)?;
1708        let mut e = trailer_helper(input, atom)?;
1709
1710        if let Expr::Verbatim(tokens) = &mut e {
1711            *tokens = verbatim::between(begin, input.cursor());
1712        } else if !attrs.is_empty() {
1713            if let Expr::Range(range) = e {
1714                let spans: &[Span] = match &range.limits {
1715                    RangeLimits::HalfOpen(limits) => &limits.spans,
1716                    RangeLimits::Closed(limits) => &limits.spans,
1717                };
1718                return Err(crate::error::new2(
1719                    spans[0],
1720                    *spans.last().unwrap(),
1721                    "attributes are not allowed on range expressions starting with `..`",
1722                ));
1723            }
1724            let inner_attrs = e.replace_attrs(Vec::new());
1725            attrs.extend(inner_attrs);
1726            e.replace_attrs(attrs);
1727        }
1728
1729        Ok(e)
1730    }
1731
1732    #[cfg(feature = "full")]
1733    fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
1734        loop {
1735            if input.peek(token::Paren) {
1736                let content;
1737                e = Expr::Call(ExprCall {
1738                    attrs: Vec::new(),
1739                    func: Box::new(e),
1740                    paren_token: parenthesized!(content in input),
1741                    args: content.parse_terminated(Expr::parse, Token![,])?,
1742                });
1743            } else if input.peek(Token![.])
1744                && !input.peek(Token![..])
1745                && match e {
1746                    Expr::Range(_) => false,
1747                    _ => true,
1748                }
1749            {
1750                let mut dot_token: Token![.] = input.parse()?;
1751
1752                let float_token: Option<LitFloat> = input.parse()?;
1753                if let Some(float_token) = float_token {
1754                    if multi_index(&mut e, &mut dot_token, float_token)? {
1755                        continue;
1756                    }
1757                }
1758
1759                let await_token: Option<Token![await]> = input.parse()?;
1760                if let Some(await_token) = await_token {
1761                    e = Expr::Await(ExprAwait {
1762                        attrs: Vec::new(),
1763                        base: Box::new(e),
1764                        dot_token,
1765                        await_token,
1766                    });
1767                    continue;
1768                }
1769
1770                let member: Member = input.parse()?;
1771                let turbofish = if member.is_named() && input.peek(Token![::]) {
1772                    Some(AngleBracketedGenericArguments::parse_turbofish(input)?)
1773                } else {
1774                    None
1775                };
1776
1777                if turbofish.is_some() || input.peek(token::Paren) {
1778                    if let Member::Named(method) = member {
1779                        let content;
1780                        e = Expr::MethodCall(ExprMethodCall {
1781                            attrs: Vec::new(),
1782                            receiver: Box::new(e),
1783                            dot_token,
1784                            method,
1785                            turbofish,
1786                            paren_token: parenthesized!(content in input),
1787                            args: content.parse_terminated(Expr::parse, Token![,])?,
1788                        });
1789                        continue;
1790                    }
1791                }
1792
1793                e = Expr::Field(ExprField {
1794                    attrs: Vec::new(),
1795                    base: Box::new(e),
1796                    dot_token,
1797                    member,
1798                });
1799            } else if input.peek(token::Bracket) {
1800                let content;
1801                e = Expr::Index(ExprIndex {
1802                    attrs: Vec::new(),
1803                    expr: Box::new(e),
1804                    bracket_token: bracketed!(content in input),
1805                    index: content.parse()?,
1806                });
1807            } else if input.peek(Token![?])
1808                && match e {
1809                    Expr::Range(_) => false,
1810                    _ => true,
1811                }
1812            {
1813                e = Expr::Try(ExprTry {
1814                    attrs: Vec::new(),
1815                    expr: Box::new(e),
1816                    question_token: input.parse()?,
1817                });
1818            } else {
1819                break;
1820            }
1821        }
1822        Ok(e)
1823    }
1824
1825    #[cfg(not(feature = "full"))]
1826    fn trailer_expr(input: ParseStream) -> Result<Expr> {
1827        let mut e = atom_expr(input)?;
1828
1829        loop {
1830            if input.peek(token::Paren) {
1831                let content;
1832                e = Expr::Call(ExprCall {
1833                    attrs: Vec::new(),
1834                    func: Box::new(e),
1835                    paren_token: parenthesized!(content in input),
1836                    args: content.parse_terminated(Expr::parse, Token![,])?,
1837                });
1838            } else if input.peek(Token![.])
1839                && !input.peek(Token![..])
1840                && !input.peek2(Token![await])
1841            {
1842                let mut dot_token: Token![.] = input.parse()?;
1843
1844                let float_token: Option<LitFloat> = input.parse()?;
1845                if let Some(float_token) = float_token {
1846                    if multi_index(&mut e, &mut dot_token, float_token)? {
1847                        continue;
1848                    }
1849                }
1850
1851                let member: Member = input.parse()?;
1852                let turbofish = if member.is_named() && input.peek(Token![::]) {
1853                    let colon2_token: Token![::] = input.parse()?;
1854                    let turbofish =
1855                        AngleBracketedGenericArguments::do_parse(Some(colon2_token), input)?;
1856                    Some(turbofish)
1857                } else {
1858                    None
1859                };
1860
1861                if turbofish.is_some() || input.peek(token::Paren) {
1862                    if let Member::Named(method) = member {
1863                        let content;
1864                        e = Expr::MethodCall(ExprMethodCall {
1865                            attrs: Vec::new(),
1866                            receiver: Box::new(e),
1867                            dot_token,
1868                            method,
1869                            turbofish,
1870                            paren_token: parenthesized!(content in input),
1871                            args: content.parse_terminated(Expr::parse, Token![,])?,
1872                        });
1873                        continue;
1874                    }
1875                }
1876
1877                e = Expr::Field(ExprField {
1878                    attrs: Vec::new(),
1879                    base: Box::new(e),
1880                    dot_token,
1881                    member,
1882                });
1883            } else if input.peek(token::Bracket) {
1884                let content;
1885                e = Expr::Index(ExprIndex {
1886                    attrs: Vec::new(),
1887                    expr: Box::new(e),
1888                    bracket_token: bracketed!(content in input),
1889                    index: content.parse()?,
1890                });
1891            } else {
1892                break;
1893            }
1894        }
1895
1896        Ok(e)
1897    }
1898
1899    // Parse all atomic expressions which don't have to worry about precedence
1900    // interactions, as they are fully contained.
1901    #[cfg(feature = "full")]
1902    fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1903        if input.peek(token::Group) && {
1904            let group = crate::group::parse_group(&input.fork())?;
1905            !(group.content.peek(Lifetime) && group.content.peek2(End))
1906        } {
1907            expr_group(input, allow_struct)
1908        } else if input.peek(Lit) {
1909            input.parse().map(Expr::Lit)
1910        } else if input.peek(Token![async])
1911            && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
1912        {
1913            input.parse().map(Expr::Async)
1914        } else if input.peek(Token![try]) && input.peek2(token::Brace) {
1915            input.parse().map(Expr::TryBlock)
1916        } else if input.peek(Token![|])
1917            || input.peek(Token![move])
1918            || input.peek(Token![for])
1919                && generics::parsing::choose_generics_over_qpath_after_keyword(input)
1920            || input.peek(Token![const]) && !input.peek2(token::Brace)
1921            || input.peek(Token![static])
1922            || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1923        {
1924            expr_closure(input, allow_struct).map(Expr::Closure)
1925        } else if input.cursor().peek_keyword("builtin") && input.peek2(Token![#]) {
1926            expr_builtin(input)
1927        } else if input.peek(Ident)
1928            || input.peek(Token![::])
1929            || input.peek(Token![<])
1930            || input.peek(Token![self])
1931            || input.peek(Token![Self])
1932            || input.peek(Token![super])
1933            || input.peek(Token![crate])
1934            || input.peek(Token![try]) && (input.peek2(Token![!]) || input.peek2(Token![::]))
1935        {
1936            path_or_macro_or_struct(input, allow_struct)
1937        } else if input.peek(token::Paren) {
1938            paren_or_tuple(input)
1939        } else if input.peek(Token![break]) {
1940            expr_break(input, allow_struct).map(Expr::Break)
1941        } else if input.peek(Token![continue]) {
1942            input.parse().map(Expr::Continue)
1943        } else if input.peek(Token![return]) {
1944            input.parse().map(Expr::Return)
1945        } else if input.peek(Token![become]) {
1946            expr_become(input)
1947        } else if input.peek(token::Bracket) {
1948            array_or_repeat(input)
1949        } else if input.peek(Token![let]) {
1950            expr_let(input, allow_struct).map(Expr::Let)
1951        } else if input.peek(Token![if]) {
1952            input.parse().map(Expr::If)
1953        } else if input.peek(Token![while]) {
1954            input.parse().map(Expr::While)
1955        } else if input.peek(Token![for]) {
1956            input.parse().map(Expr::ForLoop)
1957        } else if input.peek(Token![loop]) {
1958            input.parse().map(Expr::Loop)
1959        } else if input.peek(Token![match]) {
1960            input.parse().map(Expr::Match)
1961        } else if input.peek(Token![yield]) {
1962            input.parse().map(Expr::Yield)
1963        } else if input.peek(Token![unsafe]) {
1964            input.parse().map(Expr::Unsafe)
1965        } else if input.peek(Token![const]) {
1966            input.parse().map(Expr::Const)
1967        } else if input.peek(token::Brace) {
1968            input.parse().map(Expr::Block)
1969        } else if input.peek(Token![..]) {
1970            expr_range(input, allow_struct).map(Expr::Range)
1971        } else if input.peek(Token![_]) {
1972            input.parse().map(Expr::Infer)
1973        } else if input.peek(Lifetime) {
1974            atom_labeled(input)
1975        } else {
1976            Err(input.error("expected an expression"))
1977        }
1978    }
1979
1980    #[cfg(feature = "full")]
1981    fn atom_labeled(input: ParseStream) -> Result<Expr> {
1982        let the_label: Label = input.parse()?;
1983        let mut expr = if input.peek(Token![while]) {
1984            Expr::While(input.parse()?)
1985        } else if input.peek(Token![for]) {
1986            Expr::ForLoop(input.parse()?)
1987        } else if input.peek(Token![loop]) {
1988            Expr::Loop(input.parse()?)
1989        } else if input.peek(token::Brace) {
1990            Expr::Block(input.parse()?)
1991        } else {
1992            return Err(input.error("expected loop or block expression"));
1993        };
1994        match &mut expr {
1995            Expr::While(ExprWhile { label, .. })
1996            | Expr::ForLoop(ExprForLoop { label, .. })
1997            | Expr::Loop(ExprLoop { label, .. })
1998            | Expr::Block(ExprBlock { label, .. }) => *label = Some(the_label),
1999            _ => unreachable!(),
2000        }
2001        Ok(expr)
2002    }
2003
2004    #[cfg(not(feature = "full"))]
2005    fn atom_expr(input: ParseStream) -> Result<Expr> {
2006        if input.peek(token::Group) && {
2007            let group = crate::group::parse_group(&input.fork())?;
2008            !(group.content.peek(Lifetime) && group.content.peek2(End))
2009        } {
2010            expr_group(input)
2011        } else if input.peek(Lit) {
2012            input.parse().map(Expr::Lit)
2013        } else if input.peek(token::Paren) {
2014            paren_or_tuple(input)
2015        } else if input.peek(Ident)
2016            || input.peek(Token![::])
2017            || input.peek(Token![<])
2018            || input.peek(Token![self])
2019            || input.peek(Token![Self])
2020            || input.peek(Token![super])
2021            || input.peek(Token![crate])
2022        {
2023            path_or_macro_or_struct(input)
2024        } else if input.is_empty() {
2025            Err(input.error("expected an expression"))
2026        } else {
2027            if input.peek(token::Brace) {
2028                let scan = input.fork();
2029                let content;
2030                braced!(content in scan);
2031                if content.parse::<Expr>().is_ok() && content.is_empty() {
2032                    let expr_block = verbatim::between(input.cursor(), scan.cursor());
2033                    input.advance_to(&scan);
2034                    return Ok(Expr::Verbatim(expr_block));
2035                }
2036            }
2037            Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
2038        }
2039    }
2040
2041    #[cfg(feature = "full")]
2042    fn expr_builtin(input: ParseStream) -> Result<Expr> {
2043        let begin = input.cursor();
2044
2045        token::parsing::keyword(input, "builtin")?;
2046        input.parse::<Token![#]>()?;
2047        input.parse::<Ident>()?;
2048
2049        let args;
2050        parenthesized!(args in input);
2051        args.parse::<TokenStream>()?;
2052
2053        Ok(Expr::Verbatim(verbatim::between(begin, input.cursor())))
2054    }
2055
2056    fn path_or_macro_or_struct(
2057        input: ParseStream,
2058        #[cfg(feature = "full")] allow_struct: AllowStruct,
2059    ) -> Result<Expr> {
2060        let expr_style = true;
2061        let (qself, path) = path::parsing::qpath(input, expr_style)?;
2062        rest_of_path_or_macro_or_struct(
2063            qself,
2064            path,
2065            input,
2066            #[cfg(feature = "full")]
2067            allow_struct,
2068        )
2069    }
2070
2071    fn rest_of_path_or_macro_or_struct(
2072        qself: Option<QSelf>,
2073        path: Path,
2074        input: ParseStream,
2075        #[cfg(feature = "full")] allow_struct: AllowStruct,
2076    ) -> Result<Expr> {
2077        if qself.is_none()
2078            && input.peek(Token![!])
2079            && !input.peek(Token![!=])
2080            && path.is_mod_style()
2081        {
2082            let bang_token: Token![!] = input.parse()?;
2083            let (delimiter, tokens) = mac::parse_delimiter(input)?;
2084            return Ok(Expr::Macro(ExprMacro {
2085                attrs: Vec::new(),
2086                mac: Macro {
2087                    path,
2088                    bang_token,
2089                    delimiter,
2090                    tokens,
2091                },
2092            }));
2093        }
2094
2095        #[cfg(not(feature = "full"))]
2096        let allow_struct = (true,);
2097        if allow_struct.0 && input.peek(token::Brace) {
2098            return expr_struct_helper(input, qself, path).map(Expr::Struct);
2099        }
2100
2101        Ok(Expr::Path(ExprPath {
2102            attrs: Vec::new(),
2103            qself,
2104            path,
2105        }))
2106    }
2107
2108    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2109    impl Parse for ExprMacro {
2110        fn parse(input: ParseStream) -> Result<Self> {
2111            Ok(ExprMacro {
2112                attrs: Vec::new(),
2113                mac: input.parse()?,
2114            })
2115        }
2116    }
2117
2118    fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
2119        let content;
2120        let paren_token = parenthesized!(content in input);
2121        if content.is_empty() {
2122            return Ok(Expr::Tuple(ExprTuple {
2123                attrs: Vec::new(),
2124                paren_token,
2125                elems: Punctuated::new(),
2126            }));
2127        }
2128
2129        let first: Expr = content.parse()?;
2130        if content.is_empty() {
2131            return Ok(Expr::Paren(ExprParen {
2132                attrs: Vec::new(),
2133                paren_token,
2134                expr: Box::new(first),
2135            }));
2136        }
2137
2138        let mut elems = Punctuated::new();
2139        elems.push_value(first);
2140        while !content.is_empty() {
2141            let punct = content.parse()?;
2142            elems.push_punct(punct);
2143            if content.is_empty() {
2144                break;
2145            }
2146            let value = content.parse()?;
2147            elems.push_value(value);
2148        }
2149        Ok(Expr::Tuple(ExprTuple {
2150            attrs: Vec::new(),
2151            paren_token,
2152            elems,
2153        }))
2154    }
2155
2156    #[cfg(feature = "full")]
2157    fn array_or_repeat(input: ParseStream) -> Result<Expr> {
2158        let content;
2159        let bracket_token = bracketed!(content in input);
2160        if content.is_empty() {
2161            return Ok(Expr::Array(ExprArray {
2162                attrs: Vec::new(),
2163                bracket_token,
2164                elems: Punctuated::new(),
2165            }));
2166        }
2167
2168        let first: Expr = content.parse()?;
2169        if content.is_empty() || content.peek(Token![,]) {
2170            let mut elems = Punctuated::new();
2171            elems.push_value(first);
2172            while !content.is_empty() {
2173                let punct = content.parse()?;
2174                elems.push_punct(punct);
2175                if content.is_empty() {
2176                    break;
2177                }
2178                let value = content.parse()?;
2179                elems.push_value(value);
2180            }
2181            Ok(Expr::Array(ExprArray {
2182                attrs: Vec::new(),
2183                bracket_token,
2184                elems,
2185            }))
2186        } else if content.peek(Token![;]) {
2187            let semi_token: Token![;] = content.parse()?;
2188            let len: Expr = content.parse()?;
2189            Ok(Expr::Repeat(ExprRepeat {
2190                attrs: Vec::new(),
2191                bracket_token,
2192                expr: Box::new(first),
2193                semi_token,
2194                len: Box::new(len),
2195            }))
2196        } else {
2197            Err(content.error("expected `,` or `;`"))
2198        }
2199    }
2200
2201    #[cfg(feature = "full")]
2202    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2203    impl Parse for ExprArray {
2204        fn parse(input: ParseStream) -> Result<Self> {
2205            let content;
2206            let bracket_token = bracketed!(content in input);
2207            let mut elems = Punctuated::new();
2208
2209            while !content.is_empty() {
2210                let first: Expr = content.parse()?;
2211                elems.push_value(first);
2212                if content.is_empty() {
2213                    break;
2214                }
2215                let punct = content.parse()?;
2216                elems.push_punct(punct);
2217            }
2218
2219            Ok(ExprArray {
2220                attrs: Vec::new(),
2221                bracket_token,
2222                elems,
2223            })
2224        }
2225    }
2226
2227    #[cfg(feature = "full")]
2228    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2229    impl Parse for ExprRepeat {
2230        fn parse(input: ParseStream) -> Result<Self> {
2231            let content;
2232            Ok(ExprRepeat {
2233                bracket_token: bracketed!(content in input),
2234                attrs: Vec::new(),
2235                expr: content.parse()?,
2236                semi_token: content.parse()?,
2237                len: content.parse()?,
2238            })
2239        }
2240    }
2241
2242    #[cfg(feature = "full")]
2243    fn continue_parsing_early(mut expr: &Expr) -> bool {
2244        while let Expr::Group(group) = expr {
2245            expr = &group.expr;
2246        }
2247        match expr {
2248            Expr::If(_)
2249            | Expr::While(_)
2250            | Expr::ForLoop(_)
2251            | Expr::Loop(_)
2252            | Expr::Match(_)
2253            | Expr::TryBlock(_)
2254            | Expr::Unsafe(_)
2255            | Expr::Const(_)
2256            | Expr::Block(_) => false,
2257            _ => true,
2258        }
2259    }
2260
2261    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2262    impl Parse for ExprLit {
2263        fn parse(input: ParseStream) -> Result<Self> {
2264            Ok(ExprLit {
2265                attrs: Vec::new(),
2266                lit: input.parse()?,
2267            })
2268        }
2269    }
2270
2271    fn expr_group(
2272        input: ParseStream,
2273        #[cfg(feature = "full")] allow_struct: AllowStruct,
2274    ) -> Result<Expr> {
2275        let group = crate::group::parse_group(input)?;
2276        let mut inner: Expr = group.content.parse()?;
2277
2278        match inner {
2279            Expr::Path(mut expr) if expr.attrs.is_empty() => {
2280                let grouped_len = expr.path.segments.len();
2281                Path::parse_rest(input, &mut expr.path, true)?;
2282                match rest_of_path_or_macro_or_struct(
2283                    expr.qself,
2284                    expr.path,
2285                    input,
2286                    #[cfg(feature = "full")]
2287                    allow_struct,
2288                )? {
2289                    Expr::Path(expr) if expr.path.segments.len() == grouped_len => {
2290                        inner = Expr::Path(expr);
2291                    }
2292                    extended => return Ok(extended),
2293                }
2294            }
2295            _ => {}
2296        }
2297
2298        Ok(Expr::Group(ExprGroup {
2299            attrs: Vec::new(),
2300            group_token: group.token,
2301            expr: Box::new(inner),
2302        }))
2303    }
2304
2305    #[cfg(feature = "full")]
2306    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2307    impl Parse for ExprParen {
2308        fn parse(input: ParseStream) -> Result<Self> {
2309            let content;
2310            Ok(ExprParen {
2311                attrs: Vec::new(),
2312                paren_token: parenthesized!(content in input),
2313                expr: content.parse()?,
2314            })
2315        }
2316    }
2317
2318    #[cfg(feature = "full")]
2319    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2320    impl Parse for ExprLet {
2321        fn parse(input: ParseStream) -> Result<Self> {
2322            let allow_struct = AllowStruct(true);
2323            expr_let(input, allow_struct)
2324        }
2325    }
2326
2327    #[cfg(feature = "full")]
2328    fn expr_let(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprLet> {
2329        Ok(ExprLet {
2330            attrs: Vec::new(),
2331            let_token: input.parse()?,
2332            pat: Box::new(Pat::parse_multi_with_leading_vert(input)?),
2333            eq_token: input.parse()?,
2334            expr: Box::new({
2335                let lhs = unary_expr(input, allow_struct)?;
2336                parse_expr(input, lhs, allow_struct, Precedence::Compare)?
2337            }),
2338        })
2339    }
2340
2341    #[cfg(feature = "full")]
2342    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2343    impl Parse for ExprIf {
2344        fn parse(input: ParseStream) -> Result<Self> {
2345            let attrs = input.call(Attribute::parse_outer)?;
2346
2347            let mut clauses = Vec::new();
2348            let mut expr;
2349            loop {
2350                let if_token: Token![if] = input.parse()?;
2351                let cond = input.call(Expr::parse_without_eager_brace)?;
2352                let then_branch: Block = input.parse()?;
2353
2354                expr = ExprIf {
2355                    attrs: Vec::new(),
2356                    if_token,
2357                    cond: Box::new(cond),
2358                    then_branch,
2359                    else_branch: None,
2360                };
2361
2362                if !input.peek(Token![else]) {
2363                    break;
2364                }
2365
2366                let else_token: Token![else] = input.parse()?;
2367                let lookahead = input.lookahead1();
2368                if lookahead.peek(Token![if]) {
2369                    expr.else_branch = Some((else_token, Box::new(Expr::PLACEHOLDER)));
2370                    clauses.push(expr);
2371                } else if lookahead.peek(token::Brace) {
2372                    expr.else_branch = Some((
2373                        else_token,
2374                        Box::new(Expr::Block(ExprBlock {
2375                            attrs: Vec::new(),
2376                            label: None,
2377                            block: input.parse()?,
2378                        })),
2379                    ));
2380                    break;
2381                } else {
2382                    return Err(lookahead.error());
2383                }
2384            }
2385
2386            while let Some(mut prev) = clauses.pop() {
2387                *prev.else_branch.as_mut().unwrap().1 = Expr::If(expr);
2388                expr = prev;
2389            }
2390            expr.attrs = attrs;
2391            Ok(expr)
2392        }
2393    }
2394
2395    #[cfg(feature = "full")]
2396    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2397    impl Parse for ExprInfer {
2398        fn parse(input: ParseStream) -> Result<Self> {
2399            Ok(ExprInfer {
2400                attrs: input.call(Attribute::parse_outer)?,
2401                underscore_token: input.parse()?,
2402            })
2403        }
2404    }
2405
2406    #[cfg(feature = "full")]
2407    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2408    impl Parse for ExprForLoop {
2409        fn parse(input: ParseStream) -> Result<Self> {
2410            let mut attrs = input.call(Attribute::parse_outer)?;
2411            let label: Option<Label> = input.parse()?;
2412            let for_token: Token![for] = input.parse()?;
2413
2414            let pat = Pat::parse_multi_with_leading_vert(input)?;
2415
2416            let in_token: Token![in] = input.parse()?;
2417            let expr: Expr = input.call(Expr::parse_without_eager_brace)?;
2418
2419            let content;
2420            let brace_token = braced!(content in input);
2421            attr::parsing::parse_inner(&content, &mut attrs)?;
2422            let stmts = content.call(Block::parse_within)?;
2423
2424            Ok(ExprForLoop {
2425                attrs,
2426                label,
2427                for_token,
2428                pat: Box::new(pat),
2429                in_token,
2430                expr: Box::new(expr),
2431                body: Block { brace_token, stmts },
2432            })
2433        }
2434    }
2435
2436    #[cfg(feature = "full")]
2437    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2438    impl Parse for ExprLoop {
2439        fn parse(input: ParseStream) -> Result<Self> {
2440            let mut attrs = input.call(Attribute::parse_outer)?;
2441            let label: Option<Label> = input.parse()?;
2442            let loop_token: Token![loop] = input.parse()?;
2443
2444            let content;
2445            let brace_token = braced!(content in input);
2446            attr::parsing::parse_inner(&content, &mut attrs)?;
2447            let stmts = content.call(Block::parse_within)?;
2448
2449            Ok(ExprLoop {
2450                attrs,
2451                label,
2452                loop_token,
2453                body: Block { brace_token, stmts },
2454            })
2455        }
2456    }
2457
2458    #[cfg(feature = "full")]
2459    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2460    impl Parse for ExprMatch {
2461        fn parse(input: ParseStream) -> Result<Self> {
2462            let mut attrs = input.call(Attribute::parse_outer)?;
2463            let match_token: Token![match] = input.parse()?;
2464            let expr = Expr::parse_without_eager_brace(input)?;
2465
2466            let content;
2467            let brace_token = braced!(content in input);
2468            attr::parsing::parse_inner(&content, &mut attrs)?;
2469
2470            let arms = Arm::parse_multiple(&content)?;
2471
2472            Ok(ExprMatch {
2473                attrs,
2474                match_token,
2475                expr: Box::new(expr),
2476                brace_token,
2477                arms,
2478            })
2479        }
2480    }
2481
2482    macro_rules! impl_by_parsing_expr {
2483        (
2484            $(
2485                $expr_type:ty, $variant:ident, $msg:expr,
2486            )*
2487        ) => {
2488            $(
2489                #[cfg(all(feature = "full", feature = "printing"))]
2490                #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2491                impl Parse for $expr_type {
2492                    fn parse(input: ParseStream) -> Result<Self> {
2493                        let mut expr: Expr = input.parse()?;
2494                        loop {
2495                            match expr {
2496                                Expr::$variant(inner) => return Ok(inner),
2497                                Expr::Group(next) => expr = *next.expr,
2498                                _ => return Err(Error::new_spanned(expr, $msg)),
2499                            }
2500                        }
2501                    }
2502                }
2503            )*
2504        };
2505    }
2506
2507    impl_by_parsing_expr! {
2508        ExprAssign, Assign, "expected assignment expression",
2509        ExprAwait, Await, "expected await expression",
2510        ExprBinary, Binary, "expected binary operation",
2511        ExprCall, Call, "expected function call expression",
2512        ExprCast, Cast, "expected cast expression",
2513        ExprField, Field, "expected struct field access",
2514        ExprIndex, Index, "expected indexing expression",
2515        ExprMethodCall, MethodCall, "expected method call expression",
2516        ExprRange, Range, "expected range expression",
2517        ExprTry, Try, "expected try expression",
2518        ExprTuple, Tuple, "expected tuple expression",
2519    }
2520
2521    #[cfg(feature = "full")]
2522    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2523    impl Parse for ExprUnary {
2524        fn parse(input: ParseStream) -> Result<Self> {
2525            let attrs = Vec::new();
2526            let allow_struct = AllowStruct(true);
2527            expr_unary(input, attrs, allow_struct)
2528        }
2529    }
2530
2531    #[cfg(feature = "full")]
2532    fn expr_unary(
2533        input: ParseStream,
2534        attrs: Vec<Attribute>,
2535        allow_struct: AllowStruct,
2536    ) -> Result<ExprUnary> {
2537        Ok(ExprUnary {
2538            attrs,
2539            op: input.parse()?,
2540            expr: Box::new(unary_expr(input, allow_struct)?),
2541        })
2542    }
2543
2544    #[cfg(feature = "full")]
2545    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2546    impl Parse for ExprClosure {
2547        fn parse(input: ParseStream) -> Result<Self> {
2548            let allow_struct = AllowStruct(true);
2549            expr_closure(input, allow_struct)
2550        }
2551    }
2552
2553    #[cfg(feature = "full")]
2554    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2555    impl Parse for ExprRawAddr {
2556        fn parse(input: ParseStream) -> Result<Self> {
2557            let allow_struct = AllowStruct(true);
2558            Ok(ExprRawAddr {
2559                attrs: Vec::new(),
2560                and_token: input.parse()?,
2561                raw: input.parse()?,
2562                mutability: input.parse()?,
2563                expr: Box::new(unary_expr(input, allow_struct)?),
2564            })
2565        }
2566    }
2567
2568    #[cfg(feature = "full")]
2569    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2570    impl Parse for ExprReference {
2571        fn parse(input: ParseStream) -> Result<Self> {
2572            let allow_struct = AllowStruct(true);
2573            Ok(ExprReference {
2574                attrs: Vec::new(),
2575                and_token: input.parse()?,
2576                mutability: input.parse()?,
2577                expr: Box::new(unary_expr(input, allow_struct)?),
2578            })
2579        }
2580    }
2581
2582    #[cfg(feature = "full")]
2583    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2584    impl Parse for ExprBreak {
2585        fn parse(input: ParseStream) -> Result<Self> {
2586            let allow_struct = AllowStruct(true);
2587            expr_break(input, allow_struct)
2588        }
2589    }
2590
2591    #[cfg(feature = "full")]
2592    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2593    impl Parse for ExprReturn {
2594        fn parse(input: ParseStream) -> Result<Self> {
2595            Ok(ExprReturn {
2596                attrs: Vec::new(),
2597                return_token: input.parse()?,
2598                expr: {
2599                    if Expr::peek(input) {
2600                        Some(input.parse()?)
2601                    } else {
2602                        None
2603                    }
2604                },
2605            })
2606        }
2607    }
2608
2609    #[cfg(feature = "full")]
2610    fn expr_become(input: ParseStream) -> Result<Expr> {
2611        let begin = input.cursor();
2612        input.parse::<Token![become]>()?;
2613        input.parse::<Expr>()?;
2614        Ok(Expr::Verbatim(verbatim::between(begin, input.cursor())))
2615    }
2616
2617    #[cfg(feature = "full")]
2618    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2619    impl Parse for ExprTryBlock {
2620        fn parse(input: ParseStream) -> Result<Self> {
2621            Ok(ExprTryBlock {
2622                attrs: Vec::new(),
2623                try_token: input.parse()?,
2624                modifiers: BlockModifiers {},
2625                block: input.parse()?,
2626            })
2627        }
2628    }
2629
2630    #[cfg(feature = "full")]
2631    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2632    impl Parse for ExprYield {
2633        fn parse(input: ParseStream) -> Result<Self> {
2634            Ok(ExprYield {
2635                attrs: Vec::new(),
2636                yield_token: input.parse()?,
2637                expr: {
2638                    if Expr::peek(input) {
2639                        Some(input.parse()?)
2640                    } else {
2641                        None
2642                    }
2643                },
2644            })
2645        }
2646    }
2647
2648    #[cfg(feature = "full")]
2649    fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
2650        let lifetimes: Option<BoundLifetimes> = input.parse()?;
2651        let constness: Option<Token![const]> = input.parse()?;
2652        let asyncness: Option<Token![async]> = input.parse()?;
2653        let capture: Option<Token![move]> = input.parse()?;
2654        let inputs_begin: Token![|] = input.parse()?;
2655
2656        let mut inputs = Punctuated::new();
2657        loop {
2658            if input.peek(Token![|]) {
2659                break;
2660            }
2661            let value = closure_arg(input)?;
2662            inputs.push_value(value);
2663            if input.peek(Token![|]) {
2664                break;
2665            }
2666            let punct: Token![,] = input.parse()?;
2667            inputs.push_punct(punct);
2668        }
2669
2670        let inputs_end: Token![|] = input.parse()?;
2671
2672        let (output, body) = if input.peek(Token![->]) {
2673            let arrow_token: Token![->] = input.parse()?;
2674            let ty: Type = input.parse()?;
2675            let body: Block = input.parse()?;
2676            let output = ReturnType::Type(arrow_token, Box::new(ty));
2677            let block = Expr::Block(ExprBlock {
2678                attrs: Vec::new(),
2679                label: None,
2680                block: body,
2681            });
2682            (output, block)
2683        } else {
2684            let body = ambiguous_expr(input, allow_struct)?;
2685            (ReturnType::Default, body)
2686        };
2687
2688        Ok(ExprClosure {
2689            attrs: Vec::new(),
2690            lifetimes,
2691            modifiers: ClosureModifiers {},
2692            constness,
2693            asyncness,
2694            capture,
2695            inputs_begin,
2696            inputs,
2697            inputs_end,
2698            output,
2699            body: Box::new(body),
2700        })
2701    }
2702
2703    #[cfg(feature = "full")]
2704    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2705    impl Parse for ExprAsync {
2706        fn parse(input: ParseStream) -> Result<Self> {
2707            Ok(ExprAsync {
2708                attrs: Vec::new(),
2709                async_token: input.parse()?,
2710                capture: input.parse()?,
2711                modifiers: BlockModifiers {},
2712                block: input.parse()?,
2713            })
2714        }
2715    }
2716
2717    #[cfg(feature = "full")]
2718    fn closure_arg(input: ParseStream) -> Result<Pat> {
2719        let attrs = input.call(Attribute::parse_outer)?;
2720        let mut pat = Pat::parse_single(input)?;
2721
2722        if input.peek(Token![:]) {
2723            Ok(Pat::Type(PatType {
2724                attrs,
2725                pat: Box::new(pat),
2726                colon_token: input.parse()?,
2727                ty: input.parse()?,
2728            }))
2729        } else {
2730            match &mut pat {
2731                Pat::Const(pat) => pat.attrs = attrs,
2732                Pat::Guard(_) => unreachable!(),
2733                Pat::Ident(pat) => pat.attrs = attrs,
2734                Pat::Lit(pat) => pat.attrs = attrs,
2735                Pat::Macro(pat) => pat.attrs = attrs,
2736                Pat::Or(pat) => pat.attrs = attrs,
2737                Pat::Paren(pat) => pat.attrs = attrs,
2738                Pat::Path(pat) => pat.attrs = attrs,
2739                Pat::Range(pat) => pat.attrs = attrs,
2740                Pat::Reference(pat) => pat.attrs = attrs,
2741                Pat::Rest(pat) => pat.attrs = attrs,
2742                Pat::Slice(pat) => pat.attrs = attrs,
2743                Pat::Struct(pat) => pat.attrs = attrs,
2744                Pat::Tuple(pat) => pat.attrs = attrs,
2745                Pat::TupleStruct(pat) => pat.attrs = attrs,
2746                Pat::Type(_) => unreachable!(),
2747                Pat::Verbatim(_) => {}
2748                Pat::Wild(pat) => pat.attrs = attrs,
2749            }
2750            Ok(pat)
2751        }
2752    }
2753
2754    #[cfg(feature = "full")]
2755    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2756    impl Parse for ExprWhile {
2757        fn parse(input: ParseStream) -> Result<Self> {
2758            let mut attrs = input.call(Attribute::parse_outer)?;
2759            let label: Option<Label> = input.parse()?;
2760            let while_token: Token![while] = input.parse()?;
2761            let cond = Expr::parse_without_eager_brace(input)?;
2762
2763            let content;
2764            let brace_token = braced!(content in input);
2765            attr::parsing::parse_inner(&content, &mut attrs)?;
2766            let stmts = content.call(Block::parse_within)?;
2767
2768            Ok(ExprWhile {
2769                attrs,
2770                label,
2771                while_token,
2772                cond: Box::new(cond),
2773                body: Block { brace_token, stmts },
2774            })
2775        }
2776    }
2777
2778    #[cfg(feature = "full")]
2779    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2780    impl Parse for ExprConst {
2781        fn parse(input: ParseStream) -> Result<Self> {
2782            let const_token: Token![const] = input.parse()?;
2783
2784            let content;
2785            let brace_token = braced!(content in input);
2786            let inner_attrs = content.call(Attribute::parse_inner)?;
2787            let stmts = content.call(Block::parse_within)?;
2788
2789            Ok(ExprConst {
2790                attrs: inner_attrs,
2791                const_token,
2792                modifiers: BlockModifiers {},
2793                block: Block { brace_token, stmts },
2794            })
2795        }
2796    }
2797
2798    #[cfg(feature = "full")]
2799    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2800    impl Parse for Label {
2801        fn parse(input: ParseStream) -> Result<Self> {
2802            Ok(Label {
2803                name: Lifetime::parse_any(input)?,
2804                colon_token: input.parse()?,
2805            })
2806        }
2807    }
2808
2809    #[cfg(feature = "full")]
2810    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2811    impl Parse for Option<Label> {
2812        fn parse(input: ParseStream) -> Result<Self> {
2813            if input.peek(Lifetime) {
2814                input.parse().map(Some)
2815            } else {
2816                Ok(None)
2817            }
2818        }
2819    }
2820
2821    #[cfg(feature = "full")]
2822    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2823    impl Parse for ExprContinue {
2824        fn parse(input: ParseStream) -> Result<Self> {
2825            Ok(ExprContinue {
2826                attrs: Vec::new(),
2827                continue_token: input.parse()?,
2828                label: Lifetime::parse_optional_any(input),
2829            })
2830        }
2831    }
2832
2833    #[cfg(feature = "full")]
2834    fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2835        let break_token: Token![break] = input.parse()?;
2836
2837        let ahead = input.fork();
2838        let label_begin = ahead.cursor();
2839        let label = Lifetime::parse_optional_any(&ahead);
2840        if label.is_some() && ahead.peek(Token![:]) && !ahead.peek(Token![::]) {
2841            // Not allowed: `break 'label: loop {...}`
2842            // Parentheses are required. `break ('label: loop {...})`
2843            let _: Expr = input.parse()?;
2844            return Err(Error::new_range(
2845                label_begin..input.cursor(),
2846                "parentheses required",
2847            ));
2848        }
2849
2850        input.advance_to(&ahead);
2851        let expr = if Expr::peek(input) && (allow_struct.0 || !input.peek(token::Brace)) {
2852            Some(input.parse()?)
2853        } else {
2854            None
2855        };
2856
2857        Ok(ExprBreak {
2858            attrs: Vec::new(),
2859            break_token,
2860            label,
2861            expr,
2862        })
2863    }
2864
2865    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2866    impl Parse for FieldValue {
2867        fn parse(input: ParseStream) -> Result<Self> {
2868            let attrs = input.call(Attribute::parse_outer)?;
2869            let member: Member = input.parse()?;
2870            let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
2871                let colon_token: Token![:] = input.parse()?;
2872                let value: Expr = input.parse()?;
2873                (Some(colon_token), value)
2874            } else if let Member::Named(ident) = &member {
2875                let value = Expr::Path(ExprPath {
2876                    attrs: Vec::new(),
2877                    qself: None,
2878                    path: Path::from(ident.clone()),
2879                });
2880                (None, value)
2881            } else {
2882                unreachable!()
2883            };
2884
2885            Ok(FieldValue {
2886                attrs,
2887                member,
2888                colon_token,
2889                expr: value,
2890            })
2891        }
2892    }
2893
2894    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2895    impl Parse for ExprStruct {
2896        fn parse(input: ParseStream) -> Result<Self> {
2897            let expr_style = true;
2898            let (qself, path) = path::parsing::qpath(input, expr_style)?;
2899            expr_struct_helper(input, qself, path)
2900        }
2901    }
2902
2903    fn expr_struct_helper(
2904        input: ParseStream,
2905        qself: Option<QSelf>,
2906        path: Path,
2907    ) -> Result<ExprStruct> {
2908        let content;
2909        let brace_token = braced!(content in input);
2910
2911        let mut fields = Punctuated::new();
2912        while !content.is_empty() {
2913            if content.peek(Token![..]) {
2914                return Ok(ExprStruct {
2915                    attrs: Vec::new(),
2916                    qself,
2917                    path,
2918                    brace_token,
2919                    fields,
2920                    dot2_token: Some(content.parse()?),
2921                    rest: if content.is_empty() {
2922                        None
2923                    } else {
2924                        Some(Box::new(content.parse()?))
2925                    },
2926                });
2927            }
2928
2929            fields.push(content.parse()?);
2930            if content.is_empty() {
2931                break;
2932            }
2933            let punct: Token![,] = content.parse()?;
2934            fields.push_punct(punct);
2935        }
2936
2937        Ok(ExprStruct {
2938            attrs: Vec::new(),
2939            qself,
2940            path,
2941            brace_token,
2942            fields,
2943            dot2_token: None,
2944            rest: None,
2945        })
2946    }
2947
2948    #[cfg(feature = "full")]
2949    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2950    impl Parse for ExprUnsafe {
2951        fn parse(input: ParseStream) -> Result<Self> {
2952            let unsafe_token: Token![unsafe] = input.parse()?;
2953
2954            let content;
2955            let brace_token = braced!(content in input);
2956            let inner_attrs = content.call(Attribute::parse_inner)?;
2957            let stmts = content.call(Block::parse_within)?;
2958
2959            Ok(ExprUnsafe {
2960                attrs: inner_attrs,
2961                unsafe_token,
2962                block: Block { brace_token, stmts },
2963            })
2964        }
2965    }
2966
2967    #[cfg(feature = "full")]
2968    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2969    impl Parse for ExprBlock {
2970        fn parse(input: ParseStream) -> Result<Self> {
2971            let mut attrs = input.call(Attribute::parse_outer)?;
2972            let label: Option<Label> = input.parse()?;
2973
2974            let content;
2975            let brace_token = braced!(content in input);
2976            attr::parsing::parse_inner(&content, &mut attrs)?;
2977            let stmts = content.call(Block::parse_within)?;
2978
2979            Ok(ExprBlock {
2980                attrs,
2981                label,
2982                block: Block { brace_token, stmts },
2983            })
2984        }
2985    }
2986
2987    #[cfg(feature = "full")]
2988    fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2989        let limits: RangeLimits = input.parse()?;
2990        let end = parse_range_end(input, &limits, allow_struct)?;
2991        Ok(ExprRange {
2992            attrs: Vec::new(),
2993            start: None,
2994            limits,
2995            end,
2996        })
2997    }
2998
2999    #[cfg(feature = "full")]
3000    fn parse_range_end(
3001        input: ParseStream,
3002        limits: &RangeLimits,
3003        allow_struct: AllowStruct,
3004    ) -> Result<Option<Box<Expr>>> {
3005        if matches!(limits, RangeLimits::HalfOpen(_))
3006            && (input.is_empty()
3007                || input.peek(Token![,])
3008                || input.peek(Token![;])
3009                || input.peek(Token![.]) && !input.peek(Token![..])
3010                || input.peek(Token![?])
3011                || input.peek(Token![=>])
3012                || !allow_struct.0 && input.peek(token::Brace)
3013                || input.peek(Token![=])
3014                || input.peek(Token![+])
3015                || input.peek(Token![/])
3016                || input.peek(Token![%])
3017                || input.peek(Token![^])
3018                || input.peek(Token![>])
3019                || input.peek(Token![<=])
3020                || input.peek(Token![!=])
3021                || input.peek(Token![-=])
3022                || input.peek(Token![*=])
3023                || input.peek(Token![&=])
3024                || input.peek(Token![|=])
3025                || input.peek(Token![<<=])
3026                || input.peek(Token![as]))
3027        {
3028            Ok(None)
3029        } else {
3030            let end = parse_binop_rhs(input, allow_struct, Precedence::Range)?;
3031            Ok(Some(end))
3032        }
3033    }
3034
3035    #[cfg(feature = "full")]
3036    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3037    impl Parse for RangeLimits {
3038        fn parse(input: ParseStream) -> Result<Self> {
3039            let lookahead = input.lookahead1();
3040            let dot_dot = lookahead.peek(Token![..]);
3041            let dot_dot_eq = dot_dot && lookahead.peek(Token![..=]);
3042            let dot_dot_dot = dot_dot && input.peek(Token![...]);
3043            if dot_dot_eq {
3044                input.parse().map(RangeLimits::Closed)
3045            } else if dot_dot && !dot_dot_dot {
3046                input.parse().map(RangeLimits::HalfOpen)
3047            } else {
3048                Err(lookahead.error())
3049            }
3050        }
3051    }
3052
3053    #[cfg(feature = "full")]
3054    impl RangeLimits {
3055        pub(crate) fn parse_obsolete(input: ParseStream) -> Result<Self> {
3056            let lookahead = input.lookahead1();
3057            let dot_dot = lookahead.peek(Token![..]);
3058            let dot_dot_eq = dot_dot && lookahead.peek(Token![..=]);
3059            let dot_dot_dot = dot_dot && input.peek(Token![...]);
3060            if dot_dot_eq {
3061                input.parse().map(RangeLimits::Closed)
3062            } else if dot_dot_dot {
3063                let dot3: Token![...] = input.parse()?;
3064                Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
3065            } else if dot_dot {
3066                input.parse().map(RangeLimits::HalfOpen)
3067            } else {
3068                Err(lookahead.error())
3069            }
3070        }
3071    }
3072
3073    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3074    impl Parse for ExprPath {
3075        fn parse(input: ParseStream) -> Result<Self> {
3076            #[cfg(not(feature = "full"))]
3077            let attrs = Vec::new();
3078            #[cfg(feature = "full")]
3079            let attrs = input.call(Attribute::parse_outer)?;
3080
3081            let expr_style = true;
3082            let (qself, path) = path::parsing::qpath(input, expr_style)?;
3083
3084            Ok(ExprPath { attrs, qself, path })
3085        }
3086    }
3087
3088    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3089    impl Parse for Member {
3090        fn parse(input: ParseStream) -> Result<Self> {
3091            if input.peek(Ident) {
3092                input.parse().map(Member::Named)
3093            } else if input.peek(LitInt) {
3094                input.parse().map(Member::Unnamed)
3095            } else {
3096                Err(input.error("expected identifier or integer"))
3097            }
3098        }
3099    }
3100
3101    #[cfg(feature = "full")]
3102    impl Arm {
3103        pub(crate) fn parse_multiple(input: ParseStream) -> Result<Vec<Self>> {
3104            let mut arms = Vec::new();
3105            while !input.is_empty() {
3106                arms.push(input.call(Arm::parse)?);
3107            }
3108            Ok(arms)
3109        }
3110    }
3111
3112    #[cfg(feature = "full")]
3113    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3114    impl Parse for Arm {
3115        fn parse(input: ParseStream) -> Result<Arm> {
3116            let requires_comma;
3117            Ok(Arm {
3118                attrs: input.call(Attribute::parse_outer)?,
3119                pat: Pat::parse_multi_with_leading_vert_and_guard(input)?,
3120                fat_arrow_token: input.parse()?,
3121                body: {
3122                    let body = Expr::parse_with_earlier_boundary_rule(input)?;
3123                    requires_comma = classify::requires_comma_to_be_match_arm(&body);
3124                    Box::new(body)
3125                },
3126                comma: {
3127                    if requires_comma && !input.is_empty() {
3128                        Some(input.parse()?)
3129                    } else {
3130                        input.parse()?
3131                    }
3132                },
3133            })
3134        }
3135    }
3136
3137    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3138    impl Parse for Index {
3139        fn parse(input: ParseStream) -> Result<Self> {
3140            let lit: LitInt = input.parse()?;
3141            if lit.suffix().is_empty() {
3142                Ok(Index {
3143                    index: lit
3144                        .base10_digits()
3145                        .parse()
3146                        .map_err(|err| Error::new(lit.span(), err))?,
3147                    span: lit.span(),
3148                })
3149            } else {
3150                Err(Error::new(lit.span(), "expected unsuffixed integer"))
3151            }
3152        }
3153    }
3154
3155    fn multi_index(e: &mut Expr, dot_token: &mut Token![.], float: LitFloat) -> Result<bool> {
3156        let float_token = float.token();
3157        let float_span = float_token.span();
3158        let mut float_repr = float_token.to_string();
3159        let trailing_dot = float_repr.ends_with('.');
3160        if trailing_dot {
3161            float_repr.truncate(float_repr.len() - 1);
3162        }
3163
3164        let mut offset = 0;
3165        for part in float_repr.split('.') {
3166            let mut index: Index =
3167                crate::parse_str(part).map_err(|err| Error::new(float_span, err))?;
3168            let part_end = offset + part.len();
3169            index.span = float_token.subspan(offset..part_end).unwrap_or(float_span);
3170
3171            let base = mem::replace(e, Expr::PLACEHOLDER);
3172            *e = Expr::Field(ExprField {
3173                attrs: Vec::new(),
3174                base: Box::new(base),
3175                dot_token: Token![.](dot_token.span),
3176                member: Member::Unnamed(index),
3177            });
3178
3179            let dot_span = float_token
3180                .subspan(part_end..part_end + 1)
3181                .unwrap_or(float_span);
3182            *dot_token = Token![.](dot_span);
3183            offset = part_end + 1;
3184        }
3185
3186        Ok(!trailing_dot)
3187    }
3188
3189    fn check_cast(input: ParseStream) -> Result<()> {
3190        let kind = if input.peek(Token![.]) && !input.peek(Token![..]) {
3191            if input.peek2(Token![await]) {
3192                "`.await`"
3193            } else if input.peek2(Ident) && (input.peek3(token::Paren) || input.peek3(Token![::])) {
3194                "a method call"
3195            } else {
3196                "a field access"
3197            }
3198        } else if input.peek(Token![?]) {
3199            "`?`"
3200        } else if input.peek(token::Bracket) {
3201            "indexing"
3202        } else if input.peek(token::Paren) {
3203            "a function call"
3204        } else {
3205            return Ok(());
3206        };
3207        let msg = format!("casts cannot be followed by {}", kind);
3208        Err(input.error(msg))
3209    }
3210}
3211
3212#[cfg(feature = "printing")]
3213pub(crate) mod printing {
3214    use crate::attr::Attribute;
3215    #[cfg(feature = "full")]
3216    use crate::attr::FilterAttrs;
3217    #[cfg(feature = "full")]
3218    use crate::classify;
3219    #[cfg(feature = "full")]
3220    use crate::expr::{
3221        Arm, ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure,
3222        ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch,
3223        ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprUnsafe,
3224        ExprWhile, ExprYield, Label, RangeLimits,
3225    };
3226    use crate::expr::{
3227        Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro,
3228        ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprTuple, ExprUnary,
3229        FieldValue, Index, Member,
3230    };
3231    use crate::fixup::FixupContext;
3232    use crate::op::BinOp;
3233    use crate::path;
3234    use crate::path::printing::PathStyle;
3235    use crate::precedence::Precedence;
3236    use crate::token;
3237    #[cfg(feature = "full")]
3238    use crate::ty::ReturnType;
3239    use proc_macro2::{Literal, Span, TokenStream};
3240    use quote::{ToTokens, TokenStreamExt as _};
3241
3242    #[cfg(feature = "full")]
3243    pub(crate) fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3244        tokens.append_all(attrs.outer());
3245    }
3246
3247    #[cfg(feature = "full")]
3248    fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3249        tokens.append_all(attrs.inner());
3250    }
3251
3252    #[cfg(not(feature = "full"))]
3253    pub(crate) fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3254
3255    pub(crate) fn print_subexpression(
3256        expr: &Expr,
3257        needs_group: bool,
3258        tokens: &mut TokenStream,
3259        mut fixup: FixupContext,
3260    ) {
3261        if needs_group {
3262            // If we are surrounding the whole cond in parentheses, such as:
3263            //
3264            //     if (return Struct {}) {}
3265            //
3266            // then there is no need for parenthesizing the individual struct
3267            // expressions within. On the other hand if the whole cond is not
3268            // parenthesized, then print_expr must parenthesize exterior struct
3269            // literals.
3270            //
3271            //     if x == (Struct {}) {}
3272            //
3273            fixup = FixupContext::NONE;
3274        }
3275
3276        let do_print_expr = |tokens: &mut TokenStream| print_expr(expr, tokens, fixup);
3277
3278        if needs_group {
3279            token::Paren::default().surround(tokens, do_print_expr);
3280        } else {
3281            do_print_expr(tokens);
3282        }
3283    }
3284
3285    pub(crate) fn print_expr(expr: &Expr, tokens: &mut TokenStream, mut fixup: FixupContext) {
3286        #[cfg(feature = "full")]
3287        let needs_group = fixup.parenthesize(expr);
3288        #[cfg(not(feature = "full"))]
3289        let needs_group = false;
3290
3291        if needs_group {
3292            fixup = FixupContext::NONE;
3293        }
3294
3295        let do_print_expr = |tokens: &mut TokenStream| match expr {
3296            #[cfg(feature = "full")]
3297            Expr::Array(e) => e.to_tokens(tokens),
3298            #[cfg(feature = "full")]
3299            Expr::Assign(e) => print_expr_assign(e, tokens, fixup),
3300            #[cfg(feature = "full")]
3301            Expr::Async(e) => e.to_tokens(tokens),
3302            #[cfg(feature = "full")]
3303            Expr::Await(e) => print_expr_await(e, tokens, fixup),
3304            Expr::Binary(e) => print_expr_binary(e, tokens, fixup),
3305            #[cfg(feature = "full")]
3306            Expr::Block(e) => e.to_tokens(tokens),
3307            #[cfg(feature = "full")]
3308            Expr::Break(e) => print_expr_break(e, tokens, fixup),
3309            Expr::Call(e) => print_expr_call(e, tokens, fixup),
3310            Expr::Cast(e) => print_expr_cast(e, tokens, fixup),
3311            #[cfg(feature = "full")]
3312            Expr::Closure(e) => print_expr_closure(e, tokens, fixup),
3313            #[cfg(feature = "full")]
3314            Expr::Const(e) => e.to_tokens(tokens),
3315            #[cfg(feature = "full")]
3316            Expr::Continue(e) => e.to_tokens(tokens),
3317            Expr::Field(e) => print_expr_field(e, tokens, fixup),
3318            #[cfg(feature = "full")]
3319            Expr::ForLoop(e) => e.to_tokens(tokens),
3320            Expr::Group(e) => e.to_tokens(tokens),
3321            #[cfg(feature = "full")]
3322            Expr::If(e) => e.to_tokens(tokens),
3323            Expr::Index(e) => print_expr_index(e, tokens, fixup),
3324            #[cfg(feature = "full")]
3325            Expr::Infer(e) => e.to_tokens(tokens),
3326            #[cfg(feature = "full")]
3327            Expr::Let(e) => print_expr_let(e, tokens, fixup),
3328            Expr::Lit(e) => e.to_tokens(tokens),
3329            #[cfg(feature = "full")]
3330            Expr::Loop(e) => e.to_tokens(tokens),
3331            Expr::Macro(e) => e.to_tokens(tokens),
3332            #[cfg(feature = "full")]
3333            Expr::Match(e) => e.to_tokens(tokens),
3334            Expr::MethodCall(e) => print_expr_method_call(e, tokens, fixup),
3335            Expr::Paren(e) => e.to_tokens(tokens),
3336            Expr::Path(e) => e.to_tokens(tokens),
3337            #[cfg(feature = "full")]
3338            Expr::Range(e) => print_expr_range(e, tokens, fixup),
3339            #[cfg(feature = "full")]
3340            Expr::RawAddr(e) => print_expr_raw_addr(e, tokens, fixup),
3341            Expr::Reference(e) => print_expr_reference(e, tokens, fixup),
3342            #[cfg(feature = "full")]
3343            Expr::Repeat(e) => e.to_tokens(tokens),
3344            #[cfg(feature = "full")]
3345            Expr::Return(e) => print_expr_return(e, tokens, fixup),
3346            Expr::Struct(e) => e.to_tokens(tokens),
3347            #[cfg(feature = "full")]
3348            Expr::Try(e) => print_expr_try(e, tokens, fixup),
3349            #[cfg(feature = "full")]
3350            Expr::TryBlock(e) => e.to_tokens(tokens),
3351            Expr::Tuple(e) => e.to_tokens(tokens),
3352            Expr::Unary(e) => print_expr_unary(e, tokens, fixup),
3353            #[cfg(feature = "full")]
3354            Expr::Unsafe(e) => e.to_tokens(tokens),
3355            Expr::Verbatim(e) => e.to_tokens(tokens),
3356            #[cfg(feature = "full")]
3357            Expr::While(e) => e.to_tokens(tokens),
3358            #[cfg(feature = "full")]
3359            Expr::Yield(e) => print_expr_yield(e, tokens, fixup),
3360
3361            #[cfg(not(feature = "full"))]
3362            _ => unreachable!(),
3363        };
3364
3365        if needs_group {
3366            token::Paren::default().surround(tokens, do_print_expr);
3367        } else {
3368            do_print_expr(tokens);
3369        }
3370    }
3371
3372    #[cfg(feature = "full")]
3373    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3374    impl ToTokens for ExprArray {
3375        fn to_tokens(&self, tokens: &mut TokenStream) {
3376            outer_attrs_to_tokens(&self.attrs, tokens);
3377            self.bracket_token.surround(tokens, |tokens| {
3378                self.elems.to_tokens(tokens);
3379            });
3380        }
3381    }
3382
3383    #[cfg(feature = "full")]
3384    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3385    impl ToTokens for ExprAssign {
3386        fn to_tokens(&self, tokens: &mut TokenStream) {
3387            print_expr_assign(self, tokens, FixupContext::NONE);
3388        }
3389    }
3390
3391    #[cfg(feature = "full")]
3392    fn print_expr_assign(e: &ExprAssign, tokens: &mut TokenStream, mut fixup: FixupContext) {
3393        outer_attrs_to_tokens(&e.attrs, tokens);
3394
3395        let needs_group = !e.attrs.is_empty();
3396        if needs_group {
3397            fixup = FixupContext::NONE;
3398        }
3399
3400        let do_print_expr = |tokens: &mut TokenStream| {
3401            let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3402                &e.left,
3403                false,
3404                false,
3405                Precedence::Assign,
3406            );
3407            print_subexpression(&e.left, left_prec <= Precedence::Range, tokens, left_fixup);
3408            e.eq_token.to_tokens(tokens);
3409            print_expr(
3410                &e.right,
3411                tokens,
3412                fixup.rightmost_subexpression_fixup(false, false, Precedence::Assign),
3413            );
3414        };
3415
3416        if needs_group {
3417            token::Paren::default().surround(tokens, do_print_expr);
3418        } else {
3419            do_print_expr(tokens);
3420        }
3421    }
3422
3423    #[cfg(feature = "full")]
3424    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3425    impl ToTokens for ExprAsync {
3426        fn to_tokens(&self, tokens: &mut TokenStream) {
3427            outer_attrs_to_tokens(&self.attrs, tokens);
3428            self.async_token.to_tokens(tokens);
3429            self.capture.to_tokens(tokens);
3430            self.block.to_tokens(tokens);
3431        }
3432    }
3433
3434    #[cfg(feature = "full")]
3435    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3436    impl ToTokens for ExprAwait {
3437        fn to_tokens(&self, tokens: &mut TokenStream) {
3438            print_expr_await(self, tokens, FixupContext::NONE);
3439        }
3440    }
3441
3442    #[cfg(feature = "full")]
3443    fn print_expr_await(e: &ExprAwait, tokens: &mut TokenStream, fixup: FixupContext) {
3444        outer_attrs_to_tokens(&e.attrs, tokens);
3445        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.base);
3446        print_subexpression(
3447            &e.base,
3448            left_prec < Precedence::Unambiguous,
3449            tokens,
3450            left_fixup,
3451        );
3452        e.dot_token.to_tokens(tokens);
3453        e.await_token.to_tokens(tokens);
3454    }
3455
3456    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3457    impl ToTokens for ExprBinary {
3458        fn to_tokens(&self, tokens: &mut TokenStream) {
3459            print_expr_binary(self, tokens, FixupContext::NONE);
3460        }
3461    }
3462
3463    fn print_expr_binary(e: &ExprBinary, tokens: &mut TokenStream, mut fixup: FixupContext) {
3464        outer_attrs_to_tokens(&e.attrs, tokens);
3465
3466        let needs_group = !e.attrs.is_empty();
3467        if needs_group {
3468            fixup = FixupContext::NONE;
3469        }
3470
3471        let do_print_expr = |tokens: &mut TokenStream| {
3472            let binop_prec = Precedence::of_binop(&e.op);
3473            let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3474                &e.left,
3475                #[cfg(feature = "full")]
3476                match &e.op {
3477                    BinOp::Sub(_)
3478                    | BinOp::Mul(_)
3479                    | BinOp::And(_)
3480                    | BinOp::Or(_)
3481                    | BinOp::BitAnd(_)
3482                    | BinOp::BitOr(_)
3483                    | BinOp::Shl(_)
3484                    | BinOp::Lt(_) => true,
3485                    _ => false,
3486                },
3487                match &e.op {
3488                    BinOp::Shl(_) | BinOp::Lt(_) => true,
3489                    _ => false,
3490                },
3491                #[cfg(feature = "full")]
3492                binop_prec,
3493            );
3494            let left_needs_group = match binop_prec {
3495                Precedence::Assign => left_prec <= Precedence::Range,
3496                Precedence::Compare => left_prec <= binop_prec,
3497                _ => left_prec < binop_prec,
3498            };
3499
3500            let right_fixup = fixup.rightmost_subexpression_fixup(
3501                #[cfg(feature = "full")]
3502                false,
3503                #[cfg(feature = "full")]
3504                false,
3505                #[cfg(feature = "full")]
3506                binop_prec,
3507            );
3508            let right_needs_group = binop_prec != Precedence::Assign
3509                && right_fixup.rightmost_subexpression_precedence(&e.right) <= binop_prec;
3510
3511            print_subexpression(&e.left, left_needs_group, tokens, left_fixup);
3512            e.op.to_tokens(tokens);
3513            print_subexpression(&e.right, right_needs_group, tokens, right_fixup);
3514        };
3515
3516        if needs_group {
3517            token::Paren::default().surround(tokens, do_print_expr);
3518        } else {
3519            do_print_expr(tokens);
3520        }
3521    }
3522
3523    #[cfg(feature = "full")]
3524    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3525    impl ToTokens for ExprBlock {
3526        fn to_tokens(&self, tokens: &mut TokenStream) {
3527            outer_attrs_to_tokens(&self.attrs, tokens);
3528            self.label.to_tokens(tokens);
3529            self.block.brace_token.surround(tokens, |tokens| {
3530                inner_attrs_to_tokens(&self.attrs, tokens);
3531                tokens.append_all(&self.block.stmts);
3532            });
3533        }
3534    }
3535
3536    #[cfg(feature = "full")]
3537    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3538    impl ToTokens for ExprBreak {
3539        fn to_tokens(&self, tokens: &mut TokenStream) {
3540            print_expr_break(self, tokens, FixupContext::NONE);
3541        }
3542    }
3543
3544    #[cfg(feature = "full")]
3545    fn print_expr_break(e: &ExprBreak, tokens: &mut TokenStream, fixup: FixupContext) {
3546        outer_attrs_to_tokens(&e.attrs, tokens);
3547        e.break_token.to_tokens(tokens);
3548        e.label.to_tokens(tokens);
3549        if let Some(value) = &e.expr {
3550            print_subexpression(
3551                value,
3552                // Parenthesize `break 'inner: loop { break 'inner 1 } + 1`
3553                //                     ^---------------------------------^
3554                e.label.is_none() && classify::expr_leading_label(value),
3555                tokens,
3556                fixup.rightmost_subexpression_fixup(true, true, Precedence::Jump),
3557            );
3558        }
3559    }
3560
3561    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3562    impl ToTokens for ExprCall {
3563        fn to_tokens(&self, tokens: &mut TokenStream) {
3564            print_expr_call(self, tokens, FixupContext::NONE);
3565        }
3566    }
3567
3568    fn print_expr_call(e: &ExprCall, tokens: &mut TokenStream, fixup: FixupContext) {
3569        outer_attrs_to_tokens(&e.attrs, tokens);
3570
3571        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3572            &e.func,
3573            #[cfg(feature = "full")]
3574            true,
3575            false,
3576            #[cfg(feature = "full")]
3577            Precedence::Unambiguous,
3578        );
3579        let needs_group = if let Expr::Field(func) = &*e.func {
3580            func.member.is_named()
3581        } else {
3582            left_prec < Precedence::Unambiguous
3583        };
3584        print_subexpression(&e.func, needs_group, tokens, left_fixup);
3585
3586        e.paren_token.surround(tokens, |tokens| {
3587            e.args.to_tokens(tokens);
3588        });
3589    }
3590
3591    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3592    impl ToTokens for ExprCast {
3593        fn to_tokens(&self, tokens: &mut TokenStream) {
3594            print_expr_cast(self, tokens, FixupContext::NONE);
3595        }
3596    }
3597
3598    fn print_expr_cast(e: &ExprCast, tokens: &mut TokenStream, mut fixup: FixupContext) {
3599        outer_attrs_to_tokens(&e.attrs, tokens);
3600
3601        let needs_group = !e.attrs.is_empty();
3602        if needs_group {
3603            fixup = FixupContext::NONE;
3604        }
3605
3606        let do_print_expr = |tokens: &mut TokenStream| {
3607            let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3608                &e.expr,
3609                #[cfg(feature = "full")]
3610                false,
3611                false,
3612                #[cfg(feature = "full")]
3613                Precedence::Cast,
3614            );
3615            print_subexpression(&e.expr, left_prec < Precedence::Cast, tokens, left_fixup);
3616            e.as_token.to_tokens(tokens);
3617            e.ty.to_tokens(tokens);
3618        };
3619
3620        if needs_group {
3621            token::Paren::default().surround(tokens, do_print_expr);
3622        } else {
3623            do_print_expr(tokens);
3624        }
3625    }
3626
3627    #[cfg(feature = "full")]
3628    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3629    impl ToTokens for ExprClosure {
3630        fn to_tokens(&self, tokens: &mut TokenStream) {
3631            print_expr_closure(self, tokens, FixupContext::NONE);
3632        }
3633    }
3634
3635    #[cfg(feature = "full")]
3636    fn print_expr_closure(e: &ExprClosure, tokens: &mut TokenStream, fixup: FixupContext) {
3637        outer_attrs_to_tokens(&e.attrs, tokens);
3638        e.lifetimes.to_tokens(tokens);
3639        e.constness.to_tokens(tokens);
3640        e.asyncness.to_tokens(tokens);
3641        e.capture.to_tokens(tokens);
3642        e.inputs_begin.to_tokens(tokens);
3643        e.inputs.to_tokens(tokens);
3644        e.inputs_end.to_tokens(tokens);
3645        e.output.to_tokens(tokens);
3646        if matches!(e.output, ReturnType::Default)
3647            || matches!(&*e.body, Expr::Block(body) if body.attrs.is_empty() && body.label.is_none())
3648        {
3649            print_expr(
3650                &e.body,
3651                tokens,
3652                fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump),
3653            );
3654        } else {
3655            token::Brace::default().surround(tokens, |tokens| {
3656                print_expr(&e.body, tokens, FixupContext::new_stmt());
3657            });
3658        }
3659    }
3660
3661    #[cfg(feature = "full")]
3662    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3663    impl ToTokens for ExprConst {
3664        fn to_tokens(&self, tokens: &mut TokenStream) {
3665            outer_attrs_to_tokens(&self.attrs, tokens);
3666            self.const_token.to_tokens(tokens);
3667            self.block.brace_token.surround(tokens, |tokens| {
3668                inner_attrs_to_tokens(&self.attrs, tokens);
3669                tokens.append_all(&self.block.stmts);
3670            });
3671        }
3672    }
3673
3674    #[cfg(feature = "full")]
3675    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3676    impl ToTokens for ExprContinue {
3677        fn to_tokens(&self, tokens: &mut TokenStream) {
3678            outer_attrs_to_tokens(&self.attrs, tokens);
3679            self.continue_token.to_tokens(tokens);
3680            self.label.to_tokens(tokens);
3681        }
3682    }
3683
3684    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3685    impl ToTokens for ExprField {
3686        fn to_tokens(&self, tokens: &mut TokenStream) {
3687            print_expr_field(self, tokens, FixupContext::NONE);
3688        }
3689    }
3690
3691    fn print_expr_field(e: &ExprField, tokens: &mut TokenStream, fixup: FixupContext) {
3692        outer_attrs_to_tokens(&e.attrs, tokens);
3693        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.base);
3694        print_subexpression(
3695            &e.base,
3696            left_prec < Precedence::Unambiguous,
3697            tokens,
3698            left_fixup,
3699        );
3700        e.dot_token.to_tokens(tokens);
3701        e.member.to_tokens(tokens);
3702    }
3703
3704    #[cfg(feature = "full")]
3705    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3706    impl ToTokens for ExprForLoop {
3707        fn to_tokens(&self, tokens: &mut TokenStream) {
3708            outer_attrs_to_tokens(&self.attrs, tokens);
3709            self.label.to_tokens(tokens);
3710            self.for_token.to_tokens(tokens);
3711            self.pat.to_tokens(tokens);
3712            self.in_token.to_tokens(tokens);
3713            print_expr(&self.expr, tokens, FixupContext::new_condition());
3714            self.body.brace_token.surround(tokens, |tokens| {
3715                inner_attrs_to_tokens(&self.attrs, tokens);
3716                tokens.append_all(&self.body.stmts);
3717            });
3718        }
3719    }
3720
3721    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3722    impl ToTokens for ExprGroup {
3723        fn to_tokens(&self, tokens: &mut TokenStream) {
3724            outer_attrs_to_tokens(&self.attrs, tokens);
3725            self.group_token.surround(tokens, |tokens| {
3726                self.expr.to_tokens(tokens);
3727            });
3728        }
3729    }
3730
3731    #[cfg(feature = "full")]
3732    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3733    impl ToTokens for ExprIf {
3734        fn to_tokens(&self, tokens: &mut TokenStream) {
3735            outer_attrs_to_tokens(&self.attrs, tokens);
3736
3737            let mut expr = self;
3738            loop {
3739                expr.if_token.to_tokens(tokens);
3740                print_expr(&expr.cond, tokens, FixupContext::new_condition());
3741                expr.then_branch.to_tokens(tokens);
3742
3743                let (else_token, else_) = match &expr.else_branch {
3744                    Some(else_branch) => else_branch,
3745                    None => break,
3746                };
3747
3748                else_token.to_tokens(tokens);
3749                match &**else_ {
3750                    Expr::If(next) => {
3751                        expr = next;
3752                    }
3753                    Expr::Block(last) => {
3754                        last.to_tokens(tokens);
3755                        break;
3756                    }
3757                    // If this is not one of the valid expressions to exist in
3758                    // an else clause, wrap it in a block.
3759                    other => {
3760                        token::Brace::default().surround(tokens, |tokens| {
3761                            print_expr(other, tokens, FixupContext::new_stmt());
3762                        });
3763                        break;
3764                    }
3765                }
3766            }
3767        }
3768    }
3769
3770    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3771    impl ToTokens for ExprIndex {
3772        fn to_tokens(&self, tokens: &mut TokenStream) {
3773            print_expr_index(self, tokens, FixupContext::NONE);
3774        }
3775    }
3776
3777    fn print_expr_index(e: &ExprIndex, tokens: &mut TokenStream, fixup: FixupContext) {
3778        outer_attrs_to_tokens(&e.attrs, tokens);
3779        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3780            &e.expr,
3781            #[cfg(feature = "full")]
3782            true,
3783            false,
3784            #[cfg(feature = "full")]
3785            Precedence::Unambiguous,
3786        );
3787        print_subexpression(
3788            &e.expr,
3789            left_prec < Precedence::Unambiguous,
3790            tokens,
3791            left_fixup,
3792        );
3793        e.bracket_token.surround(tokens, |tokens| {
3794            e.index.to_tokens(tokens);
3795        });
3796    }
3797
3798    #[cfg(feature = "full")]
3799    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3800    impl ToTokens for ExprInfer {
3801        fn to_tokens(&self, tokens: &mut TokenStream) {
3802            outer_attrs_to_tokens(&self.attrs, tokens);
3803            self.underscore_token.to_tokens(tokens);
3804        }
3805    }
3806
3807    #[cfg(feature = "full")]
3808    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3809    impl ToTokens for ExprLet {
3810        fn to_tokens(&self, tokens: &mut TokenStream) {
3811            print_expr_let(self, tokens, FixupContext::NONE);
3812        }
3813    }
3814
3815    #[cfg(feature = "full")]
3816    fn print_expr_let(e: &ExprLet, tokens: &mut TokenStream, fixup: FixupContext) {
3817        outer_attrs_to_tokens(&e.attrs, tokens);
3818        e.let_token.to_tokens(tokens);
3819        e.pat.to_tokens(tokens);
3820        e.eq_token.to_tokens(tokens);
3821        let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Let);
3822        print_subexpression(&e.expr, right_prec < Precedence::Let, tokens, right_fixup);
3823    }
3824
3825    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3826    impl ToTokens for ExprLit {
3827        fn to_tokens(&self, tokens: &mut TokenStream) {
3828            outer_attrs_to_tokens(&self.attrs, tokens);
3829            self.lit.to_tokens(tokens);
3830        }
3831    }
3832
3833    #[cfg(feature = "full")]
3834    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3835    impl ToTokens for ExprLoop {
3836        fn to_tokens(&self, tokens: &mut TokenStream) {
3837            outer_attrs_to_tokens(&self.attrs, tokens);
3838            self.label.to_tokens(tokens);
3839            self.loop_token.to_tokens(tokens);
3840            self.body.brace_token.surround(tokens, |tokens| {
3841                inner_attrs_to_tokens(&self.attrs, tokens);
3842                tokens.append_all(&self.body.stmts);
3843            });
3844        }
3845    }
3846
3847    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3848    impl ToTokens for ExprMacro {
3849        fn to_tokens(&self, tokens: &mut TokenStream) {
3850            outer_attrs_to_tokens(&self.attrs, tokens);
3851            self.mac.to_tokens(tokens);
3852        }
3853    }
3854
3855    #[cfg(feature = "full")]
3856    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3857    impl ToTokens for ExprMatch {
3858        fn to_tokens(&self, tokens: &mut TokenStream) {
3859            outer_attrs_to_tokens(&self.attrs, tokens);
3860            self.match_token.to_tokens(tokens);
3861            print_expr(&self.expr, tokens, FixupContext::new_condition());
3862            self.brace_token.surround(tokens, |tokens| {
3863                inner_attrs_to_tokens(&self.attrs, tokens);
3864                for (i, arm) in self.arms.iter().enumerate() {
3865                    arm.to_tokens(tokens);
3866                    // Ensure that we have a comma after a non-block arm, except
3867                    // for the last one.
3868                    let is_last = i == self.arms.len() - 1;
3869                    if !is_last
3870                        && classify::requires_comma_to_be_match_arm(&arm.body)
3871                        && arm.comma.is_none()
3872                    {
3873                        <Token![,]>::default().to_tokens(tokens);
3874                    }
3875                }
3876            });
3877        }
3878    }
3879
3880    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3881    impl ToTokens for ExprMethodCall {
3882        fn to_tokens(&self, tokens: &mut TokenStream) {
3883            print_expr_method_call(self, tokens, FixupContext::NONE);
3884        }
3885    }
3886
3887    fn print_expr_method_call(e: &ExprMethodCall, tokens: &mut TokenStream, fixup: FixupContext) {
3888        outer_attrs_to_tokens(&e.attrs, tokens);
3889        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.receiver);
3890        print_subexpression(
3891            &e.receiver,
3892            left_prec < Precedence::Unambiguous,
3893            tokens,
3894            left_fixup,
3895        );
3896        e.dot_token.to_tokens(tokens);
3897        e.method.to_tokens(tokens);
3898        if let Some(turbofish) = &e.turbofish {
3899            path::printing::print_angle_bracketed_generic_arguments(
3900                tokens,
3901                turbofish,
3902                PathStyle::Expr,
3903            );
3904        }
3905        e.paren_token.surround(tokens, |tokens| {
3906            e.args.to_tokens(tokens);
3907        });
3908    }
3909
3910    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3911    impl ToTokens for ExprParen {
3912        fn to_tokens(&self, tokens: &mut TokenStream) {
3913            outer_attrs_to_tokens(&self.attrs, tokens);
3914            self.paren_token.surround(tokens, |tokens| {
3915                self.expr.to_tokens(tokens);
3916            });
3917        }
3918    }
3919
3920    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3921    impl ToTokens for ExprPath {
3922        fn to_tokens(&self, tokens: &mut TokenStream) {
3923            outer_attrs_to_tokens(&self.attrs, tokens);
3924            path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
3925        }
3926    }
3927
3928    #[cfg(feature = "full")]
3929    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3930    impl ToTokens for ExprRange {
3931        fn to_tokens(&self, tokens: &mut TokenStream) {
3932            print_expr_range(self, tokens, FixupContext::NONE);
3933        }
3934    }
3935
3936    #[cfg(feature = "full")]
3937    fn print_expr_range(e: &ExprRange, tokens: &mut TokenStream, mut fixup: FixupContext) {
3938        outer_attrs_to_tokens(&e.attrs, tokens);
3939
3940        let needs_group = !e.attrs.is_empty();
3941        if needs_group {
3942            fixup = FixupContext::NONE;
3943        }
3944
3945        let do_print_expr = |tokens: &mut TokenStream| {
3946            if let Some(start) = &e.start {
3947                let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3948                    start,
3949                    true,
3950                    false,
3951                    Precedence::Range,
3952                );
3953                print_subexpression(start, left_prec <= Precedence::Range, tokens, left_fixup);
3954            }
3955            e.limits.to_tokens(tokens);
3956            if let Some(end) = &e.end {
3957                let right_fixup =
3958                    fixup.rightmost_subexpression_fixup(false, true, Precedence::Range);
3959                let right_prec = right_fixup.rightmost_subexpression_precedence(end);
3960                print_subexpression(end, right_prec <= Precedence::Range, tokens, right_fixup);
3961            }
3962        };
3963
3964        if needs_group {
3965            token::Paren::default().surround(tokens, do_print_expr);
3966        } else {
3967            do_print_expr(tokens);
3968        }
3969    }
3970
3971    #[cfg(feature = "full")]
3972    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3973    impl ToTokens for ExprRawAddr {
3974        fn to_tokens(&self, tokens: &mut TokenStream) {
3975            print_expr_raw_addr(self, tokens, FixupContext::NONE);
3976        }
3977    }
3978
3979    #[cfg(feature = "full")]
3980    fn print_expr_raw_addr(e: &ExprRawAddr, tokens: &mut TokenStream, fixup: FixupContext) {
3981        outer_attrs_to_tokens(&e.attrs, tokens);
3982        e.and_token.to_tokens(tokens);
3983        e.raw.to_tokens(tokens);
3984        e.mutability.to_tokens(tokens);
3985        let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Prefix);
3986        print_subexpression(
3987            &e.expr,
3988            right_prec < Precedence::Prefix,
3989            tokens,
3990            right_fixup,
3991        );
3992    }
3993
3994    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3995    impl ToTokens for ExprReference {
3996        fn to_tokens(&self, tokens: &mut TokenStream) {
3997            print_expr_reference(self, tokens, FixupContext::NONE);
3998        }
3999    }
4000
4001    fn print_expr_reference(e: &ExprReference, tokens: &mut TokenStream, fixup: FixupContext) {
4002        outer_attrs_to_tokens(&e.attrs, tokens);
4003        e.and_token.to_tokens(tokens);
4004        e.mutability.to_tokens(tokens);
4005        let (right_prec, right_fixup) = fixup.rightmost_subexpression(
4006            &e.expr,
4007            #[cfg(feature = "full")]
4008            Precedence::Prefix,
4009        );
4010        print_subexpression(
4011            &e.expr,
4012            right_prec < Precedence::Prefix,
4013            tokens,
4014            right_fixup,
4015        );
4016    }
4017
4018    #[cfg(feature = "full")]
4019    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4020    impl ToTokens for ExprRepeat {
4021        fn to_tokens(&self, tokens: &mut TokenStream) {
4022            outer_attrs_to_tokens(&self.attrs, tokens);
4023            self.bracket_token.surround(tokens, |tokens| {
4024                self.expr.to_tokens(tokens);
4025                self.semi_token.to_tokens(tokens);
4026                self.len.to_tokens(tokens);
4027            });
4028        }
4029    }
4030
4031    #[cfg(feature = "full")]
4032    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4033    impl ToTokens for ExprReturn {
4034        fn to_tokens(&self, tokens: &mut TokenStream) {
4035            print_expr_return(self, tokens, FixupContext::NONE);
4036        }
4037    }
4038
4039    #[cfg(feature = "full")]
4040    fn print_expr_return(e: &ExprReturn, tokens: &mut TokenStream, fixup: FixupContext) {
4041        outer_attrs_to_tokens(&e.attrs, tokens);
4042        e.return_token.to_tokens(tokens);
4043        if let Some(expr) = &e.expr {
4044            print_expr(
4045                expr,
4046                tokens,
4047                fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
4048            );
4049        }
4050    }
4051
4052    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4053    impl ToTokens for ExprStruct {
4054        fn to_tokens(&self, tokens: &mut TokenStream) {
4055            outer_attrs_to_tokens(&self.attrs, tokens);
4056            path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
4057            self.brace_token.surround(tokens, |tokens| {
4058                self.fields.to_tokens(tokens);
4059                if let Some(dot2_token) = &self.dot2_token {
4060                    dot2_token.to_tokens(tokens);
4061                } else if self.rest.is_some() {
4062                    Token![..](Span::call_site()).to_tokens(tokens);
4063                }
4064                self.rest.to_tokens(tokens);
4065            });
4066        }
4067    }
4068
4069    #[cfg(feature = "full")]
4070    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4071    impl ToTokens for ExprTry {
4072        fn to_tokens(&self, tokens: &mut TokenStream) {
4073            print_expr_try(self, tokens, FixupContext::NONE);
4074        }
4075    }
4076
4077    #[cfg(feature = "full")]
4078    fn print_expr_try(e: &ExprTry, tokens: &mut TokenStream, fixup: FixupContext) {
4079        outer_attrs_to_tokens(&e.attrs, tokens);
4080        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.expr);
4081        print_subexpression(
4082            &e.expr,
4083            left_prec < Precedence::Unambiguous,
4084            tokens,
4085            left_fixup,
4086        );
4087        e.question_token.to_tokens(tokens);
4088    }
4089
4090    #[cfg(feature = "full")]
4091    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4092    impl ToTokens for ExprTryBlock {
4093        fn to_tokens(&self, tokens: &mut TokenStream) {
4094            outer_attrs_to_tokens(&self.attrs, tokens);
4095            self.try_token.to_tokens(tokens);
4096            self.block.to_tokens(tokens);
4097        }
4098    }
4099
4100    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4101    impl ToTokens for ExprTuple {
4102        fn to_tokens(&self, tokens: &mut TokenStream) {
4103            outer_attrs_to_tokens(&self.attrs, tokens);
4104            self.paren_token.surround(tokens, |tokens| {
4105                self.elems.to_tokens(tokens);
4106                // If we only have one argument, we need a trailing comma to
4107                // distinguish ExprTuple from ExprParen.
4108                if self.elems.len() == 1 && !self.elems.trailing_punct() {
4109                    <Token![,]>::default().to_tokens(tokens);
4110                }
4111            });
4112        }
4113    }
4114
4115    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4116    impl ToTokens for ExprUnary {
4117        fn to_tokens(&self, tokens: &mut TokenStream) {
4118            print_expr_unary(self, tokens, FixupContext::NONE);
4119        }
4120    }
4121
4122    fn print_expr_unary(e: &ExprUnary, tokens: &mut TokenStream, fixup: FixupContext) {
4123        outer_attrs_to_tokens(&e.attrs, tokens);
4124        e.op.to_tokens(tokens);
4125        let (right_prec, right_fixup) = fixup.rightmost_subexpression(
4126            &e.expr,
4127            #[cfg(feature = "full")]
4128            Precedence::Prefix,
4129        );
4130        print_subexpression(
4131            &e.expr,
4132            right_prec < Precedence::Prefix,
4133            tokens,
4134            right_fixup,
4135        );
4136    }
4137
4138    #[cfg(feature = "full")]
4139    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4140    impl ToTokens for ExprUnsafe {
4141        fn to_tokens(&self, tokens: &mut TokenStream) {
4142            outer_attrs_to_tokens(&self.attrs, tokens);
4143            self.unsafe_token.to_tokens(tokens);
4144            self.block.brace_token.surround(tokens, |tokens| {
4145                inner_attrs_to_tokens(&self.attrs, tokens);
4146                tokens.append_all(&self.block.stmts);
4147            });
4148        }
4149    }
4150
4151    #[cfg(feature = "full")]
4152    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4153    impl ToTokens for ExprWhile {
4154        fn to_tokens(&self, tokens: &mut TokenStream) {
4155            outer_attrs_to_tokens(&self.attrs, tokens);
4156            self.label.to_tokens(tokens);
4157            self.while_token.to_tokens(tokens);
4158            print_expr(&self.cond, tokens, FixupContext::new_condition());
4159            self.body.brace_token.surround(tokens, |tokens| {
4160                inner_attrs_to_tokens(&self.attrs, tokens);
4161                tokens.append_all(&self.body.stmts);
4162            });
4163        }
4164    }
4165
4166    #[cfg(feature = "full")]
4167    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4168    impl ToTokens for ExprYield {
4169        fn to_tokens(&self, tokens: &mut TokenStream) {
4170            print_expr_yield(self, tokens, FixupContext::NONE);
4171        }
4172    }
4173
4174    #[cfg(feature = "full")]
4175    fn print_expr_yield(e: &ExprYield, tokens: &mut TokenStream, fixup: FixupContext) {
4176        outer_attrs_to_tokens(&e.attrs, tokens);
4177        e.yield_token.to_tokens(tokens);
4178        if let Some(expr) = &e.expr {
4179            print_expr(
4180                expr,
4181                tokens,
4182                fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
4183            );
4184        }
4185    }
4186
4187    #[cfg(feature = "full")]
4188    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4189    impl ToTokens for Arm {
4190        fn to_tokens(&self, tokens: &mut TokenStream) {
4191            tokens.append_all(&self.attrs);
4192            self.pat.to_tokens(tokens);
4193            self.fat_arrow_token.to_tokens(tokens);
4194            print_expr(&self.body, tokens, FixupContext::new_match_arm());
4195            self.comma.to_tokens(tokens);
4196        }
4197    }
4198
4199    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4200    impl ToTokens for FieldValue {
4201        fn to_tokens(&self, tokens: &mut TokenStream) {
4202            outer_attrs_to_tokens(&self.attrs, tokens);
4203            self.member.to_tokens(tokens);
4204            if let Some(colon_token) = &self.colon_token {
4205                colon_token.to_tokens(tokens);
4206                self.expr.to_tokens(tokens);
4207            }
4208        }
4209    }
4210
4211    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4212    impl ToTokens for Index {
4213        fn to_tokens(&self, tokens: &mut TokenStream) {
4214            let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
4215            lit.set_span(self.span);
4216            tokens.append(lit);
4217        }
4218    }
4219
4220    #[cfg(feature = "full")]
4221    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4222    impl ToTokens for Label {
4223        fn to_tokens(&self, tokens: &mut TokenStream) {
4224            self.name.to_tokens(tokens);
4225            self.colon_token.to_tokens(tokens);
4226        }
4227    }
4228
4229    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4230    impl ToTokens for Member {
4231        fn to_tokens(&self, tokens: &mut TokenStream) {
4232            match self {
4233                Member::Named(ident) => ident.to_tokens(tokens),
4234                Member::Unnamed(index) => index.to_tokens(tokens),
4235            }
4236        }
4237    }
4238
4239    #[cfg(feature = "full")]
4240    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4241    impl ToTokens for RangeLimits {
4242        fn to_tokens(&self, tokens: &mut TokenStream) {
4243            match self {
4244                RangeLimits::HalfOpen(t) => t.to_tokens(tokens),
4245                RangeLimits::Closed(t) => t.to_tokens(tokens),
4246            }
4247        }
4248    }
4249}