syn/
expr.rs

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