Skip to main content

syn/
expr.rs

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