Skip to main content

syn/
expr.rs

1use crate::attr::Attribute;
2#[cfg(all(feature = "parsing", feature = "full"))]
3use crate::error::Result;
4#[cfg(feature = "parsing")]
5use crate::ext::IdentExt as _;
6#[cfg(feature = "full")]
7use crate::generics::BoundLifetimes;
8use crate::ident::Ident;
9#[cfg(any(feature = "parsing", feature = "full"))]
10use crate::lifetime::Lifetime;
11use crate::lit::Lit;
12use crate::mac::Macro;
13use crate::op::{BinOp, UnOp};
14#[cfg(feature = "parsing")]
15use crate::parse::ParseStream;
16#[cfg(feature = "full")]
17use crate::pat::Pat;
18use crate::path::{AngleBracketedGenericArguments, Path, QSelf};
19use crate::punctuated::Punctuated;
20#[cfg(feature = "full")]
21use crate::stmt::Block;
22use crate::token;
23use crate::ty::Type;
24#[cfg(feature = "full")]
25use crate::ty::{PointerMutability, ReturnType};
26use alloc::boxed::Box;
27use alloc::vec::Vec;
28#[cfg(feature = "printing")]
29use core::fmt::{self, Display};
30use core::hash::{Hash, Hasher};
31#[cfg(all(feature = "parsing", feature = "full"))]
32use core::mem;
33use proc_macro2::{Span, TokenStream};
34#[cfg(feature = "printing")]
35use quote::IdentFragment;
36
37#[doc = r" A Rust expression."]
#[doc = r""]
#[doc =
r#" *This type is available only if Syn is built with the `"derive"` or `"full"`"#]
#[doc =
r#" feature, but most of the variants are not available unless "full" is enabled.*"#]
#[doc = r""]
#[doc = r" # Syntax tree enums"]
#[doc = r""]
#[doc =
r" This type is a syntax tree enum. In Syn this and other syntax tree enums"]
#[doc = r" are designed to be traversed using the following rebinding idiom."]
#[doc = r""]
#[doc = r" ```"]
#[doc = r" # use syn::Expr;"]
#[doc = r" #"]
#[doc = r" # fn example(expr: Expr) {"]
#[doc = r" # const IGNORE: &str = stringify! {"]
#[doc = r" let expr: Expr = /* ... */;"]
#[doc = r" # };"]
#[doc = r" match expr {"]
#[doc = r"     Expr::MethodCall(expr) => {"]
#[doc = r"         /* ... */"]
#[doc = r"     }"]
#[doc = r"     Expr::Cast(expr) => {"]
#[doc = r"         /* ... */"]
#[doc = r"     }"]
#[doc = r"     Expr::If(expr) => {"]
#[doc = r"         /* ... */"]
#[doc = r"     }"]
#[doc = r""]
#[doc = r"     /* ... */"]
#[doc = r"     # _ => {}"]
#[doc = r" # }"]
#[doc = r" # }"]
#[doc = r" ```"]
#[doc = r""]
#[doc = r" We begin with a variable `expr` of type `Expr` that has no fields"]
#[doc =
r" (because it is an enum), and by matching on it and rebinding a variable"]
#[doc =
r" with the same name `expr` we effectively imbue our variable with all of"]
#[doc =
r" the data fields provided by the variant that it turned out to be. So for"]
#[doc =
r" example above if we ended up in the `MethodCall` case then we get to use"]
#[doc =
r" `expr.receiver`, `expr.args` etc; if we ended up in the `If` case we get"]
#[doc = r" to use `expr.cond`, `expr.then_branch`, `expr.else_branch`."]
#[doc = r""]
#[doc =
r" This approach avoids repeating the variant names twice on every line."]
#[doc = r""]
#[doc = r" ```"]
#[doc = r" # use syn::{Expr, ExprMethodCall};"]
#[doc = r" #"]
#[doc = r" # fn example(expr: Expr) {"]
#[doc = r" // Repetitive; recommend not doing this."]
#[doc = r" match expr {"]
#[doc = r"     Expr::MethodCall(ExprMethodCall { method, args, .. }) => {"]
#[doc = r" # }"]
#[doc = r" # _ => {}"]
#[doc = r" # }"]
#[doc = r" # }"]
#[doc = r" ```"]
#[doc = r""]
#[doc =
r" In general, the name to which a syntax tree enum variant is bound should"]
#[doc = r" be a suitable name for the complete syntax tree enum type."]
#[doc = r""]
#[doc = r" ```"]
#[doc = r" # use syn::{Expr, ExprField};"]
#[doc = r" #"]
#[doc = r" # fn example(discriminant: ExprField) {"]
#[doc =
r" // Binding is called `base` which is the name I would use if I were"]
#[doc = r" // assigning `*discriminant.base` without an `if let`."]
#[doc = r" if let Expr::Tuple(base) = *discriminant.base {"]
#[doc = r" # }"]
#[doc = r" # }"]
#[doc = r" ```"]
#[doc = r""]
#[doc =
r" A sign that you may not be choosing the right variable names is if you"]
#[doc = r" see names getting repeated in your code, like accessing"]
#[doc = r" `receiver.receiver` or `pat.pat` or `cond.cond`."]
#[doc = r""]
#[doc = r" # Exhaustive matching"]
#[doc = r""]
#[doc =
r" For testing exhaustiveness in downstream code, use the following idiom:"]
#[doc = r""]
#[doc = r" ```"]
#[doc = r" # use syn::Expr;"]
#[doc = r" #"]
#[doc = r" # fn example(expr: Expr) {"]
#[doc = r" match expr {"]
#[doc = r"     #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]"]
#[doc = r""]
#[doc = r"     Expr::Array(expr) => { /*...*/ }"]
#[doc = r"     Expr::Assign(expr) => { /*...*/ }"]
#[doc = "     ..."]
#[doc = r"     Expr::Yield(expr) => { /*...*/ }"]
#[doc = r""]
#[doc = r"     _ => { /* some sane fallback */ }"]
#[doc = r" }"]
#[doc = r" # }"]
#[doc = r" ```"]
#[doc = r""]
#[doc =
r" This way we fail your tests but don't break your library when adding a"]
#[doc =
r" variant. You will be notified by a test failure when a variant is added,"]
#[doc =
r" so that you can add code to handle it, but your library will continue to"]
#[doc = r" compile and work for downstream users in the interim."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
#[non_exhaustive]
pub enum Expr {

    #[doc = r" A slice literal expression: `[a, b, c, d]`."]
    #[doc(cfg(feature = "full"))]
    Array(ExprArray),

    #[doc = r" An assignment expression: `a = compute()`."]
    #[doc(cfg(feature = "full"))]
    Assign(ExprAssign),

    #[doc = r" An async block: `async { ... }`."]
    #[doc(cfg(feature = "full"))]
    Async(ExprAsync),

    #[doc = r" An await expression: `fut.await`."]
    #[doc(cfg(feature = "full"))]
    Await(ExprAwait),

    #[doc = r" A binary operation: `a + b`, `a += b`."]
    Binary(ExprBinary),

    #[doc = r" A braced block: `{ ... }`."]
    #[doc(cfg(feature = "full"))]
    Block(ExprBlock),

    #[doc = r" A `break`, with an optional label to break and an optional"]
    #[doc = r" expression."]
    #[doc(cfg(feature = "full"))]
    Break(ExprBreak),

    #[doc = r" A function call expression: `invoke(a, b)`."]
    Call(ExprCall),

    #[doc = r" A cast expression: `foo as f64`."]
    Cast(ExprCast),

    #[doc = r" A closure expression: `|a, b| a + b`."]
    #[doc(cfg(feature = "full"))]
    Closure(ExprClosure),

    #[doc = r" A const block: `const { ... }`."]
    #[doc(cfg(feature = "full"))]
    Const(ExprConst),

    #[doc = r" A `continue`, with an optional label."]
    #[doc(cfg(feature = "full"))]
    Continue(ExprContinue),

    #[doc =
    r" Access of a named struct field (`obj.k`) or unnamed tuple struct"]
    #[doc = r" field (`obj.0`)."]
    Field(ExprField),

    #[doc = r" A for loop: `for pat in expr { ... }`."]
    #[doc(cfg(feature = "full"))]
    ForLoop(ExprForLoop),

    #[doc = r" An expression contained within invisible delimiters."]
    #[doc = r""]
    #[doc =
    r" This variant is important for faithfully representing the precedence"]
    #[doc = r" of expressions and is related to `None`-delimited spans in a"]
    #[doc = r" `TokenStream`."]
    Group(ExprGroup),

    #[doc =
    r" An `if` expression with an optional `else` block: `if expr { ... }"]
    #[doc = r" else { ... }`."]
    #[doc = r""]
    #[doc = r" The `else` branch expression may only be an `If` or `Block`"]
    #[doc = r" expression, not any of the other types of expression."]
    #[doc(cfg(feature = "full"))]
    If(ExprIf),

    #[doc = r" A square bracketed indexing expression: `vector[2]`."]
    Index(ExprIndex),

    #[doc = r" The inferred value of a const generic argument, denoted `_`."]
    #[doc(cfg(feature = "full"))]
    Infer(ExprInfer),

    #[doc = r" A pattern application: `let Some(x) = opt`."]
    #[doc(cfg(feature = "full"))]
    Let(ExprLet),

    #[doc = r#" A literal in place of an expression: `1`, `"foo"`."#]
    Lit(ExprLit),

    #[doc = r" Conditionless loop: `loop { ... }`."]
    #[doc(cfg(feature = "full"))]
    Loop(ExprLoop),

    #[doc = r#" A macro invocation expression: `format!("{}", q)`."#]
    Macro(ExprMacro),

    #[doc =
    r" A `match` expression: `match n { Some(n) => {}, None => {} }`."]
    #[doc(cfg(feature = "full"))]
    Match(ExprMatch),

    #[doc = r" A method call expression: `x.foo::<T>(a, b)`."]
    MethodCall(ExprMethodCall),

    #[doc = r" A parenthesized expression: `(a + b)`."]
    Paren(ExprParen),

    #[doc = r" A path like `core::mem::replace` possibly containing generic"]
    #[doc = r" parameters and a qualified self-type."]
    #[doc = r""]
    #[doc = r" A plain identifier like `x` is a path of length 1."]
    Path(ExprPath),

    #[doc = r" A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`."]
    #[doc(cfg(feature = "full"))]
    Range(ExprRange),

    #[doc = r" Address-of operation: `&raw const place` or `&raw mut place`."]
    #[doc(cfg(feature = "full"))]
    RawAddr(ExprRawAddr),

    #[doc = r" A referencing operation: `&a` or `&mut a`."]
    Reference(ExprReference),

    #[doc =
    r" An array literal constructed from one repeated element: `[0u8; N]`."]
    #[doc(cfg(feature = "full"))]
    Repeat(ExprRepeat),

    #[doc = r" A `return`, with an optional value to be returned."]
    #[doc(cfg(feature = "full"))]
    Return(ExprReturn),

    #[doc = r" A struct literal expression: `Point { x: 1, y: 1 }`."]
    #[doc = r""]
    #[doc =
    r" The `rest` provides the value of the remaining fields as in `S { a:"]
    #[doc = r" 1, b: 1, ..rest }`."]
    Struct(ExprStruct),

    #[doc = r" A try-expression: `expr?`."]
    #[doc(cfg(feature = "full"))]
    Try(ExprTry),

    #[doc = r" A try block: `try { ... }`."]
    #[doc(cfg(feature = "full"))]
    TryBlock(ExprTryBlock),

    #[doc = r" A tuple expression: `(a, b, c, d)`."]
    Tuple(ExprTuple),

    #[doc = r" A unary operation: `!x`, `*x`, `-x`."]
    Unary(ExprUnary),

    #[doc = r" An unsafe block: `unsafe { ... }`."]
    #[doc(cfg(feature = "full"))]
    Unsafe(ExprUnsafe),

    #[doc = r" Tokens in expression position not interpreted by Syn."]
    #[doc = r""]
    #[doc = r#" <div class="warning">"#]
    #[doc = r""]
    #[doc =
    r" Important: see [Compatibility notes][crate#verbatim-variants]."]
    #[doc = r""]
    #[doc = r" </div>"]
    Verbatim(TokenStream),

    #[doc = r" A while loop: `while expr { ... }`."]
    #[doc(cfg(feature = "full"))]
    While(ExprWhile),

    #[doc = r" A yield expression: `yield expr`."]
    #[doc(cfg(feature = "full"))]
    Yield(ExprYield),
}
#[doc(cfg(feature = "printing"))]
impl ::quote::ToTokens for Expr {
    fn to_tokens(&self, tokens: &mut ::proc_macro2::TokenStream) {
        match self {
            Expr::Array(_e) => _e.to_tokens(tokens),
            Expr::Assign(_e) => _e.to_tokens(tokens),
            Expr::Async(_e) => _e.to_tokens(tokens),
            Expr::Await(_e) => _e.to_tokens(tokens),
            Expr::Binary(_e) => _e.to_tokens(tokens),
            Expr::Block(_e) => _e.to_tokens(tokens),
            Expr::Break(_e) => _e.to_tokens(tokens),
            Expr::Call(_e) => _e.to_tokens(tokens),
            Expr::Cast(_e) => _e.to_tokens(tokens),
            Expr::Closure(_e) => _e.to_tokens(tokens),
            Expr::Const(_e) => _e.to_tokens(tokens),
            Expr::Continue(_e) => _e.to_tokens(tokens),
            Expr::Field(_e) => _e.to_tokens(tokens),
            Expr::ForLoop(_e) => _e.to_tokens(tokens),
            Expr::Group(_e) => _e.to_tokens(tokens),
            Expr::If(_e) => _e.to_tokens(tokens),
            Expr::Index(_e) => _e.to_tokens(tokens),
            Expr::Infer(_e) => _e.to_tokens(tokens),
            Expr::Let(_e) => _e.to_tokens(tokens),
            Expr::Lit(_e) => _e.to_tokens(tokens),
            Expr::Loop(_e) => _e.to_tokens(tokens),
            Expr::Macro(_e) => _e.to_tokens(tokens),
            Expr::Match(_e) => _e.to_tokens(tokens),
            Expr::MethodCall(_e) => _e.to_tokens(tokens),
            Expr::Paren(_e) => _e.to_tokens(tokens),
            Expr::Path(_e) => _e.to_tokens(tokens),
            Expr::Range(_e) => _e.to_tokens(tokens),
            Expr::RawAddr(_e) => _e.to_tokens(tokens),
            Expr::Reference(_e) => _e.to_tokens(tokens),
            Expr::Repeat(_e) => _e.to_tokens(tokens),
            Expr::Return(_e) => _e.to_tokens(tokens),
            Expr::Struct(_e) => _e.to_tokens(tokens),
            Expr::Try(_e) => _e.to_tokens(tokens),
            Expr::TryBlock(_e) => _e.to_tokens(tokens),
            Expr::Tuple(_e) => _e.to_tokens(tokens),
            Expr::Unary(_e) => _e.to_tokens(tokens),
            Expr::Unsafe(_e) => _e.to_tokens(tokens),
            Expr::Verbatim(_e) => _e.to_tokens(tokens),
            Expr::While(_e) => _e.to_tokens(tokens),
            Expr::Yield(_e) => _e.to_tokens(tokens),
        }
    }
}ast_enum_of_structs! {
38    /// A Rust expression.
39    ///
40    /// *This type is available only if Syn is built with the `"derive"` or `"full"`
41    /// feature, but most of the variants are not available unless "full" is enabled.*
42    ///
43    /// # Syntax tree enums
44    ///
45    /// This type is a syntax tree enum. In Syn this and other syntax tree enums
46    /// are designed to be traversed using the following rebinding idiom.
47    ///
48    /// ```
49    /// # use syn::Expr;
50    /// #
51    /// # fn example(expr: Expr) {
52    /// # const IGNORE: &str = stringify! {
53    /// let expr: Expr = /* ... */;
54    /// # };
55    /// match expr {
56    ///     Expr::MethodCall(expr) => {
57    ///         /* ... */
58    ///     }
59    ///     Expr::Cast(expr) => {
60    ///         /* ... */
61    ///     }
62    ///     Expr::If(expr) => {
63    ///         /* ... */
64    ///     }
65    ///
66    ///     /* ... */
67    ///     # _ => {}
68    /// # }
69    /// # }
70    /// ```
71    ///
72    /// We begin with a variable `expr` of type `Expr` that has no fields
73    /// (because it is an enum), and by matching on it and rebinding a variable
74    /// with the same name `expr` we effectively imbue our variable with all of
75    /// the data fields provided by the variant that it turned out to be. So for
76    /// example above if we ended up in the `MethodCall` case then we get to use
77    /// `expr.receiver`, `expr.args` etc; if we ended up in the `If` case we get
78    /// to use `expr.cond`, `expr.then_branch`, `expr.else_branch`.
79    ///
80    /// This approach avoids repeating the variant names twice on every line.
81    ///
82    /// ```
83    /// # use syn::{Expr, ExprMethodCall};
84    /// #
85    /// # fn example(expr: Expr) {
86    /// // Repetitive; recommend not doing this.
87    /// match expr {
88    ///     Expr::MethodCall(ExprMethodCall { method, args, .. }) => {
89    /// # }
90    /// # _ => {}
91    /// # }
92    /// # }
93    /// ```
94    ///
95    /// In general, the name to which a syntax tree enum variant is bound should
96    /// be a suitable name for the complete syntax tree enum type.
97    ///
98    /// ```
99    /// # use syn::{Expr, ExprField};
100    /// #
101    /// # fn example(discriminant: ExprField) {
102    /// // Binding is called `base` which is the name I would use if I were
103    /// // assigning `*discriminant.base` without an `if let`.
104    /// if let Expr::Tuple(base) = *discriminant.base {
105    /// # }
106    /// # }
107    /// ```
108    ///
109    /// A sign that you may not be choosing the right variable names is if you
110    /// see names getting repeated in your code, like accessing
111    /// `receiver.receiver` or `pat.pat` or `cond.cond`.
112    ///
113    /// # Exhaustive matching
114    ///
115    /// For testing exhaustiveness in downstream code, use the following idiom:
116    ///
117    /// ```
118    /// # use syn::Expr;
119    /// #
120    /// # fn example(expr: Expr) {
121    /// match expr {
122    ///     #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
123    ///
124    ///     Expr::Array(expr) => { /*...*/ }
125    ///     Expr::Assign(expr) => { /*...*/ }
126    #[cfg_attr(not(doctest), doc = "     ...")]
127    ///     Expr::Yield(expr) => { /*...*/ }
128    ///
129    ///     _ => { /* some sane fallback */ }
130    /// }
131    /// # }
132    /// ```
133    ///
134    /// This way we fail your tests but don't break your library when adding a
135    /// variant. You will be notified by a test failure when a variant is added,
136    /// so that you can add code to handle it, but your library will continue to
137    /// compile and work for downstream users in the interim.
138    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
139    #[non_exhaustive]
140    pub enum Expr {
141        /// A slice literal expression: `[a, b, c, d]`.
142        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
143        Array(ExprArray),
144
145        /// An assignment expression: `a = compute()`.
146        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
147        Assign(ExprAssign),
148
149        /// An async block: `async { ... }`.
150        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
151        Async(ExprAsync),
152
153        /// An await expression: `fut.await`.
154        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
155        Await(ExprAwait),
156
157        /// A binary operation: `a + b`, `a += b`.
158        Binary(ExprBinary),
159
160        /// A braced block: `{ ... }`.
161        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
162        Block(ExprBlock),
163
164        /// A `break`, with an optional label to break and an optional
165        /// expression.
166        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
167        Break(ExprBreak),
168
169        /// A function call expression: `invoke(a, b)`.
170        Call(ExprCall),
171
172        /// A cast expression: `foo as f64`.
173        Cast(ExprCast),
174
175        /// A closure expression: `|a, b| a + b`.
176        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
177        Closure(ExprClosure),
178
179        /// A const block: `const { ... }`.
180        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
181        Const(ExprConst),
182
183        /// A `continue`, with an optional label.
184        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
185        Continue(ExprContinue),
186
187        /// Access of a named struct field (`obj.k`) or unnamed tuple struct
188        /// field (`obj.0`).
189        Field(ExprField),
190
191        /// A for loop: `for pat in expr { ... }`.
192        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
193        ForLoop(ExprForLoop),
194
195        /// An expression contained within invisible delimiters.
196        ///
197        /// This variant is important for faithfully representing the precedence
198        /// of expressions and is related to `None`-delimited spans in a
199        /// `TokenStream`.
200        Group(ExprGroup),
201
202        /// An `if` expression with an optional `else` block: `if expr { ... }
203        /// else { ... }`.
204        ///
205        /// The `else` branch expression may only be an `If` or `Block`
206        /// expression, not any of the other types of expression.
207        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
208        If(ExprIf),
209
210        /// A square bracketed indexing expression: `vector[2]`.
211        Index(ExprIndex),
212
213        /// The inferred value of a const generic argument, denoted `_`.
214        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
215        Infer(ExprInfer),
216
217        /// A pattern application: `let Some(x) = opt`.
218        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
219        Let(ExprLet),
220
221        /// A literal in place of an expression: `1`, `"foo"`.
222        Lit(ExprLit),
223
224        /// Conditionless loop: `loop { ... }`.
225        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
226        Loop(ExprLoop),
227
228        /// A macro invocation expression: `format!("{}", q)`.
229        Macro(ExprMacro),
230
231        /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
232        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
233        Match(ExprMatch),
234
235        /// A method call expression: `x.foo::<T>(a, b)`.
236        MethodCall(ExprMethodCall),
237
238        /// A parenthesized expression: `(a + b)`.
239        Paren(ExprParen),
240
241        /// A path like `core::mem::replace` possibly containing generic
242        /// parameters and a qualified self-type.
243        ///
244        /// A plain identifier like `x` is a path of length 1.
245        Path(ExprPath),
246
247        /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
248        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
249        Range(ExprRange),
250
251        /// Address-of operation: `&raw const place` or `&raw mut place`.
252        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
253        RawAddr(ExprRawAddr),
254
255        /// A referencing operation: `&a` or `&mut a`.
256        Reference(ExprReference),
257
258        /// An array literal constructed from one repeated element: `[0u8; N]`.
259        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
260        Repeat(ExprRepeat),
261
262        /// A `return`, with an optional value to be returned.
263        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
264        Return(ExprReturn),
265
266        /// A struct literal expression: `Point { x: 1, y: 1 }`.
267        ///
268        /// The `rest` provides the value of the remaining fields as in `S { a:
269        /// 1, b: 1, ..rest }`.
270        Struct(ExprStruct),
271
272        /// A try-expression: `expr?`.
273        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
274        Try(ExprTry),
275
276        /// A try block: `try { ... }`.
277        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
278        TryBlock(ExprTryBlock),
279
280        /// A tuple expression: `(a, b, c, d)`.
281        Tuple(ExprTuple),
282
283        /// A unary operation: `!x`, `*x`, `-x`.
284        Unary(ExprUnary),
285
286        /// An unsafe block: `unsafe { ... }`.
287        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
288        Unsafe(ExprUnsafe),
289
290        /// Tokens in expression position not interpreted by Syn.
291        ///
292        /// <div class="warning">
293        ///
294        /// Important: see [Compatibility notes][crate#verbatim-variants].
295        ///
296        /// </div>
297        Verbatim(TokenStream),
298
299        /// A while loop: `while expr { ... }`.
300        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
301        While(ExprWhile),
302
303        /// A yield expression: `yield expr`.
304        #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
305        Yield(ExprYield),
306    }
307}
308
309#[doc = r" A slice literal expression: `[a, b, c, d]`."]
#[doc(cfg(feature = "full"))]
pub struct ExprArray {
    pub attrs: Vec<Attribute>,
    pub bracket_token: token::Bracket,
    pub elems: Punctuated<Expr, crate::token::Comma>,
}ast_struct! {
310    /// A slice literal expression: `[a, b, c, d]`.
311    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
312    pub struct ExprArray #full {
313        pub attrs: Vec<Attribute>,
314        pub bracket_token: token::Bracket,
315        pub elems: Punctuated<Expr, Token![,]>,
316    }
317}
318
319#[doc = r" An assignment expression: `a = compute()`."]
#[doc(cfg(feature = "full"))]
pub struct ExprAssign {
    pub attrs: Vec<Attribute>,
    pub left: Box<Expr>,
    pub eq_token: crate::token::Eq,
    pub right: Box<Expr>,
}ast_struct! {
320    /// An assignment expression: `a = compute()`.
321    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
322    pub struct ExprAssign #full {
323        pub attrs: Vec<Attribute>,
324        pub left: Box<Expr>,
325        pub eq_token: Token![=],
326        pub right: Box<Expr>,
327    }
328}
329
330#[doc = r" An async block: `async { ... }`."]
#[doc(cfg(feature = "full"))]
pub struct ExprAsync {
    pub attrs: Vec<Attribute>,
    pub async_token: crate::token::Async,
    pub capture: Option<crate::token::Move>,
    #[doc =
    r" (Non-exhaustive) Additional optional information about a block."]
    pub modifiers: BlockModifiers,
    pub block: Block,
}ast_struct! {
331    /// An async block: `async { ... }`.
332    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
333    pub struct ExprAsync #full {
334        pub attrs: Vec<Attribute>,
335        pub async_token: Token![async],
336        pub capture: Option<Token![move]>,
337        /// (Non-exhaustive) Additional optional information about a block.
338        pub modifiers: BlockModifiers,
339        pub block: Block,
340    }
341}
342
343#[doc = r" An await expression: `fut.await`."]
#[doc(cfg(feature = "full"))]
pub struct ExprAwait {
    pub attrs: Vec<Attribute>,
    pub base: Box<Expr>,
    pub dot_token: crate::token::Dot,
    pub await_token: crate::token::Await,
}ast_struct! {
344    /// An await expression: `fut.await`.
345    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
346    pub struct ExprAwait #full {
347        pub attrs: Vec<Attribute>,
348        pub base: Box<Expr>,
349        pub dot_token: Token![.],
350        pub await_token: Token![await],
351    }
352}
353
354#[doc = r" A binary operation: `a + b`, `a += b`."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
pub struct ExprBinary {
    pub attrs: Vec<Attribute>,
    pub left: Box<Expr>,
    pub op: BinOp,
    pub right: Box<Expr>,
}ast_struct! {
355    /// A binary operation: `a + b`, `a += b`.
356    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
357    pub struct ExprBinary {
358        pub attrs: Vec<Attribute>,
359        pub left: Box<Expr>,
360        pub op: BinOp,
361        pub right: Box<Expr>,
362    }
363}
364
365#[doc = r" A braced block: `{ ... }`."]
#[doc(cfg(feature = "full"))]
pub struct ExprBlock {
    pub attrs: Vec<Attribute>,
    pub label: Option<Label>,
    pub block: Block,
}ast_struct! {
366    /// A braced block: `{ ... }`.
367    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
368    pub struct ExprBlock #full {
369        pub attrs: Vec<Attribute>,
370        pub label: Option<Label>,
371        pub block: Block,
372    }
373}
374
375#[doc = r" A `break`, with an optional label to break and an optional"]
#[doc = r" expression."]
#[doc(cfg(feature = "full"))]
pub struct ExprBreak {
    pub attrs: Vec<Attribute>,
    pub break_token: crate::token::Break,
    pub label: Option<Lifetime>,
    pub expr: Option<Box<Expr>>,
}ast_struct! {
376    /// A `break`, with an optional label to break and an optional
377    /// expression.
378    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
379    pub struct ExprBreak #full {
380        pub attrs: Vec<Attribute>,
381        pub break_token: Token![break],
382        pub label: Option<Lifetime>,
383        pub expr: Option<Box<Expr>>,
384    }
385}
386
387#[doc = r" A function call expression: `invoke(a, b)`."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
pub struct ExprCall {
    pub attrs: Vec<Attribute>,
    pub func: Box<Expr>,
    pub paren_token: token::Paren,
    pub args: Punctuated<Expr, crate::token::Comma>,
}ast_struct! {
388    /// A function call expression: `invoke(a, b)`.
389    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
390    pub struct ExprCall {
391        pub attrs: Vec<Attribute>,
392        pub func: Box<Expr>,
393        pub paren_token: token::Paren,
394        pub args: Punctuated<Expr, Token![,]>,
395    }
396}
397
398#[doc = r" A cast expression: `foo as f64`."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
pub struct ExprCast {
    pub attrs: Vec<Attribute>,
    pub expr: Box<Expr>,
    pub as_token: crate::token::As,
    pub ty: Box<Type>,
}ast_struct! {
399    /// A cast expression: `foo as f64`.
400    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
401    pub struct ExprCast {
402        pub attrs: Vec<Attribute>,
403        pub expr: Box<Expr>,
404        pub as_token: Token![as],
405        pub ty: Box<Type>,
406    }
407}
408
409#[doc = r" A closure expression: `|a, b| a + b`."]
#[doc(cfg(feature = "full"))]
pub struct ExprClosure {
    pub attrs: Vec<Attribute>,
    pub lifetimes: Option<BoundLifetimes>,
    #[doc =
    r" (Non-exhaustive) Additional optional information about a closure."]
    pub modifiers: ClosureModifiers,
    pub constness: Option<crate::token::Const>,
    pub asyncness: Option<crate::token::Async>,
    pub capture: Option<crate::token::Move>,
    pub inputs_begin: crate::token::Or,
    pub inputs: Punctuated<Pat, crate::token::Comma>,
    pub inputs_end: crate::token::Or,
    pub output: ReturnType,
    pub body: Box<Expr>,
}ast_struct! {
410    /// A closure expression: `|a, b| a + b`.
411    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
412    pub struct ExprClosure #full {
413        pub attrs: Vec<Attribute>,
414        pub lifetimes: Option<BoundLifetimes>,
415        /// (Non-exhaustive) Additional optional information about a closure.
416        pub modifiers: ClosureModifiers,
417        pub constness: Option<Token![const]>,
418        pub asyncness: Option<Token![async]>,
419        pub capture: Option<Token![move]>,
420        pub inputs_begin: Token![|],
421        pub inputs: Punctuated<Pat, Token![,]>,
422        pub inputs_end: Token![|],
423        pub output: ReturnType,
424        pub body: Box<Expr>,
425    }
426}
427
428#[cfg(feature = "full")]
429#[doc = r" Additional optional information about a closure."]
#[doc = r""]
#[doc = r" This data structure may grow to accommodate future Rust language"]
#[doc = r" changes, including the following in-progress RFCs:"]
#[doc = r""]
#[doc = r#" - [RFC 2033] "Coroutines" (`static || ...`)"#]
#[doc = r#" - [RFC 3680] "Simplify lightweight clones" (`use || ...`)"#]
#[doc = r""]
#[doc = r" [RFC 2033]: https://github.com/rust-lang/rust/issues/43122"]
#[doc = r" [RFC 3680]: https://github.com/rust-lang/rust/issues/132290"]
#[doc(cfg(feature = "full"))]
#[non_exhaustive]
pub struct ClosureModifiers {}ast_struct! {
430    /// Additional optional information about a closure.
431    ///
432    /// This data structure may grow to accommodate future Rust language
433    /// changes, including the following in-progress RFCs:
434    ///
435    /// - [RFC 2033] "Coroutines" (`static || ...`)
436    /// - [RFC 3680] "Simplify lightweight clones" (`use || ...`)
437    ///
438    /// [RFC 2033]: https://github.com/rust-lang/rust/issues/43122
439    /// [RFC 3680]: https://github.com/rust-lang/rust/issues/132290
440    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
441    #[non_exhaustive]
442    pub struct ClosureModifiers {}
443}
444
445#[cfg(feature = "full")]
446impl Default for ClosureModifiers {
447    fn default() -> Self {
448        ClosureModifiers {}
449    }
450}
451
452#[cfg(feature = "full")]
453impl ClosureModifiers {
454    #[cfg(feature = "parsing")]
455    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
456    pub fn require_empty(&self) -> Result<()> {
457        Ok(())
458    }
459}
460
461#[doc = r" A const block: `const { ... }`."]
#[doc(cfg(feature = "full"))]
pub struct ExprConst {
    pub attrs: Vec<Attribute>,
    pub const_token: crate::token::Const,
    #[doc =
    r" (Non-exhaustive) Additional optional information about a block."]
    pub modifiers: BlockModifiers,
    pub block: Block,
}ast_struct! {
462    /// A const block: `const { ... }`.
463    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
464    pub struct ExprConst #full {
465        pub attrs: Vec<Attribute>,
466        pub const_token: Token![const],
467        /// (Non-exhaustive) Additional optional information about a block.
468        pub modifiers: BlockModifiers,
469        pub block: Block,
470    }
471}
472
473#[doc = r" A `continue`, with an optional label."]
#[doc(cfg(feature = "full"))]
pub struct ExprContinue {
    pub attrs: Vec<Attribute>,
    pub continue_token: crate::token::Continue,
    pub label: Option<Lifetime>,
}ast_struct! {
474    /// A `continue`, with an optional label.
475    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
476    pub struct ExprContinue #full {
477        pub attrs: Vec<Attribute>,
478        pub continue_token: Token![continue],
479        pub label: Option<Lifetime>,
480    }
481}
482
483#[doc = r" Access of a named struct field (`obj.k`) or unnamed tuple struct"]
#[doc = r" field (`obj.0`)."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
pub struct ExprField {
    pub attrs: Vec<Attribute>,
    pub base: Box<Expr>,
    pub dot_token: crate::token::Dot,
    pub member: Member,
}ast_struct! {
484    /// Access of a named struct field (`obj.k`) or unnamed tuple struct
485    /// field (`obj.0`).
486    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
487    pub struct ExprField {
488        pub attrs: Vec<Attribute>,
489        pub base: Box<Expr>,
490        pub dot_token: Token![.],
491        pub member: Member,
492    }
493}
494
495#[doc = r" A for loop: `for pat in expr { ... }`."]
#[doc(cfg(feature = "full"))]
pub struct ExprForLoop {
    pub attrs: Vec<Attribute>,
    pub label: Option<Label>,
    pub for_token: crate::token::For,
    pub pat: Box<Pat>,
    pub in_token: crate::token::In,
    pub expr: Box<Expr>,
    pub body: Block,
}ast_struct! {
496    /// A for loop: `for pat in expr { ... }`.
497    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
498    pub struct ExprForLoop #full {
499        pub attrs: Vec<Attribute>,
500        pub label: Option<Label>,
501        pub for_token: Token![for],
502        pub pat: Box<Pat>,
503        pub in_token: Token![in],
504        pub expr: Box<Expr>,
505        pub body: Block,
506    }
507}
508
509#[doc = r" An expression contained within invisible delimiters."]
#[doc = r""]
#[doc =
r" This variant is important for faithfully representing the precedence"]
#[doc = r" of expressions and is related to `None`-delimited spans in a"]
#[doc = r" `TokenStream`."]
#[doc(cfg(feature = "full"))]
pub struct ExprGroup {
    pub attrs: Vec<Attribute>,
    pub group_token: token::Group,
    pub expr: Box<Expr>,
}ast_struct! {
510    /// An expression contained within invisible delimiters.
511    ///
512    /// This variant is important for faithfully representing the precedence
513    /// of expressions and is related to `None`-delimited spans in a
514    /// `TokenStream`.
515    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
516    pub struct ExprGroup {
517        pub attrs: Vec<Attribute>,
518        pub group_token: token::Group,
519        pub expr: Box<Expr>,
520    }
521}
522
523#[doc =
r" An `if` expression with an optional `else` block: `if expr { ... }"]
#[doc = r" else { ... }`."]
#[doc = r""]
#[doc = r" The `else` branch expression may only be an `If` or `Block`"]
#[doc = r" expression, not any of the other types of expression."]
#[doc(cfg(feature = "full"))]
pub struct ExprIf {
    pub attrs: Vec<Attribute>,
    pub if_token: crate::token::If,
    pub cond: Box<Expr>,
    pub then_branch: Block,
    pub else_branch: Option<(crate::token::Else, Box<Expr>)>,
}ast_struct! {
524    /// An `if` expression with an optional `else` block: `if expr { ... }
525    /// else { ... }`.
526    ///
527    /// The `else` branch expression may only be an `If` or `Block`
528    /// expression, not any of the other types of expression.
529    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
530    pub struct ExprIf #full {
531        pub attrs: Vec<Attribute>,
532        pub if_token: Token![if],
533        pub cond: Box<Expr>,
534        pub then_branch: Block,
535        pub else_branch: Option<(Token![else], Box<Expr>)>,
536    }
537}
538
539#[doc = r" A square bracketed indexing expression: `vector[2]`."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
pub struct ExprIndex {
    pub attrs: Vec<Attribute>,
    pub expr: Box<Expr>,
    pub bracket_token: token::Bracket,
    pub index: Box<Expr>,
}ast_struct! {
540    /// A square bracketed indexing expression: `vector[2]`.
541    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
542    pub struct ExprIndex {
543        pub attrs: Vec<Attribute>,
544        pub expr: Box<Expr>,
545        pub bracket_token: token::Bracket,
546        pub index: Box<Expr>,
547    }
548}
549
550#[doc = r" The inferred value of a const generic argument, denoted `_`."]
#[doc(cfg(feature = "full"))]
pub struct ExprInfer {
    pub attrs: Vec<Attribute>,
    pub underscore_token: crate::token::Underscore,
}ast_struct! {
551    /// The inferred value of a const generic argument, denoted `_`.
552    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
553    pub struct ExprInfer #full {
554        pub attrs: Vec<Attribute>,
555        pub underscore_token: Token![_],
556    }
557}
558
559#[doc = r" A pattern application: `let Some(x) = opt`."]
#[doc(cfg(feature = "full"))]
pub struct ExprLet {
    pub attrs: Vec<Attribute>,
    pub let_token: crate::token::Let,
    pub pat: Box<Pat>,
    pub eq_token: crate::token::Eq,
    pub expr: Box<Expr>,
}ast_struct! {
560    /// A pattern application: `let Some(x) = opt`.
561    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
562    pub struct ExprLet #full {
563        pub attrs: Vec<Attribute>,
564        pub let_token: Token![let],
565        pub pat: Box<Pat>,
566        pub eq_token: Token![=],
567        pub expr: Box<Expr>,
568    }
569}
570
571#[doc = r#" A literal in place of an expression: `1`, `"foo"`."#]
#[doc(cfg(any(feature = "full", feature = "derive")))]
pub struct ExprLit {
    pub attrs: Vec<Attribute>,
    pub lit: Lit,
}ast_struct! {
572    /// A literal in place of an expression: `1`, `"foo"`.
573    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
574    pub struct ExprLit {
575        pub attrs: Vec<Attribute>,
576        pub lit: Lit,
577    }
578}
579
580#[doc = r" Conditionless loop: `loop { ... }`."]
#[doc(cfg(feature = "full"))]
pub struct ExprLoop {
    pub attrs: Vec<Attribute>,
    pub label: Option<Label>,
    pub loop_token: crate::token::Loop,
    pub body: Block,
}ast_struct! {
581    /// Conditionless loop: `loop { ... }`.
582    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
583    pub struct ExprLoop #full {
584        pub attrs: Vec<Attribute>,
585        pub label: Option<Label>,
586        pub loop_token: Token![loop],
587        pub body: Block,
588    }
589}
590
591#[doc = r#" A macro invocation expression: `format!("{}", q)`."#]
#[doc(cfg(any(feature = "full", feature = "derive")))]
pub struct ExprMacro {
    pub attrs: Vec<Attribute>,
    pub mac: Macro,
}ast_struct! {
592    /// A macro invocation expression: `format!("{}", q)`.
593    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
594    pub struct ExprMacro {
595        pub attrs: Vec<Attribute>,
596        pub mac: Macro,
597    }
598}
599
600#[doc = r" A `match` expression: `match n { Some(n) => {}, None => {} }`."]
#[doc(cfg(feature = "full"))]
pub struct ExprMatch {
    pub attrs: Vec<Attribute>,
    pub match_token: crate::token::Match,
    pub expr: Box<Expr>,
    pub brace_token: token::Brace,
    pub arms: Vec<Arm>,
}ast_struct! {
601    /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
602    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
603    pub struct ExprMatch #full {
604        pub attrs: Vec<Attribute>,
605        pub match_token: Token![match],
606        pub expr: Box<Expr>,
607        pub brace_token: token::Brace,
608        pub arms: Vec<Arm>,
609    }
610}
611
612#[doc = r" A method call expression: `x.foo::<T>(a, b)`."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
pub struct ExprMethodCall {
    pub attrs: Vec<Attribute>,
    pub receiver: Box<Expr>,
    pub dot_token: crate::token::Dot,
    pub method: Ident,
    pub turbofish: Option<AngleBracketedGenericArguments>,
    pub paren_token: token::Paren,
    pub args: Punctuated<Expr, crate::token::Comma>,
}ast_struct! {
613    /// A method call expression: `x.foo::<T>(a, b)`.
614    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
615    pub struct ExprMethodCall {
616        pub attrs: Vec<Attribute>,
617        pub receiver: Box<Expr>,
618        pub dot_token: Token![.],
619        pub method: Ident,
620        pub turbofish: Option<AngleBracketedGenericArguments>,
621        pub paren_token: token::Paren,
622        pub args: Punctuated<Expr, Token![,]>,
623    }
624}
625
626#[doc = r" A parenthesized expression: `(a + b)`."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
pub struct ExprParen {
    pub attrs: Vec<Attribute>,
    pub paren_token: token::Paren,
    pub expr: Box<Expr>,
}ast_struct! {
627    /// A parenthesized expression: `(a + b)`.
628    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
629    pub struct ExprParen {
630        pub attrs: Vec<Attribute>,
631        pub paren_token: token::Paren,
632        pub expr: Box<Expr>,
633    }
634}
635
636#[doc = r" A path like `core::mem::replace` possibly containing generic"]
#[doc = r" parameters and a qualified self-type."]
#[doc = r""]
#[doc = r" A plain identifier like `x` is a path of length 1."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
pub struct ExprPath {
    pub attrs: Vec<Attribute>,
    pub qself: Option<QSelf>,
    pub path: Path,
}ast_struct! {
637    /// A path like `core::mem::replace` possibly containing generic
638    /// parameters and a qualified self-type.
639    ///
640    /// A plain identifier like `x` is a path of length 1.
641    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
642    pub struct ExprPath {
643        pub attrs: Vec<Attribute>,
644        pub qself: Option<QSelf>,
645        pub path: Path,
646    }
647}
648
649#[doc = r" A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`."]
#[doc(cfg(feature = "full"))]
pub struct ExprRange {
    pub attrs: Vec<Attribute>,
    pub start: Option<Box<Expr>>,
    pub limits: RangeLimits,
    pub end: Option<Box<Expr>>,
}ast_struct! {
650    /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
651    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
652    pub struct ExprRange #full {
653        pub attrs: Vec<Attribute>,
654        pub start: Option<Box<Expr>>,
655        pub limits: RangeLimits,
656        pub end: Option<Box<Expr>>,
657    }
658}
659
660#[doc = r" Address-of operation: `&raw const place` or `&raw mut place`."]
#[doc(cfg(feature = "full"))]
pub struct ExprRawAddr {
    pub attrs: Vec<Attribute>,
    pub and_token: crate::token::And,
    pub raw: crate::token::Raw,
    pub mutability: PointerMutability,
    pub expr: Box<Expr>,
}ast_struct! {
661    /// Address-of operation: `&raw const place` or `&raw mut place`.
662    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
663    pub struct ExprRawAddr #full {
664        pub attrs: Vec<Attribute>,
665        pub and_token: Token![&],
666        pub raw: Token![raw],
667        pub mutability: PointerMutability,
668        pub expr: Box<Expr>,
669    }
670}
671
672#[doc = r" A referencing operation: `&a` or `&mut a`."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
pub struct ExprReference {
    pub attrs: Vec<Attribute>,
    pub and_token: crate::token::And,
    pub mutability: Option<crate::token::Mut>,
    pub expr: Box<Expr>,
}ast_struct! {
673    /// A referencing operation: `&a` or `&mut a`.
674    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
675    pub struct ExprReference {
676        pub attrs: Vec<Attribute>,
677        pub and_token: Token![&],
678        pub mutability: Option<Token![mut]>,
679        pub expr: Box<Expr>,
680    }
681}
682
683#[doc =
r" An array literal constructed from one repeated element: `[0u8; N]`."]
#[doc(cfg(feature = "full"))]
pub struct ExprRepeat {
    pub attrs: Vec<Attribute>,
    pub bracket_token: token::Bracket,
    pub expr: Box<Expr>,
    pub semi_token: crate::token::Semi,
    pub len: Box<Expr>,
}ast_struct! {
684    /// An array literal constructed from one repeated element: `[0u8; N]`.
685    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
686    pub struct ExprRepeat #full {
687        pub attrs: Vec<Attribute>,
688        pub bracket_token: token::Bracket,
689        pub expr: Box<Expr>,
690        pub semi_token: Token![;],
691        pub len: Box<Expr>,
692    }
693}
694
695#[doc = r" A `return`, with an optional value to be returned."]
#[doc(cfg(feature = "full"))]
pub struct ExprReturn {
    pub attrs: Vec<Attribute>,
    pub return_token: crate::token::Return,
    pub expr: Option<Box<Expr>>,
}ast_struct! {
696    /// A `return`, with an optional value to be returned.
697    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
698    pub struct ExprReturn #full {
699        pub attrs: Vec<Attribute>,
700        pub return_token: Token![return],
701        pub expr: Option<Box<Expr>>,
702    }
703}
704
705#[doc = r" A struct literal expression: `Point { x: 1, y: 1 }`."]
#[doc = r""]
#[doc =
r" The `rest` provides the value of the remaining fields as in `S { a:"]
#[doc = r" 1, b: 1, ..rest }`."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
pub struct ExprStruct {
    pub attrs: Vec<Attribute>,
    pub qself: Option<QSelf>,
    pub path: Path,
    pub brace_token: token::Brace,
    pub fields: Punctuated<FieldValue, crate::token::Comma>,
    pub dot2_token: Option<crate::token::DotDot>,
    pub rest: Option<Box<Expr>>,
}ast_struct! {
706    /// A struct literal expression: `Point { x: 1, y: 1 }`.
707    ///
708    /// The `rest` provides the value of the remaining fields as in `S { a:
709    /// 1, b: 1, ..rest }`.
710    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
711    pub struct ExprStruct {
712        pub attrs: Vec<Attribute>,
713        pub qself: Option<QSelf>,
714        pub path: Path,
715        pub brace_token: token::Brace,
716        pub fields: Punctuated<FieldValue, Token![,]>,
717        pub dot2_token: Option<Token![..]>,
718        pub rest: Option<Box<Expr>>,
719    }
720}
721
722#[doc = r" A try-expression: `expr?`."]
#[doc(cfg(feature = "full"))]
pub struct ExprTry {
    pub attrs: Vec<Attribute>,
    pub expr: Box<Expr>,
    pub question_token: crate::token::Question,
}ast_struct! {
723    /// A try-expression: `expr?`.
724    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
725    pub struct ExprTry #full {
726        pub attrs: Vec<Attribute>,
727        pub expr: Box<Expr>,
728        pub question_token: Token![?],
729    }
730}
731
732#[doc = r" A try block: `try { ... }`."]
#[doc(cfg(feature = "full"))]
pub struct ExprTryBlock {
    pub attrs: Vec<Attribute>,
    pub try_token: crate::token::Try,
    #[doc =
    r" (Non-exhaustive) Additional optional information about a block."]
    pub modifiers: BlockModifiers,
    pub block: Block,
}ast_struct! {
733    /// A try block: `try { ... }`.
734    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
735    pub struct ExprTryBlock #full {
736        pub attrs: Vec<Attribute>,
737        pub try_token: Token![try],
738        /// (Non-exhaustive) Additional optional information about a block.
739        pub modifiers: BlockModifiers,
740        pub block: Block,
741    }
742}
743
744#[doc = r" A tuple expression: `(a, b, c, d)`."]
#[doc(cfg(feature = "full"))]
pub struct ExprTuple {
    pub attrs: Vec<Attribute>,
    pub paren_token: token::Paren,
    pub elems: Punctuated<Expr, crate::token::Comma>,
}ast_struct! {
745    /// A tuple expression: `(a, b, c, d)`.
746    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
747    pub struct ExprTuple {
748        pub attrs: Vec<Attribute>,
749        pub paren_token: token::Paren,
750        pub elems: Punctuated<Expr, Token![,]>,
751    }
752}
753
754#[doc = r" A unary operation: `!x`, `*x`, `-x`."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
pub struct ExprUnary {
    pub attrs: Vec<Attribute>,
    pub op: UnOp,
    pub expr: Box<Expr>,
}ast_struct! {
755    /// A unary operation: `!x`, `*x`, `-x`.
756    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
757    pub struct ExprUnary {
758        pub attrs: Vec<Attribute>,
759        pub op: UnOp,
760        pub expr: Box<Expr>,
761    }
762}
763
764#[doc = r" An unsafe block: `unsafe { ... }`."]
#[doc(cfg(feature = "full"))]
pub struct ExprUnsafe {
    pub attrs: Vec<Attribute>,
    pub unsafe_token: crate::token::Unsafe,
    pub block: Block,
}ast_struct! {
765    /// An unsafe block: `unsafe { ... }`.
766    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
767    pub struct ExprUnsafe #full {
768        pub attrs: Vec<Attribute>,
769        pub unsafe_token: Token![unsafe],
770        pub block: Block,
771    }
772}
773
774#[doc = r" A while loop: `while expr { ... }`."]
#[doc(cfg(feature = "full"))]
pub struct ExprWhile {
    pub attrs: Vec<Attribute>,
    pub label: Option<Label>,
    pub while_token: crate::token::While,
    pub cond: Box<Expr>,
    pub body: Block,
}ast_struct! {
775    /// A while loop: `while expr { ... }`.
776    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
777    pub struct ExprWhile #full {
778        pub attrs: Vec<Attribute>,
779        pub label: Option<Label>,
780        pub while_token: Token![while],
781        pub cond: Box<Expr>,
782        pub body: Block,
783    }
784}
785
786#[doc = r" A yield expression: `yield expr`."]
#[doc(cfg(feature = "full"))]
pub struct ExprYield {
    pub attrs: Vec<Attribute>,
    pub yield_token: crate::token::Yield,
    pub expr: Option<Box<Expr>>,
}ast_struct! {
787    /// A yield expression: `yield expr`.
788    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
789    pub struct ExprYield #full {
790        pub attrs: Vec<Attribute>,
791        pub yield_token: Token![yield],
792        pub expr: Option<Box<Expr>>,
793    }
794}
795
796impl Expr {
797    /// An unspecified invalid expression.
798    ///
799    /// ```
800    /// use core::mem;
801    /// use quote::ToTokens;
802    /// use syn::{parse_quote, Expr};
803    ///
804    /// fn unparenthesize(e: &mut Expr) {
805    ///     while let Expr::Paren(paren) = e {
806    ///         *e = mem::replace(&mut *paren.expr, Expr::PLACEHOLDER);
807    ///     }
808    /// }
809    ///
810    /// fn main() {
811    ///     let mut e: Expr = parse_quote! { ((1 + 1)) };
812    ///     unparenthesize(&mut e);
813    ///     assert_eq!("1 + 1", e.to_token_stream().to_string());
814    /// }
815    /// ```
816    pub const PLACEHOLDER: Self = Expr::Path(ExprPath {
817        attrs: Vec::new(),
818        qself: None,
819        path: Path {
820            leading_colon: None,
821            segments: Punctuated::new(),
822        },
823    });
824
825    /// An alternative to the primary `Expr::parse` parser (from the [`Parse`]
826    /// trait) for ambiguous syntactic positions in which a trailing brace
827    /// should not be taken as part of the expression.
828    ///
829    /// [`Parse`]: crate::parse::Parse
830    ///
831    /// Rust grammar has an ambiguity where braces sometimes turn a path
832    /// expression into a struct initialization and sometimes do not. In the
833    /// following code, the expression `S {}` is one expression. Presumably
834    /// there is an empty struct `struct S {}` defined somewhere which it is
835    /// instantiating.
836    ///
837    /// ```
838    /// # struct S;
839    /// # impl core::ops::Deref for S {
840    /// #     type Target = bool;
841    /// #     fn deref(&self) -> &Self::Target {
842    /// #         &true
843    /// #     }
844    /// # }
845    /// let _ = *S {};
846    ///
847    /// // parsed by rustc as: `*(S {})`
848    /// ```
849    ///
850    /// We would want to parse the above using `Expr::parse` after the `=`
851    /// token.
852    ///
853    /// But in the following, `S {}` is *not* a struct init expression.
854    ///
855    /// ```
856    /// # const S: &bool = &true;
857    /// if *S {} {}
858    ///
859    /// // parsed by rustc as:
860    /// //
861    /// //    if (*S) {
862    /// //        /* empty block */
863    /// //    }
864    /// //    {
865    /// //        /* another empty block */
866    /// //    }
867    /// ```
868    ///
869    /// For that reason we would want to parse if-conditions using
870    /// `Expr::parse_without_eager_brace` after the `if` token. Same for similar
871    /// syntactic positions such as the condition expr after a `while` token or
872    /// the expr at the top of a `match`.
873    ///
874    /// The Rust grammar's choices around which way this ambiguity is resolved
875    /// at various syntactic positions is fairly arbitrary. Really either parse
876    /// behavior could work in most positions, and language designers just
877    /// decide each case based on which is more likely to be what the programmer
878    /// had in mind most of the time.
879    ///
880    /// ```
881    /// # struct S;
882    /// # fn doc() -> S {
883    /// if return S {} {}
884    /// # unreachable!()
885    /// # }
886    ///
887    /// // parsed by rustc as:
888    /// //
889    /// //    if (return (S {})) {
890    /// //    }
891    /// //
892    /// // but could equally well have been this other arbitrary choice:
893    /// //
894    /// //    if (return S) {
895    /// //    }
896    /// //    {}
897    /// ```
898    ///
899    /// Note the grammar ambiguity on trailing braces is distinct from
900    /// precedence and is not captured by assigning a precedence level to the
901    /// braced struct init expr in relation to other operators. This can be
902    /// illustrated by `return 0..S {}` vs `match 0..S {}`. The former parses as
903    /// `return (0..(S {}))` implying tighter precedence for struct init than
904    /// `..`, while the latter parses as `match (0..S) {}` implying tighter
905    /// precedence for `..` than struct init, a contradiction.
906    #[cfg(all(feature = "full", feature = "parsing"))]
907    #[cfg_attr(docsrs, doc(cfg(all(feature = "full", feature = "parsing"))))]
908    pub fn parse_without_eager_brace(input: ParseStream) -> Result<Expr> {
909        parsing::ambiguous_expr(input, parsing::AllowStruct(false))
910    }
911
912    /// An alternative to the primary `Expr::parse` parser (from the [`Parse`]
913    /// trait) for syntactic positions in which expression boundaries are placed
914    /// more eagerly than done by the typical expression grammar. This includes
915    /// expressions at the head of a statement or in the right-hand side of a
916    /// `match` arm.
917    ///
918    /// [`Parse`]: crate::parse::Parse
919    ///
920    /// Compare the following cases:
921    ///
922    /// 1.
923    ///   ```
924    ///   # let result = ();
925    ///   # let guard = false;
926    ///   # let cond = true;
927    ///   # let f = true;
928    ///   # let g = f;
929    ///   #
930    ///   let _ = match result {
931    ///       () if guard => if cond { f } else { g }
932    ///       () => false,
933    ///   };
934    ///   ```
935    ///
936    /// 2.
937    ///   ```
938    ///   # let cond = true;
939    ///   # let f = ();
940    ///   # let g = f;
941    ///   #
942    ///   let _ = || {
943    ///       if cond { f } else { g }
944    ///       ()
945    ///   };
946    ///   ```
947    ///
948    /// 3.
949    ///   ```
950    ///   # let cond = true;
951    ///   # let f = || ();
952    ///   # let g = f;
953    ///   #
954    ///   let _ = [if cond { f } else { g } ()];
955    ///   ```
956    ///
957    /// The same sequence of tokens `if cond { f } else { g } ()` appears in
958    /// expression position 3 times. The first two syntactic positions use eager
959    /// placement of expression boundaries, and parse as `Expr::If`, with the
960    /// adjacent `()` becoming `Pat::Tuple` or `Expr::Tuple`. In contrast, the
961    /// third case uses standard expression boundaries and parses as
962    /// `Expr::Call`.
963    ///
964    /// As with [`parse_without_eager_brace`], this ambiguity in the Rust
965    /// grammar is independent of precedence.
966    ///
967    /// [`parse_without_eager_brace`]: Self::parse_without_eager_brace
968    #[cfg(all(feature = "full", feature = "parsing"))]
969    #[cfg_attr(docsrs, doc(cfg(all(feature = "full", feature = "parsing"))))]
970    pub fn parse_with_earlier_boundary_rule(input: ParseStream) -> Result<Expr> {
971        parsing::parse_with_earlier_boundary_rule(input)
972    }
973
974    /// Returns whether the next token in the parse stream is one that might
975    /// possibly form the beginning of an expr.
976    ///
977    /// This classification is a load-bearing part of the grammar of some Rust
978    /// expressions, notably `return` and `break`. For example `return < …` will
979    /// never parse `<` as a binary operator regardless of what comes after,
980    /// because `<` is a legal starting token for an expression and so it's
981    /// required to be continued as a return value, such as `return <Struct as
982    /// Trait>::CONST`. Meanwhile `return > …` treats the `>` as a binary
983    /// operator because it cannot be a starting token for any Rust expression.
984    #[cfg(feature = "parsing")]
985    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
986    pub fn peek(input: ParseStream) -> bool {
987        input.peek(Ident::peek_any) && !input.peek(crate::token::AsToken![as]) // value name or keyword
988            || input.peek(token::Paren) // tuple
989            || input.peek(token::Bracket) // array
990            || input.peek(token::Brace) // block
991            || input.peek(Lit) // literal
992            || input.peek(crate::token::NotToken![!]) && !input.peek(crate::token::NeToken![!=]) // operator not
993            || input.peek(crate::token::MinusToken![-]) && !input.peek(crate::token::MinusEqToken![-=]) && !input.peek(crate::token::RArrowToken![->]) // unary minus
994            || input.peek(crate::token::StarToken![*]) && !input.peek(crate::token::StarEqToken![*=]) // dereference
995            || input.peek(crate::token::OrToken![|]) && !input.peek(crate::token::OrEqToken![|=]) // closure
996            || input.peek(crate::token::AndToken![&]) && !input.peek(crate::token::AndEqToken![&=]) // reference
997            || input.peek(crate::token::DotDotToken![..]) // range
998            || input.peek(crate::token::LtToken![<]) && !input.peek(crate::token::LeToken![<=]) && !input.peek(crate::token::ShlEqToken![<<=]) // associated path
999            || input.peek(crate::token::PathSepToken![::]) // absolute path
1000            || input.peek(Lifetime) // labeled loop
1001            || input.peek(crate::token::PoundToken![#]) // expression attributes
1002    }
1003
1004    #[cfg(all(feature = "parsing", feature = "full"))]
1005    pub(crate) fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
1006        match self {
1007            Expr::Array(ExprArray { attrs, .. })
1008            | Expr::Assign(ExprAssign { attrs, .. })
1009            | Expr::Async(ExprAsync { attrs, .. })
1010            | Expr::Await(ExprAwait { attrs, .. })
1011            | Expr::Binary(ExprBinary { attrs, .. })
1012            | Expr::Block(ExprBlock { attrs, .. })
1013            | Expr::Break(ExprBreak { attrs, .. })
1014            | Expr::Call(ExprCall { attrs, .. })
1015            | Expr::Cast(ExprCast { attrs, .. })
1016            | Expr::Closure(ExprClosure { attrs, .. })
1017            | Expr::Const(ExprConst { attrs, .. })
1018            | Expr::Continue(ExprContinue { attrs, .. })
1019            | Expr::Field(ExprField { attrs, .. })
1020            | Expr::ForLoop(ExprForLoop { attrs, .. })
1021            | Expr::Group(ExprGroup { attrs, .. })
1022            | Expr::If(ExprIf { attrs, .. })
1023            | Expr::Index(ExprIndex { attrs, .. })
1024            | Expr::Infer(ExprInfer { attrs, .. })
1025            | Expr::Let(ExprLet { attrs, .. })
1026            | Expr::Lit(ExprLit { attrs, .. })
1027            | Expr::Loop(ExprLoop { attrs, .. })
1028            | Expr::Macro(ExprMacro { attrs, .. })
1029            | Expr::Match(ExprMatch { attrs, .. })
1030            | Expr::MethodCall(ExprMethodCall { attrs, .. })
1031            | Expr::Paren(ExprParen { attrs, .. })
1032            | Expr::Path(ExprPath { attrs, .. })
1033            | Expr::Range(ExprRange { attrs, .. })
1034            | Expr::RawAddr(ExprRawAddr { attrs, .. })
1035            | Expr::Reference(ExprReference { attrs, .. })
1036            | Expr::Repeat(ExprRepeat { attrs, .. })
1037            | Expr::Return(ExprReturn { attrs, .. })
1038            | Expr::Struct(ExprStruct { attrs, .. })
1039            | Expr::Try(ExprTry { attrs, .. })
1040            | Expr::TryBlock(ExprTryBlock { attrs, .. })
1041            | Expr::Tuple(ExprTuple { attrs, .. })
1042            | Expr::Unary(ExprUnary { attrs, .. })
1043            | Expr::Unsafe(ExprUnsafe { attrs, .. })
1044            | Expr::While(ExprWhile { attrs, .. })
1045            | Expr::Yield(ExprYield { attrs, .. }) => mem::replace(attrs, new),
1046            Expr::Verbatim(_) => Vec::new(),
1047        }
1048    }
1049}
1050
1051#[doc =
r" A struct or tuple struct field accessed in a struct literal or field"]
#[doc = r" expression."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
pub enum Member {

    #[doc = r" A named field like `self.x`."]
    Named(Ident),

    #[doc = r" An unnamed field like `self.0`."]
    Unnamed(Index),
}ast_enum! {
1052    /// A struct or tuple struct field accessed in a struct literal or field
1053    /// expression.
1054    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
1055    pub enum Member {
1056        /// A named field like `self.x`.
1057        Named(Ident),
1058        /// An unnamed field like `self.0`.
1059        Unnamed(Index),
1060    }
1061}
1062
1063impl From<Ident> for Member {
1064    fn from(ident: Ident) -> Member {
1065        Member::Named(ident)
1066    }
1067}
1068
1069impl From<Index> for Member {
1070    fn from(index: Index) -> Member {
1071        Member::Unnamed(index)
1072    }
1073}
1074
1075impl From<usize> for Member {
1076    fn from(index: usize) -> Member {
1077        Member::Unnamed(Index::from(index))
1078    }
1079}
1080
1081impl Eq for Member {}
1082
1083impl PartialEq for Member {
1084    fn eq(&self, other: &Self) -> bool {
1085        match (self, other) {
1086            (Member::Named(this), Member::Named(other)) => this == other,
1087            (Member::Unnamed(this), Member::Unnamed(other)) => this == other,
1088            _ => false,
1089        }
1090    }
1091}
1092
1093impl Hash for Member {
1094    fn hash<H: Hasher>(&self, state: &mut H) {
1095        match self {
1096            Member::Named(m) => m.hash(state),
1097            Member::Unnamed(m) => m.hash(state),
1098        }
1099    }
1100}
1101
1102#[cfg(feature = "printing")]
1103impl IdentFragment for Member {
1104    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1105        match self {
1106            Member::Named(m) => Display::fmt(m, formatter),
1107            Member::Unnamed(m) => Display::fmt(&m.index, formatter),
1108        }
1109    }
1110
1111    fn span(&self) -> Option<Span> {
1112        match self {
1113            Member::Named(m) => Some(m.span()),
1114            Member::Unnamed(m) => Some(m.span),
1115        }
1116    }
1117}
1118
1119#[cfg(any(feature = "parsing", feature = "printing"))]
1120impl Member {
1121    pub(crate) fn is_named(&self) -> bool {
1122        match self {
1123            Member::Named(_) => true,
1124            Member::Unnamed(_) => false,
1125        }
1126    }
1127}
1128
1129#[doc = r" The index of an unnamed tuple struct field."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
pub struct Index {
    pub index: u32,
    pub span: Span,
}ast_struct! {
1130    /// The index of an unnamed tuple struct field.
1131    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
1132    pub struct Index {
1133        pub index: u32,
1134        pub span: Span,
1135    }
1136}
1137
1138impl From<usize> for Index {
1139    fn from(index: usize) -> Index {
1140        if !(index < u32::MAX as usize) {
    ::core::panicking::panic("assertion failed: index < u32::MAX as usize")
};assert!(index < u32::MAX as usize);
1141        Index {
1142            index: index as u32,
1143            span: Span::call_site(),
1144        }
1145    }
1146}
1147
1148impl Eq for Index {}
1149
1150impl PartialEq for Index {
1151    fn eq(&self, other: &Self) -> bool {
1152        self.index == other.index
1153    }
1154}
1155
1156impl Hash for Index {
1157    fn hash<H: Hasher>(&self, state: &mut H) {
1158        self.index.hash(state);
1159    }
1160}
1161
1162#[cfg(feature = "printing")]
1163impl IdentFragment for Index {
1164    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1165        Display::fmt(&self.index, formatter)
1166    }
1167
1168    fn span(&self) -> Option<Span> {
1169        Some(self.span)
1170    }
1171}
1172
1173#[doc = r" A field-value pair in a struct literal."]
#[doc(cfg(any(feature = "full", feature = "derive")))]
pub struct FieldValue {
    pub attrs: Vec<Attribute>,
    pub member: Member,
    #[doc = r" The colon in `Struct { x: x }`. If written in shorthand like"]
    #[doc = r" `Struct { x }`, there is no colon."]
    pub colon_token: Option<crate::token::Colon>,
    pub expr: Expr,
}ast_struct! {
1174    /// A field-value pair in a struct literal.
1175    #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
1176    pub struct FieldValue {
1177        pub attrs: Vec<Attribute>,
1178        pub member: Member,
1179
1180        /// The colon in `Struct { x: x }`. If written in shorthand like
1181        /// `Struct { x }`, there is no colon.
1182        pub colon_token: Option<Token![:]>,
1183
1184        pub expr: Expr,
1185    }
1186}
1187
1188#[cfg(feature = "full")]
1189#[doc = r" A lifetime labeling a `for`, `while`, or `loop`."]
#[doc(cfg(feature = "full"))]
pub struct Label {
    pub name: Lifetime,
    pub colon_token: crate::token::Colon,
}ast_struct! {
1190    /// A lifetime labeling a `for`, `while`, or `loop`.
1191    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
1192    pub struct Label {
1193        pub name: Lifetime,
1194        pub colon_token: Token![:],
1195    }
1196}
1197
1198#[cfg(feature = "full")]
1199#[doc = r" One arm of a `match` expression: `0..=10 => { return true; }`."]
#[doc = r""]
#[doc = r" As in:"]
#[doc = r""]
#[doc = r" ```"]
#[doc = r" # fn f() -> bool {"]
#[doc = r" #     let n = 0;"]
#[doc = r" match n {"]
#[doc = r"     0..=10 => {"]
#[doc = r"         return true;"]
#[doc = r"     }"]
#[doc = r"     // ..."]
#[doc = r"     # _ => {}"]
#[doc = r" }"]
#[doc = r" #   false"]
#[doc = r" # }"]
#[doc = r" ```"]
#[doc(cfg(feature = "full"))]
pub struct Arm {
    pub attrs: Vec<Attribute>,
    pub pat: Pat,
    pub fat_arrow_token: crate::token::FatArrow,
    pub body: Box<Expr>,
    pub comma: Option<crate::token::Comma>,
}ast_struct! {
1200    /// One arm of a `match` expression: `0..=10 => { return true; }`.
1201    ///
1202    /// As in:
1203    ///
1204    /// ```
1205    /// # fn f() -> bool {
1206    /// #     let n = 0;
1207    /// match n {
1208    ///     0..=10 => {
1209    ///         return true;
1210    ///     }
1211    ///     // ...
1212    ///     # _ => {}
1213    /// }
1214    /// #   false
1215    /// # }
1216    /// ```
1217    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
1218    pub struct Arm {
1219        pub attrs: Vec<Attribute>,
1220        pub pat: Pat,
1221        pub fat_arrow_token: Token![=>],
1222        pub body: Box<Expr>,
1223        pub comma: Option<Token![,]>,
1224    }
1225}
1226
1227#[cfg(feature = "full")]
1228#[doc = r" Additional optional information about a block."]
#[doc = r""]
#[doc = r" This data structure may grow to accommodate future Rust language"]
#[doc = r" changes, including the following in-progress RFCs:"]
#[doc = r""]
#[doc =
r#" - [RFC 3680] "Simplify lightweight clones" (`async use { ... }`)"#]
#[doc =
r#" - [#149488] "Heterogeneous try blocks" (`try bikeshed Option<_> { ... }`)"#]
#[doc = r""]
#[doc = r" [RFC 3680]: https://github.com/rust-lang/rust/issues/132290"]
#[doc = r" [#149488]: https://github.com/rust-lang/rust/issues/149488"]
#[non_exhaustive]
pub struct BlockModifiers {}ast_struct! {
1229    /// Additional optional information about a block.
1230    ///
1231    /// This data structure may grow to accommodate future Rust language
1232    /// changes, including the following in-progress RFCs:
1233    ///
1234    /// - [RFC 3680] "Simplify lightweight clones" (`async use { ... }`)
1235    /// - [#149488] "Heterogeneous try blocks" (`try bikeshed Option<_> { ... }`)
1236    ///
1237    /// [RFC 3680]: https://github.com/rust-lang/rust/issues/132290
1238    /// [#149488]: https://github.com/rust-lang/rust/issues/149488
1239    #[non_exhaustive]
1240    pub struct BlockModifiers {}
1241}
1242
1243#[cfg(feature = "full")]
1244impl Default for BlockModifiers {
1245    fn default() -> Self {
1246        BlockModifiers {}
1247    }
1248}
1249
1250#[cfg(feature = "full")]
1251impl BlockModifiers {
1252    #[cfg(feature = "parsing")]
1253    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1254    pub fn require_empty(&self) -> Result<()> {
1255        Ok(())
1256    }
1257}
1258
1259#[cfg(feature = "full")]
1260#[doc = r" Limit types of a range, inclusive or exclusive."]
#[doc(cfg(feature = "full"))]
pub enum RangeLimits {

    #[doc = r" Inclusive at the beginning, exclusive at the end."]
    HalfOpen(crate::token::DotDot),

    #[doc = r" Inclusive at the beginning and end."]
    Closed(crate::token::DotDotEq),
}ast_enum! {
1261    /// Limit types of a range, inclusive or exclusive.
1262    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
1263    pub enum RangeLimits {
1264        /// Inclusive at the beginning, exclusive at the end.
1265        HalfOpen(Token![..]),
1266        /// Inclusive at the beginning and end.
1267        Closed(Token![..=]),
1268    }
1269}
1270
1271#[cfg(feature = "parsing")]
1272pub(crate) mod parsing {
1273    #[cfg(feature = "full")]
1274    use crate::attr;
1275    use crate::attr::Attribute;
1276    #[cfg(feature = "full")]
1277    use crate::buffer::Cursor;
1278    #[cfg(feature = "full")]
1279    use crate::classify;
1280    use crate::error::{Error, Result};
1281    #[cfg(feature = "full")]
1282    use crate::expr::{
1283        Arm, BlockModifiers, ClosureModifiers, ExprArray, ExprAssign, ExprAsync, ExprAwait,
1284        ExprBlock, ExprBreak, ExprClosure, ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer,
1285        ExprLet, ExprLoop, ExprMatch, ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry,
1286        ExprTryBlock, ExprUnsafe, ExprWhile, ExprYield, Label, RangeLimits,
1287    };
1288    use crate::expr::{
1289        Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro,
1290        ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprTuple, ExprUnary,
1291        FieldValue, Index, Member,
1292    };
1293    #[cfg(feature = "full")]
1294    use crate::generics::{self, BoundLifetimes};
1295    use crate::ident::Ident;
1296    use crate::lifetime::Lifetime;
1297    use crate::lit::{Lit, LitFloat, LitInt};
1298    use crate::mac::{self, Macro};
1299    use crate::op::BinOp;
1300    use crate::parse::discouraged::Speculative as _;
1301    use crate::parse::{End, Parse, ParseStream};
1302    #[cfg(feature = "full")]
1303    use crate::pat::{Pat, PatType};
1304    use crate::path::{self, AngleBracketedGenericArguments, Path, QSelf};
1305    use crate::precedence::Precedence;
1306    use crate::punctuated::Punctuated;
1307    #[cfg(feature = "full")]
1308    use crate::stmt::Block;
1309    use crate::token;
1310    use crate::ty;
1311    #[cfg(feature = "full")]
1312    use crate::ty::{PointerMutability, ReturnType, Type};
1313    use crate::verbatim;
1314    use alloc::boxed::Box;
1315    use alloc::format;
1316    use alloc::string::ToString;
1317    use alloc::vec::Vec;
1318    use core::mem;
1319    #[cfg(feature = "full")]
1320    use proc_macro2::{Span, TokenStream};
1321
1322    // When we're parsing expressions which occur before blocks, like in an if
1323    // statement's condition, we cannot parse a struct literal.
1324    //
1325    // Struct literals are ambiguous in certain positions
1326    // https://github.com/rust-lang/rfcs/pull/92
1327    #[cfg(feature = "full")]
1328    pub(super) struct AllowStruct(pub bool);
1329
1330    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1331    impl Parse for Expr {
1332        fn parse(input: ParseStream) -> Result<Self> {
1333            ambiguous_expr(
1334                input,
1335                #[cfg(feature = "full")]
1336                AllowStruct(true),
1337            )
1338        }
1339    }
1340
1341    #[cfg(feature = "full")]
1342    pub(super) fn parse_with_earlier_boundary_rule(input: ParseStream) -> Result<Expr> {
1343        let mut attrs = input.call(expr_attrs)?;
1344        let mut expr = if input.peek(token::Group) && {
1345            let group = crate::group::parse_group(&input.fork())?;
1346            !(group.content.peek(Lifetime) && group.content.peek2(End))
1347        } {
1348            let allow_struct = AllowStruct(true);
1349            let atom = expr_group(input, allow_struct)?;
1350            if continue_parsing_early(&atom) {
1351                trailer_helper(input, atom)?
1352            } else {
1353                atom
1354            }
1355        } else if input.peek(crate::token::IfToken![if]) {
1356            Expr::If(input.parse()?)
1357        } else if input.peek(crate::token::WhileToken![while]) {
1358            Expr::While(input.parse()?)
1359        } else if input.peek(crate::token::ForToken![for])
1360            && !generics::parsing::choose_generics_over_qpath_after_keyword(input)
1361        {
1362            Expr::ForLoop(input.parse()?)
1363        } else if input.peek(crate::token::LoopToken![loop]) {
1364            Expr::Loop(input.parse()?)
1365        } else if input.peek(crate::token::MatchToken![match]) {
1366            Expr::Match(input.parse()?)
1367        } else if input.peek(crate::token::TryToken![try]) && input.peek2(token::Brace) {
1368            Expr::TryBlock(input.parse()?)
1369        } else if input.peek(crate::token::UnsafeToken![unsafe]) {
1370            Expr::Unsafe(input.parse()?)
1371        } else if input.peek(crate::token::ConstToken![const]) && input.peek2(token::Brace) {
1372            Expr::Const(input.parse()?)
1373        } else if input.peek(token::Brace) {
1374            Expr::Block(input.parse()?)
1375        } else if input.peek(Lifetime) {
1376            atom_labeled(input)?
1377        } else {
1378            let allow_struct = AllowStruct(true);
1379            unary_expr(input, allow_struct)?
1380        };
1381
1382        if continue_parsing_early(&expr) {
1383            attrs.extend(expr.replace_attrs(Vec::new()));
1384            expr.replace_attrs(attrs);
1385
1386            let allow_struct = AllowStruct(true);
1387            return parse_expr(input, expr, allow_struct, Precedence::MIN);
1388        }
1389
1390        if input.peek(crate::token::DotToken![.]) && !input.peek(crate::token::DotDotToken![..]) || input.peek(crate::token::QuestionToken![?]) {
1391            expr = trailer_helper(input, expr)?;
1392
1393            attrs.extend(expr.replace_attrs(Vec::new()));
1394            expr.replace_attrs(attrs);
1395
1396            let allow_struct = AllowStruct(true);
1397            return parse_expr(input, expr, allow_struct, Precedence::MIN);
1398        }
1399
1400        attrs.extend(expr.replace_attrs(Vec::new()));
1401        expr.replace_attrs(attrs);
1402        Ok(expr)
1403    }
1404
1405    #[cfg(feature = "full")]
1406    impl Copy for AllowStruct {}
1407
1408    #[cfg(feature = "full")]
1409    impl Clone for AllowStruct {
1410        fn clone(&self) -> Self {
1411            *self
1412        }
1413    }
1414
1415    #[cfg(feature = "full")]
1416    fn parse_expr(
1417        input: ParseStream,
1418        mut lhs: Expr,
1419        allow_struct: AllowStruct,
1420        base: Precedence,
1421    ) -> Result<Expr> {
1422        loop {
1423            let ahead = input.fork();
1424            if let Expr::Range(_) = lhs {
1425                // A range cannot be the left-hand side of another binary operator.
1426                break;
1427            } else if let Ok(op) = ahead.parse::<BinOp>() {
1428                let precedence = Precedence::of_binop(&op);
1429                if precedence < base {
1430                    break;
1431                }
1432                if precedence == Precedence::Assign {
1433                    if let Expr::Range(_) = lhs {
1434                        break;
1435                    }
1436                }
1437                if precedence == Precedence::Compare {
1438                    if let Expr::Binary(lhs) = &lhs {
1439                        if Precedence::of_binop(&lhs.op) == Precedence::Compare {
1440                            return Err(input.error("comparison operators cannot be chained"));
1441                        }
1442                    }
1443                }
1444                input.advance_to(&ahead);
1445                let right = parse_binop_rhs(input, allow_struct, precedence)?;
1446                lhs = Expr::Binary(ExprBinary {
1447                    attrs: Vec::new(),
1448                    left: Box::new(lhs),
1449                    op,
1450                    right,
1451                });
1452            } else if Precedence::Assign >= base
1453                && input.peek(crate::token::EqToken![=])
1454                && !input.peek(crate::token::FatArrowToken![=>])
1455                && match lhs {
1456                    Expr::Range(_) => false,
1457                    _ => true,
1458                }
1459            {
1460                let eq_token: crate::token::EqToken![=] = input.parse()?;
1461                let right = parse_binop_rhs(input, allow_struct, Precedence::Assign)?;
1462                lhs = Expr::Assign(ExprAssign {
1463                    attrs: Vec::new(),
1464                    left: Box::new(lhs),
1465                    eq_token,
1466                    right,
1467                });
1468            } else if Precedence::Range >= base && input.peek(crate::token::DotDotToken![..]) {
1469                let limits: RangeLimits = input.parse()?;
1470                let end = parse_range_end(input, &limits, allow_struct)?;
1471                lhs = Expr::Range(ExprRange {
1472                    attrs: Vec::new(),
1473                    start: Some(Box::new(lhs)),
1474                    limits,
1475                    end,
1476                });
1477            } else if Precedence::Cast >= base && input.peek(crate::token::AsToken![as]) {
1478                let as_token: crate::token::AsToken![as] = input.parse()?;
1479                let allow_plus = false;
1480                let allow_group_generic = false;
1481                let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
1482                check_cast(input)?;
1483                lhs = Expr::Cast(ExprCast {
1484                    attrs: Vec::new(),
1485                    expr: Box::new(lhs),
1486                    as_token,
1487                    ty: Box::new(ty),
1488                });
1489            } else {
1490                break;
1491            }
1492        }
1493        Ok(lhs)
1494    }
1495
1496    #[cfg(not(feature = "full"))]
1497    fn parse_expr(input: ParseStream, mut lhs: Expr, base: Precedence) -> Result<Expr> {
1498        loop {
1499            let ahead = input.fork();
1500            if let Ok(op) = ahead.parse::<BinOp>() {
1501                let precedence = Precedence::of_binop(&op);
1502                if precedence < base {
1503                    break;
1504                }
1505                if precedence == Precedence::Compare {
1506                    if let Expr::Binary(lhs) = &lhs {
1507                        if Precedence::of_binop(&lhs.op) == Precedence::Compare {
1508                            return Err(input.error("comparison operators cannot be chained"));
1509                        }
1510                    }
1511                }
1512                input.advance_to(&ahead);
1513                let right = parse_binop_rhs(input, precedence)?;
1514                lhs = Expr::Binary(ExprBinary {
1515                    attrs: Vec::new(),
1516                    left: Box::new(lhs),
1517                    op,
1518                    right,
1519                });
1520            } else if Precedence::Cast >= base && input.peek(Token![as]) {
1521                let as_token: Token![as] = input.parse()?;
1522                let allow_plus = false;
1523                let allow_group_generic = false;
1524                let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
1525                check_cast(input)?;
1526                lhs = Expr::Cast(ExprCast {
1527                    attrs: Vec::new(),
1528                    expr: Box::new(lhs),
1529                    as_token,
1530                    ty: Box::new(ty),
1531                });
1532            } else {
1533                break;
1534            }
1535        }
1536        Ok(lhs)
1537    }
1538
1539    fn parse_binop_rhs(
1540        input: ParseStream,
1541        #[cfg(feature = "full")] allow_struct: AllowStruct,
1542        precedence: Precedence,
1543    ) -> Result<Box<Expr>> {
1544        let mut rhs = unary_expr(
1545            input,
1546            #[cfg(feature = "full")]
1547            allow_struct,
1548        )?;
1549        loop {
1550            let next = peek_precedence(input);
1551            if next > precedence || next == precedence && precedence == Precedence::Assign {
1552                let cursor = input.cursor();
1553                rhs = parse_expr(
1554                    input,
1555                    rhs,
1556                    #[cfg(feature = "full")]
1557                    allow_struct,
1558                    next,
1559                )?;
1560                if cursor == input.cursor() {
1561                    // Bespoke grammar restrictions separate from precedence can
1562                    // cause parsing to not advance, such as `..a` being
1563                    // disallowed in the left-hand side of binary operators,
1564                    // even ones that have lower precedence than `..`.
1565                    break;
1566                }
1567            } else {
1568                break;
1569            }
1570        }
1571        Ok(Box::new(rhs))
1572    }
1573
1574    fn peek_precedence(input: ParseStream) -> Precedence {
1575        if let Ok(op) = input.fork().parse() {
1576            Precedence::of_binop(&op)
1577        } else if input.peek(crate::token::EqToken![=]) && !input.peek(crate::token::FatArrowToken![=>]) {
1578            Precedence::Assign
1579        } else if input.peek(crate::token::DotDotToken![..]) {
1580            Precedence::Range
1581        } else if input.peek(crate::token::AsToken![as]) {
1582            Precedence::Cast
1583        } else {
1584            Precedence::MIN
1585        }
1586    }
1587
1588    // Parse an arbitrary expression.
1589    pub(super) fn ambiguous_expr(
1590        input: ParseStream,
1591        #[cfg(feature = "full")] allow_struct: AllowStruct,
1592    ) -> Result<Expr> {
1593        let lhs = unary_expr(
1594            input,
1595            #[cfg(feature = "full")]
1596            allow_struct,
1597        )?;
1598        parse_expr(
1599            input,
1600            lhs,
1601            #[cfg(feature = "full")]
1602            allow_struct,
1603            Precedence::MIN,
1604        )
1605    }
1606
1607    #[cfg(feature = "full")]
1608    fn expr_attrs(input: ParseStream) -> Result<Vec<Attribute>> {
1609        let mut attrs = Vec::new();
1610        while !input.peek(token::Group) && input.peek(crate::token::PoundToken![#]) {
1611            attrs.push(input.call(attr::parsing::single_parse_outer)?);
1612        }
1613        Ok(attrs)
1614    }
1615
1616    // <UnOp> <trailer>
1617    // & <trailer>
1618    // &mut <trailer>
1619    // box <trailer>
1620    #[cfg(feature = "full")]
1621    fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1622        let begin = input.cursor();
1623        let attrs = input.call(expr_attrs)?;
1624        if input.peek(token::Group) {
1625            return trailer_expr(begin, attrs, input, allow_struct);
1626        }
1627
1628        if input.peek(crate::token::AndToken![&]) {
1629            let and_token: crate::token::AndToken![&] = input.parse()?;
1630            let raw: Option<crate::token::RawToken![raw]> = if input.peek(crate::token::RawToken![raw])
1631                && (input.peek2(crate::token::MutToken![mut]) || input.peek2(crate::token::ConstToken![const]))
1632            {
1633                Some(input.parse()?)
1634            } else {
1635                None
1636            };
1637            let mutability: Option<crate::token::MutToken![mut]> = input.parse()?;
1638            let const_token: Option<crate::token::ConstToken![const]> = if raw.is_some() && mutability.is_none() {
1639                Some(input.parse()?)
1640            } else {
1641                None
1642            };
1643            let expr = Box::new(unary_expr(input, allow_struct)?);
1644            if let Some(raw) = raw {
1645                Ok(Expr::RawAddr(ExprRawAddr {
1646                    attrs,
1647                    and_token,
1648                    raw,
1649                    mutability: match mutability {
1650                        Some(mut_token) => PointerMutability::Mut(mut_token),
1651                        None => PointerMutability::Const(const_token.unwrap()),
1652                    },
1653                    expr,
1654                }))
1655            } else {
1656                Ok(Expr::Reference(ExprReference {
1657                    attrs,
1658                    and_token,
1659                    mutability,
1660                    expr,
1661                }))
1662            }
1663        } else if input.peek(crate::token::StarToken![*]) || input.peek(crate::token::NotToken![!]) || input.peek(crate::token::MinusToken![-]) {
1664            expr_unary(input, attrs, allow_struct).map(Expr::Unary)
1665        } else {
1666            trailer_expr(begin, attrs, input, allow_struct)
1667        }
1668    }
1669
1670    #[cfg(not(feature = "full"))]
1671    fn unary_expr(input: ParseStream) -> Result<Expr> {
1672        if input.peek(Token![&]) {
1673            Ok(Expr::Reference(ExprReference {
1674                attrs: Vec::new(),
1675                and_token: input.parse()?,
1676                mutability: input.parse()?,
1677                expr: Box::new(unary_expr(input)?),
1678            }))
1679        } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
1680            Ok(Expr::Unary(ExprUnary {
1681                attrs: Vec::new(),
1682                op: input.parse()?,
1683                expr: Box::new(unary_expr(input)?),
1684            }))
1685        } else {
1686            trailer_expr(input)
1687        }
1688    }
1689
1690    // <atom> (..<args>) ...
1691    // <atom> . <ident> (..<args>) ...
1692    // <atom> . <ident> ...
1693    // <atom> . <lit> ...
1694    // <atom> [ <expr> ] ...
1695    // <atom> ? ...
1696    #[cfg(feature = "full")]
1697    fn trailer_expr(
1698        begin: Cursor,
1699        mut attrs: Vec<Attribute>,
1700        input: ParseStream,
1701        allow_struct: AllowStruct,
1702    ) -> Result<Expr> {
1703        let atom = atom_expr(input, allow_struct)?;
1704        let mut e = trailer_helper(input, atom)?;
1705
1706        if let Expr::Verbatim(tokens) = &mut e {
1707            *tokens = verbatim::between(begin, input.cursor());
1708        } else if !attrs.is_empty() {
1709            if let Expr::Range(range) = e {
1710                let spans: &[Span] = match &range.limits {
1711                    RangeLimits::HalfOpen(limits) => &limits.spans,
1712                    RangeLimits::Closed(limits) => &limits.spans,
1713                };
1714                return Err(crate::error::new2(
1715                    spans[0],
1716                    *spans.last().unwrap(),
1717                    "attributes are not allowed on range expressions starting with `..`",
1718                ));
1719            }
1720            let inner_attrs = e.replace_attrs(Vec::new());
1721            attrs.extend(inner_attrs);
1722            e.replace_attrs(attrs);
1723        }
1724
1725        Ok(e)
1726    }
1727
1728    #[cfg(feature = "full")]
1729    fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
1730        loop {
1731            if input.peek(token::Paren) {
1732                let content;
1733                e = Expr::Call(ExprCall {
1734                    attrs: Vec::new(),
1735                    func: Box::new(e),
1736                    paren_token: match crate::__private::parse_parens(&input) {
    crate::__private::Ok(parens) => {
        content = parens.content;
        _ = content;
        parens.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
}parenthesized!(content in input),
1737                    args: content.parse_terminated(Expr::parse, crate::token::CommaToken![,])?,
1738                });
1739            } else if input.peek(crate::token::DotToken![.])
1740                && !input.peek(crate::token::DotDotToken![..])
1741                && match e {
1742                    Expr::Range(_) => false,
1743                    _ => true,
1744                }
1745            {
1746                let mut dot_token: crate::token::DotToken![.] = input.parse()?;
1747
1748                let float_token: Option<LitFloat> = input.parse()?;
1749                if let Some(float_token) = float_token {
1750                    if multi_index(&mut e, &mut dot_token, float_token)? {
1751                        continue;
1752                    }
1753                }
1754
1755                let await_token: Option<crate::token::AwaitToken![await]> = input.parse()?;
1756                if let Some(await_token) = await_token {
1757                    e = Expr::Await(ExprAwait {
1758                        attrs: Vec::new(),
1759                        base: Box::new(e),
1760                        dot_token,
1761                        await_token,
1762                    });
1763                    continue;
1764                }
1765
1766                let member: Member = input.parse()?;
1767                let turbofish = if member.is_named() && input.peek(crate::token::PathSepToken![::]) {
1768                    Some(AngleBracketedGenericArguments::parse_turbofish(input)?)
1769                } else {
1770                    None
1771                };
1772
1773                if turbofish.is_some() || input.peek(token::Paren) {
1774                    if let Member::Named(method) = member {
1775                        let content;
1776                        e = Expr::MethodCall(ExprMethodCall {
1777                            attrs: Vec::new(),
1778                            receiver: Box::new(e),
1779                            dot_token,
1780                            method,
1781                            turbofish,
1782                            paren_token: match crate::__private::parse_parens(&input) {
    crate::__private::Ok(parens) => {
        content = parens.content;
        _ = content;
        parens.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
}parenthesized!(content in input),
1783                            args: content.parse_terminated(Expr::parse, crate::token::CommaToken![,])?,
1784                        });
1785                        continue;
1786                    }
1787                }
1788
1789                e = Expr::Field(ExprField {
1790                    attrs: Vec::new(),
1791                    base: Box::new(e),
1792                    dot_token,
1793                    member,
1794                });
1795            } else if input.peek(token::Bracket) {
1796                let content;
1797                e = Expr::Index(ExprIndex {
1798                    attrs: Vec::new(),
1799                    expr: Box::new(e),
1800                    bracket_token: match crate::__private::parse_brackets(&input) {
    crate::__private::Ok(brackets) => {
        content = brackets.content;
        _ = content;
        brackets.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
}bracketed!(content in input),
1801                    index: content.parse()?,
1802                });
1803            } else if input.peek(crate::token::QuestionToken![?])
1804                && match e {
1805                    Expr::Range(_) => false,
1806                    _ => true,
1807                }
1808            {
1809                e = Expr::Try(ExprTry {
1810                    attrs: Vec::new(),
1811                    expr: Box::new(e),
1812                    question_token: input.parse()?,
1813                });
1814            } else {
1815                break;
1816            }
1817        }
1818        Ok(e)
1819    }
1820
1821    #[cfg(not(feature = "full"))]
1822    fn trailer_expr(input: ParseStream) -> Result<Expr> {
1823        let mut e = atom_expr(input)?;
1824
1825        loop {
1826            if input.peek(token::Paren) {
1827                let content;
1828                e = Expr::Call(ExprCall {
1829                    attrs: Vec::new(),
1830                    func: Box::new(e),
1831                    paren_token: parenthesized!(content in input),
1832                    args: content.parse_terminated(Expr::parse, Token![,])?,
1833                });
1834            } else if input.peek(Token![.])
1835                && !input.peek(Token![..])
1836                && !input.peek2(Token![await])
1837            {
1838                let mut dot_token: Token![.] = input.parse()?;
1839
1840                let float_token: Option<LitFloat> = input.parse()?;
1841                if let Some(float_token) = float_token {
1842                    if multi_index(&mut e, &mut dot_token, float_token)? {
1843                        continue;
1844                    }
1845                }
1846
1847                let member: Member = input.parse()?;
1848                let turbofish = if member.is_named() && input.peek(Token![::]) {
1849                    let colon2_token: Token![::] = input.parse()?;
1850                    let turbofish =
1851                        AngleBracketedGenericArguments::do_parse(Some(colon2_token), input)?;
1852                    Some(turbofish)
1853                } else {
1854                    None
1855                };
1856
1857                if turbofish.is_some() || input.peek(token::Paren) {
1858                    if let Member::Named(method) = member {
1859                        let content;
1860                        e = Expr::MethodCall(ExprMethodCall {
1861                            attrs: Vec::new(),
1862                            receiver: Box::new(e),
1863                            dot_token,
1864                            method,
1865                            turbofish,
1866                            paren_token: parenthesized!(content in input),
1867                            args: content.parse_terminated(Expr::parse, Token![,])?,
1868                        });
1869                        continue;
1870                    }
1871                }
1872
1873                e = Expr::Field(ExprField {
1874                    attrs: Vec::new(),
1875                    base: Box::new(e),
1876                    dot_token,
1877                    member,
1878                });
1879            } else if input.peek(token::Bracket) {
1880                let content;
1881                e = Expr::Index(ExprIndex {
1882                    attrs: Vec::new(),
1883                    expr: Box::new(e),
1884                    bracket_token: bracketed!(content in input),
1885                    index: content.parse()?,
1886                });
1887            } else {
1888                break;
1889            }
1890        }
1891
1892        Ok(e)
1893    }
1894
1895    // Parse all atomic expressions which don't have to worry about precedence
1896    // interactions, as they are fully contained.
1897    #[cfg(feature = "full")]
1898    fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1899        if input.peek(token::Group) && {
1900            let group = crate::group::parse_group(&input.fork())?;
1901            !(group.content.peek(Lifetime) && group.content.peek2(End))
1902        } {
1903            expr_group(input, allow_struct)
1904        } else if input.peek(Lit) {
1905            input.parse().map(Expr::Lit)
1906        } else if input.peek(crate::token::AsyncToken![async])
1907            && (input.peek2(token::Brace) || input.peek2(crate::token::MoveToken![move]) && input.peek3(token::Brace))
1908        {
1909            input.parse().map(Expr::Async)
1910        } else if input.peek(crate::token::TryToken![try]) && input.peek2(token::Brace) {
1911            input.parse().map(Expr::TryBlock)
1912        } else if input.peek(crate::token::OrToken![|])
1913            || input.peek(crate::token::MoveToken![move])
1914            || input.peek(crate::token::ForToken![for])
1915                && generics::parsing::choose_generics_over_qpath_after_keyword(input)
1916            || input.peek(crate::token::ConstToken![const]) && !input.peek2(token::Brace)
1917            || input.peek(crate::token::StaticToken![static])
1918            || input.peek(crate::token::AsyncToken![async]) && (input.peek2(crate::token::OrToken![|]) || input.peek2(crate::token::MoveToken![move]))
1919        {
1920            expr_closure(input, allow_struct).map(Expr::Closure)
1921        } else if input.cursor().peek_keyword("builtin") && input.peek2(crate::token::PoundToken![#]) {
1922            expr_builtin(input)
1923        } else if input.peek(Ident)
1924            || input.peek(crate::token::PathSepToken![::])
1925            || input.peek(crate::token::LtToken![<])
1926            || input.peek(crate::token::SelfValueToken![self])
1927            || input.peek(crate::token::SelfTypeToken![Self])
1928            || input.peek(crate::token::SuperToken![super])
1929            || input.peek(crate::token::CrateToken![crate])
1930            || input.peek(crate::token::TryToken![try]) && (input.peek2(crate::token::NotToken![!]) || input.peek2(crate::token::PathSepToken![::]))
1931        {
1932            path_or_macro_or_struct(input, allow_struct)
1933        } else if input.peek(token::Paren) {
1934            paren_or_tuple(input)
1935        } else if input.peek(crate::token::BreakToken![break]) {
1936            expr_break(input, allow_struct).map(Expr::Break)
1937        } else if input.peek(crate::token::ContinueToken![continue]) {
1938            input.parse().map(Expr::Continue)
1939        } else if input.peek(crate::token::ReturnToken![return]) {
1940            input.parse().map(Expr::Return)
1941        } else if input.peek(crate::token::BecomeToken![become]) {
1942            expr_become(input)
1943        } else if input.peek(token::Bracket) {
1944            array_or_repeat(input)
1945        } else if input.peek(crate::token::LetToken![let]) {
1946            expr_let(input, allow_struct).map(Expr::Let)
1947        } else if input.peek(crate::token::IfToken![if]) {
1948            input.parse().map(Expr::If)
1949        } else if input.peek(crate::token::WhileToken![while]) {
1950            input.parse().map(Expr::While)
1951        } else if input.peek(crate::token::ForToken![for]) {
1952            input.parse().map(Expr::ForLoop)
1953        } else if input.peek(crate::token::LoopToken![loop]) {
1954            input.parse().map(Expr::Loop)
1955        } else if input.peek(crate::token::MatchToken![match]) {
1956            input.parse().map(Expr::Match)
1957        } else if input.peek(crate::token::YieldToken![yield]) {
1958            input.parse().map(Expr::Yield)
1959        } else if input.peek(crate::token::UnsafeToken![unsafe]) {
1960            input.parse().map(Expr::Unsafe)
1961        } else if input.peek(crate::token::ConstToken![const]) {
1962            input.parse().map(Expr::Const)
1963        } else if input.peek(token::Brace) {
1964            input.parse().map(Expr::Block)
1965        } else if input.peek(crate::token::DotDotToken![..]) {
1966            expr_range(input, allow_struct).map(Expr::Range)
1967        } else if input.peek(crate::token::UnderscoreToken![_]) {
1968            input.parse().map(Expr::Infer)
1969        } else if input.peek(Lifetime) {
1970            atom_labeled(input)
1971        } else {
1972            Err(input.error("expected an expression"))
1973        }
1974    }
1975
1976    #[cfg(feature = "full")]
1977    fn atom_labeled(input: ParseStream) -> Result<Expr> {
1978        let the_label: Label = input.parse()?;
1979        let mut expr = if input.peek(crate::token::WhileToken![while]) {
1980            Expr::While(input.parse()?)
1981        } else if input.peek(crate::token::ForToken![for]) {
1982            Expr::ForLoop(input.parse()?)
1983        } else if input.peek(crate::token::LoopToken![loop]) {
1984            Expr::Loop(input.parse()?)
1985        } else if input.peek(token::Brace) {
1986            Expr::Block(input.parse()?)
1987        } else {
1988            return Err(input.error("expected loop or block expression"));
1989        };
1990        match &mut expr {
1991            Expr::While(ExprWhile { label, .. })
1992            | Expr::ForLoop(ExprForLoop { label, .. })
1993            | Expr::Loop(ExprLoop { label, .. })
1994            | Expr::Block(ExprBlock { label, .. }) => *label = Some(the_label),
1995            _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
1996        }
1997        Ok(expr)
1998    }
1999
2000    #[cfg(not(feature = "full"))]
2001    fn atom_expr(input: ParseStream) -> Result<Expr> {
2002        if input.peek(token::Group) && {
2003            let group = crate::group::parse_group(&input.fork())?;
2004            !(group.content.peek(Lifetime) && group.content.peek2(End))
2005        } {
2006            expr_group(input)
2007        } else if input.peek(Lit) {
2008            input.parse().map(Expr::Lit)
2009        } else if input.peek(token::Paren) {
2010            paren_or_tuple(input)
2011        } else if input.peek(Ident)
2012            || input.peek(Token![::])
2013            || input.peek(Token![<])
2014            || input.peek(Token![self])
2015            || input.peek(Token![Self])
2016            || input.peek(Token![super])
2017            || input.peek(Token![crate])
2018        {
2019            path_or_macro_or_struct(input)
2020        } else if input.is_empty() {
2021            Err(input.error("expected an expression"))
2022        } else {
2023            if input.peek(token::Brace) {
2024                let scan = input.fork();
2025                let content;
2026                braced!(content in scan);
2027                if content.parse::<Expr>().is_ok() && content.is_empty() {
2028                    let expr_block = verbatim::between(input.cursor(), scan.cursor());
2029                    input.advance_to(&scan);
2030                    return Ok(Expr::Verbatim(expr_block));
2031                }
2032            }
2033            Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
2034        }
2035    }
2036
2037    #[cfg(feature = "full")]
2038    fn expr_builtin(input: ParseStream) -> Result<Expr> {
2039        let begin = input.cursor();
2040
2041        token::parsing::keyword(input, "builtin")?;
2042        input.parse::<crate::token::PoundToken![#]>()?;
2043        input.parse::<Ident>()?;
2044
2045        let args;
2046        match crate::__private::parse_parens(&input) {
    crate::__private::Ok(parens) => {
        args = parens.content;
        _ = args;
        parens.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
};parenthesized!(args in input);
2047        args.parse::<TokenStream>()?;
2048
2049        Ok(Expr::Verbatim(verbatim::between(begin, input.cursor())))
2050    }
2051
2052    fn path_or_macro_or_struct(
2053        input: ParseStream,
2054        #[cfg(feature = "full")] allow_struct: AllowStruct,
2055    ) -> Result<Expr> {
2056        let expr_style = true;
2057        let (qself, path) = path::parsing::qpath(input, expr_style)?;
2058        rest_of_path_or_macro_or_struct(
2059            qself,
2060            path,
2061            input,
2062            #[cfg(feature = "full")]
2063            allow_struct,
2064        )
2065    }
2066
2067    fn rest_of_path_or_macro_or_struct(
2068        qself: Option<QSelf>,
2069        path: Path,
2070        input: ParseStream,
2071        #[cfg(feature = "full")] allow_struct: AllowStruct,
2072    ) -> Result<Expr> {
2073        if qself.is_none()
2074            && input.peek(crate::token::NotToken![!])
2075            && !input.peek(crate::token::NeToken![!=])
2076            && path.is_mod_style()
2077        {
2078            let bang_token: crate::token::NotToken![!] = input.parse()?;
2079            let (delimiter, tokens) = mac::parse_delimiter(input)?;
2080            return Ok(Expr::Macro(ExprMacro {
2081                attrs: Vec::new(),
2082                mac: Macro {
2083                    path,
2084                    bang_token,
2085                    delimiter,
2086                    tokens,
2087                },
2088            }));
2089        }
2090
2091        #[cfg(not(feature = "full"))]
2092        let allow_struct = (true,);
2093        if allow_struct.0 && input.peek(token::Brace) {
2094            return expr_struct_helper(input, qself, path).map(Expr::Struct);
2095        }
2096
2097        Ok(Expr::Path(ExprPath {
2098            attrs: Vec::new(),
2099            qself,
2100            path,
2101        }))
2102    }
2103
2104    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2105    impl Parse for ExprMacro {
2106        fn parse(input: ParseStream) -> Result<Self> {
2107            Ok(ExprMacro {
2108                attrs: Vec::new(),
2109                mac: input.parse()?,
2110            })
2111        }
2112    }
2113
2114    fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
2115        let content;
2116        let paren_token = match crate::__private::parse_parens(&input) {
    crate::__private::Ok(parens) => {
        content = parens.content;
        _ = content;
        parens.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
}parenthesized!(content in input);
2117        if content.is_empty() {
2118            return Ok(Expr::Tuple(ExprTuple {
2119                attrs: Vec::new(),
2120                paren_token,
2121                elems: Punctuated::new(),
2122            }));
2123        }
2124
2125        let first: Expr = content.parse()?;
2126        if content.is_empty() {
2127            return Ok(Expr::Paren(ExprParen {
2128                attrs: Vec::new(),
2129                paren_token,
2130                expr: Box::new(first),
2131            }));
2132        }
2133
2134        let mut elems = Punctuated::new();
2135        elems.push_value(first);
2136        while !content.is_empty() {
2137            let punct = content.parse()?;
2138            elems.push_punct(punct);
2139            if content.is_empty() {
2140                break;
2141            }
2142            let value = content.parse()?;
2143            elems.push_value(value);
2144        }
2145        Ok(Expr::Tuple(ExprTuple {
2146            attrs: Vec::new(),
2147            paren_token,
2148            elems,
2149        }))
2150    }
2151
2152    #[cfg(feature = "full")]
2153    fn array_or_repeat(input: ParseStream) -> Result<Expr> {
2154        let content;
2155        let bracket_token = match crate::__private::parse_brackets(&input) {
    crate::__private::Ok(brackets) => {
        content = brackets.content;
        _ = content;
        brackets.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
}bracketed!(content in input);
2156        if content.is_empty() {
2157            return Ok(Expr::Array(ExprArray {
2158                attrs: Vec::new(),
2159                bracket_token,
2160                elems: Punctuated::new(),
2161            }));
2162        }
2163
2164        let first: Expr = content.parse()?;
2165        if content.is_empty() || content.peek(crate::token::CommaToken![,]) {
2166            let mut elems = Punctuated::new();
2167            elems.push_value(first);
2168            while !content.is_empty() {
2169                let punct = content.parse()?;
2170                elems.push_punct(punct);
2171                if content.is_empty() {
2172                    break;
2173                }
2174                let value = content.parse()?;
2175                elems.push_value(value);
2176            }
2177            Ok(Expr::Array(ExprArray {
2178                attrs: Vec::new(),
2179                bracket_token,
2180                elems,
2181            }))
2182        } else if content.peek(crate::token::SemiToken![;]) {
2183            let semi_token: crate::token::SemiToken![;] = content.parse()?;
2184            let len: Expr = content.parse()?;
2185            Ok(Expr::Repeat(ExprRepeat {
2186                attrs: Vec::new(),
2187                bracket_token,
2188                expr: Box::new(first),
2189                semi_token,
2190                len: Box::new(len),
2191            }))
2192        } else {
2193            Err(content.error("expected `,` or `;`"))
2194        }
2195    }
2196
2197    #[cfg(feature = "full")]
2198    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2199    impl Parse for ExprArray {
2200        fn parse(input: ParseStream) -> Result<Self> {
2201            let content;
2202            let bracket_token = match crate::__private::parse_brackets(&input) {
    crate::__private::Ok(brackets) => {
        content = brackets.content;
        _ = content;
        brackets.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
}bracketed!(content in input);
2203            let mut elems = Punctuated::new();
2204
2205            while !content.is_empty() {
2206                let first: Expr = content.parse()?;
2207                elems.push_value(first);
2208                if content.is_empty() {
2209                    break;
2210                }
2211                let punct = content.parse()?;
2212                elems.push_punct(punct);
2213            }
2214
2215            Ok(ExprArray {
2216                attrs: Vec::new(),
2217                bracket_token,
2218                elems,
2219            })
2220        }
2221    }
2222
2223    #[cfg(feature = "full")]
2224    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2225    impl Parse for ExprRepeat {
2226        fn parse(input: ParseStream) -> Result<Self> {
2227            let content;
2228            Ok(ExprRepeat {
2229                bracket_token: match crate::__private::parse_brackets(&input) {
    crate::__private::Ok(brackets) => {
        content = brackets.content;
        _ = content;
        brackets.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
}bracketed!(content in input),
2230                attrs: Vec::new(),
2231                expr: content.parse()?,
2232                semi_token: content.parse()?,
2233                len: content.parse()?,
2234            })
2235        }
2236    }
2237
2238    #[cfg(feature = "full")]
2239    fn continue_parsing_early(mut expr: &Expr) -> bool {
2240        while let Expr::Group(group) = expr {
2241            expr = &group.expr;
2242        }
2243        match expr {
2244            Expr::If(_)
2245            | Expr::While(_)
2246            | Expr::ForLoop(_)
2247            | Expr::Loop(_)
2248            | Expr::Match(_)
2249            | Expr::TryBlock(_)
2250            | Expr::Unsafe(_)
2251            | Expr::Const(_)
2252            | Expr::Block(_) => false,
2253            _ => true,
2254        }
2255    }
2256
2257    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2258    impl Parse for ExprLit {
2259        fn parse(input: ParseStream) -> Result<Self> {
2260            Ok(ExprLit {
2261                attrs: Vec::new(),
2262                lit: input.parse()?,
2263            })
2264        }
2265    }
2266
2267    fn expr_group(
2268        input: ParseStream,
2269        #[cfg(feature = "full")] allow_struct: AllowStruct,
2270    ) -> Result<Expr> {
2271        let group = crate::group::parse_group(input)?;
2272        let mut inner: Expr = group.content.parse()?;
2273
2274        match inner {
2275            Expr::Path(mut expr) if expr.attrs.is_empty() => {
2276                let grouped_len = expr.path.segments.len();
2277                Path::parse_rest(input, &mut expr.path, true)?;
2278                match rest_of_path_or_macro_or_struct(
2279                    expr.qself,
2280                    expr.path,
2281                    input,
2282                    #[cfg(feature = "full")]
2283                    allow_struct,
2284                )? {
2285                    Expr::Path(expr) if expr.path.segments.len() == grouped_len => {
2286                        inner = Expr::Path(expr);
2287                    }
2288                    extended => return Ok(extended),
2289                }
2290            }
2291            _ => {}
2292        }
2293
2294        Ok(Expr::Group(ExprGroup {
2295            attrs: Vec::new(),
2296            group_token: group.token,
2297            expr: Box::new(inner),
2298        }))
2299    }
2300
2301    #[cfg(feature = "full")]
2302    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2303    impl Parse for ExprParen {
2304        fn parse(input: ParseStream) -> Result<Self> {
2305            let content;
2306            Ok(ExprParen {
2307                attrs: Vec::new(),
2308                paren_token: match crate::__private::parse_parens(&input) {
    crate::__private::Ok(parens) => {
        content = parens.content;
        _ = content;
        parens.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
}parenthesized!(content in input),
2309                expr: content.parse()?,
2310            })
2311        }
2312    }
2313
2314    #[cfg(feature = "full")]
2315    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2316    impl Parse for ExprLet {
2317        fn parse(input: ParseStream) -> Result<Self> {
2318            let allow_struct = AllowStruct(true);
2319            expr_let(input, allow_struct)
2320        }
2321    }
2322
2323    #[cfg(feature = "full")]
2324    fn expr_let(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprLet> {
2325        Ok(ExprLet {
2326            attrs: Vec::new(),
2327            let_token: input.parse()?,
2328            pat: Box::new(Pat::parse_multi_with_leading_vert(input)?),
2329            eq_token: input.parse()?,
2330            expr: Box::new({
2331                let lhs = unary_expr(input, allow_struct)?;
2332                parse_expr(input, lhs, allow_struct, Precedence::Compare)?
2333            }),
2334        })
2335    }
2336
2337    #[cfg(feature = "full")]
2338    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2339    impl Parse for ExprIf {
2340        fn parse(input: ParseStream) -> Result<Self> {
2341            let attrs = input.call(Attribute::parse_outer)?;
2342
2343            let mut clauses = Vec::new();
2344            let mut expr;
2345            loop {
2346                let if_token: crate::token::IfToken![if] = input.parse()?;
2347                let cond = input.call(Expr::parse_without_eager_brace)?;
2348                let then_branch: Block = input.parse()?;
2349
2350                expr = ExprIf {
2351                    attrs: Vec::new(),
2352                    if_token,
2353                    cond: Box::new(cond),
2354                    then_branch,
2355                    else_branch: None,
2356                };
2357
2358                if !input.peek(crate::token::ElseToken![else]) {
2359                    break;
2360                }
2361
2362                let else_token: crate::token::ElseToken![else] = input.parse()?;
2363                let lookahead = input.lookahead1();
2364                if lookahead.peek(crate::token::IfToken![if]) {
2365                    expr.else_branch = Some((else_token, Box::new(Expr::PLACEHOLDER)));
2366                    clauses.push(expr);
2367                } else if lookahead.peek(token::Brace) {
2368                    expr.else_branch = Some((
2369                        else_token,
2370                        Box::new(Expr::Block(ExprBlock {
2371                            attrs: Vec::new(),
2372                            label: None,
2373                            block: input.parse()?,
2374                        })),
2375                    ));
2376                    break;
2377                } else {
2378                    return Err(lookahead.error());
2379                }
2380            }
2381
2382            while let Some(mut prev) = clauses.pop() {
2383                *prev.else_branch.as_mut().unwrap().1 = Expr::If(expr);
2384                expr = prev;
2385            }
2386            expr.attrs = attrs;
2387            Ok(expr)
2388        }
2389    }
2390
2391    #[cfg(feature = "full")]
2392    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2393    impl Parse for ExprInfer {
2394        fn parse(input: ParseStream) -> Result<Self> {
2395            Ok(ExprInfer {
2396                attrs: input.call(Attribute::parse_outer)?,
2397                underscore_token: input.parse()?,
2398            })
2399        }
2400    }
2401
2402    #[cfg(feature = "full")]
2403    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2404    impl Parse for ExprForLoop {
2405        fn parse(input: ParseStream) -> Result<Self> {
2406            let mut attrs = input.call(Attribute::parse_outer)?;
2407            let label: Option<Label> = input.parse()?;
2408            let for_token: crate::token::ForToken![for] = input.parse()?;
2409
2410            let pat = Pat::parse_multi_with_leading_vert(input)?;
2411
2412            let in_token: crate::token::InToken![in] = input.parse()?;
2413            let expr: Expr = input.call(Expr::parse_without_eager_brace)?;
2414
2415            let content;
2416            let brace_token = match crate::__private::parse_braces(&input) {
    crate::__private::Ok(braces) => {
        content = braces.content;
        _ = content;
        braces.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
}braced!(content in input);
2417            attr::parsing::parse_inner(&content, &mut attrs)?;
2418            let stmts = content.call(Block::parse_within)?;
2419
2420            Ok(ExprForLoop {
2421                attrs,
2422                label,
2423                for_token,
2424                pat: Box::new(pat),
2425                in_token,
2426                expr: Box::new(expr),
2427                body: Block { brace_token, stmts },
2428            })
2429        }
2430    }
2431
2432    #[cfg(feature = "full")]
2433    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2434    impl Parse for ExprLoop {
2435        fn parse(input: ParseStream) -> Result<Self> {
2436            let mut attrs = input.call(Attribute::parse_outer)?;
2437            let label: Option<Label> = input.parse()?;
2438            let loop_token: crate::token::LoopToken![loop] = input.parse()?;
2439
2440            let content;
2441            let brace_token = match crate::__private::parse_braces(&input) {
    crate::__private::Ok(braces) => {
        content = braces.content;
        _ = content;
        braces.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
}braced!(content in input);
2442            attr::parsing::parse_inner(&content, &mut attrs)?;
2443            let stmts = content.call(Block::parse_within)?;
2444
2445            Ok(ExprLoop {
2446                attrs,
2447                label,
2448                loop_token,
2449                body: Block { brace_token, stmts },
2450            })
2451        }
2452    }
2453
2454    #[cfg(feature = "full")]
2455    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2456    impl Parse for ExprMatch {
2457        fn parse(input: ParseStream) -> Result<Self> {
2458            let mut attrs = input.call(Attribute::parse_outer)?;
2459            let match_token: crate::token::MatchToken![match] = input.parse()?;
2460            let expr = Expr::parse_without_eager_brace(input)?;
2461
2462            let content;
2463            let brace_token = match crate::__private::parse_braces(&input) {
    crate::__private::Ok(braces) => {
        content = braces.content;
        _ = content;
        braces.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
}braced!(content in input);
2464            attr::parsing::parse_inner(&content, &mut attrs)?;
2465
2466            let arms = Arm::parse_multiple(&content)?;
2467
2468            Ok(ExprMatch {
2469                attrs,
2470                match_token,
2471                expr: Box::new(expr),
2472                brace_token,
2473                arms,
2474            })
2475        }
2476    }
2477
2478    macro_rules! impl_by_parsing_expr {
2479        (
2480            $(
2481                $expr_type:ty, $variant:ident, $msg:expr,
2482            )*
2483        ) => {
2484            $(
2485                #[cfg(all(feature = "full", feature = "printing"))]
2486                #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2487                impl Parse for $expr_type {
2488                    fn parse(input: ParseStream) -> Result<Self> {
2489                        let mut expr: Expr = input.parse()?;
2490                        loop {
2491                            match expr {
2492                                Expr::$variant(inner) => return Ok(inner),
2493                                Expr::Group(next) => expr = *next.expr,
2494                                _ => return Err(Error::new_spanned(expr, $msg)),
2495                            }
2496                        }
2497                    }
2498                }
2499            )*
2500        };
2501    }
2502
2503    #[doc(cfg(feature = "parsing"))]
impl Parse for ExprAssign {
    fn parse(input: ParseStream) -> Result<Self> {
        let mut expr: Expr = input.parse()?;
        loop {
            match expr {
                Expr::Assign(inner) => return Ok(inner),
                Expr::Group(next) => expr = *next.expr,
                _ =>
                    return Err(Error::new_spanned(expr,
                                "expected assignment expression")),
            }
        }
    }
}
#[doc(cfg(feature = "parsing"))]
impl Parse for ExprAwait {
    fn parse(input: ParseStream) -> Result<Self> {
        let mut expr: Expr = input.parse()?;
        loop {
            match expr {
                Expr::Await(inner) => return Ok(inner),
                Expr::Group(next) => expr = *next.expr,
                _ =>
                    return Err(Error::new_spanned(expr,
                                "expected await expression")),
            }
        }
    }
}
#[doc(cfg(feature = "parsing"))]
impl Parse for ExprBinary {
    fn parse(input: ParseStream) -> Result<Self> {
        let mut expr: Expr = input.parse()?;
        loop {
            match expr {
                Expr::Binary(inner) => return Ok(inner),
                Expr::Group(next) => expr = *next.expr,
                _ =>
                    return Err(Error::new_spanned(expr,
                                "expected binary operation")),
            }
        }
    }
}
#[doc(cfg(feature = "parsing"))]
impl Parse for ExprCall {
    fn parse(input: ParseStream) -> Result<Self> {
        let mut expr: Expr = input.parse()?;
        loop {
            match expr {
                Expr::Call(inner) => return Ok(inner),
                Expr::Group(next) => expr = *next.expr,
                _ =>
                    return Err(Error::new_spanned(expr,
                                "expected function call expression")),
            }
        }
    }
}
#[doc(cfg(feature = "parsing"))]
impl Parse for ExprCast {
    fn parse(input: ParseStream) -> Result<Self> {
        let mut expr: Expr = input.parse()?;
        loop {
            match expr {
                Expr::Cast(inner) => return Ok(inner),
                Expr::Group(next) => expr = *next.expr,
                _ =>
                    return Err(Error::new_spanned(expr,
                                "expected cast expression")),
            }
        }
    }
}
#[doc(cfg(feature = "parsing"))]
impl Parse for ExprField {
    fn parse(input: ParseStream) -> Result<Self> {
        let mut expr: Expr = input.parse()?;
        loop {
            match expr {
                Expr::Field(inner) => return Ok(inner),
                Expr::Group(next) => expr = *next.expr,
                _ =>
                    return Err(Error::new_spanned(expr,
                                "expected struct field access")),
            }
        }
    }
}
#[doc(cfg(feature = "parsing"))]
impl Parse for ExprIndex {
    fn parse(input: ParseStream) -> Result<Self> {
        let mut expr: Expr = input.parse()?;
        loop {
            match expr {
                Expr::Index(inner) => return Ok(inner),
                Expr::Group(next) => expr = *next.expr,
                _ =>
                    return Err(Error::new_spanned(expr,
                                "expected indexing expression")),
            }
        }
    }
}
#[doc(cfg(feature = "parsing"))]
impl Parse for ExprMethodCall {
    fn parse(input: ParseStream) -> Result<Self> {
        let mut expr: Expr = input.parse()?;
        loop {
            match expr {
                Expr::MethodCall(inner) => return Ok(inner),
                Expr::Group(next) => expr = *next.expr,
                _ =>
                    return Err(Error::new_spanned(expr,
                                "expected method call expression")),
            }
        }
    }
}
#[doc(cfg(feature = "parsing"))]
impl Parse for ExprRange {
    fn parse(input: ParseStream) -> Result<Self> {
        let mut expr: Expr = input.parse()?;
        loop {
            match expr {
                Expr::Range(inner) => return Ok(inner),
                Expr::Group(next) => expr = *next.expr,
                _ =>
                    return Err(Error::new_spanned(expr,
                                "expected range expression")),
            }
        }
    }
}
#[doc(cfg(feature = "parsing"))]
impl Parse for ExprTry {
    fn parse(input: ParseStream) -> Result<Self> {
        let mut expr: Expr = input.parse()?;
        loop {
            match expr {
                Expr::Try(inner) => return Ok(inner),
                Expr::Group(next) => expr = *next.expr,
                _ =>
                    return Err(Error::new_spanned(expr,
                                "expected try expression")),
            }
        }
    }
}
#[doc(cfg(feature = "parsing"))]
impl Parse for ExprTuple {
    fn parse(input: ParseStream) -> Result<Self> {
        let mut expr: Expr = input.parse()?;
        loop {
            match expr {
                Expr::Tuple(inner) => return Ok(inner),
                Expr::Group(next) => expr = *next.expr,
                _ =>
                    return Err(Error::new_spanned(expr,
                                "expected tuple expression")),
            }
        }
    }
}impl_by_parsing_expr! {
2504        ExprAssign, Assign, "expected assignment expression",
2505        ExprAwait, Await, "expected await expression",
2506        ExprBinary, Binary, "expected binary operation",
2507        ExprCall, Call, "expected function call expression",
2508        ExprCast, Cast, "expected cast expression",
2509        ExprField, Field, "expected struct field access",
2510        ExprIndex, Index, "expected indexing expression",
2511        ExprMethodCall, MethodCall, "expected method call expression",
2512        ExprRange, Range, "expected range expression",
2513        ExprTry, Try, "expected try expression",
2514        ExprTuple, Tuple, "expected tuple expression",
2515    }
2516
2517    #[cfg(feature = "full")]
2518    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2519    impl Parse for ExprUnary {
2520        fn parse(input: ParseStream) -> Result<Self> {
2521            let attrs = Vec::new();
2522            let allow_struct = AllowStruct(true);
2523            expr_unary(input, attrs, allow_struct)
2524        }
2525    }
2526
2527    #[cfg(feature = "full")]
2528    fn expr_unary(
2529        input: ParseStream,
2530        attrs: Vec<Attribute>,
2531        allow_struct: AllowStruct,
2532    ) -> Result<ExprUnary> {
2533        Ok(ExprUnary {
2534            attrs,
2535            op: input.parse()?,
2536            expr: Box::new(unary_expr(input, allow_struct)?),
2537        })
2538    }
2539
2540    #[cfg(feature = "full")]
2541    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2542    impl Parse for ExprClosure {
2543        fn parse(input: ParseStream) -> Result<Self> {
2544            let allow_struct = AllowStruct(true);
2545            expr_closure(input, allow_struct)
2546        }
2547    }
2548
2549    #[cfg(feature = "full")]
2550    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2551    impl Parse for ExprRawAddr {
2552        fn parse(input: ParseStream) -> Result<Self> {
2553            let allow_struct = AllowStruct(true);
2554            Ok(ExprRawAddr {
2555                attrs: Vec::new(),
2556                and_token: input.parse()?,
2557                raw: input.parse()?,
2558                mutability: input.parse()?,
2559                expr: Box::new(unary_expr(input, allow_struct)?),
2560            })
2561        }
2562    }
2563
2564    #[cfg(feature = "full")]
2565    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2566    impl Parse for ExprReference {
2567        fn parse(input: ParseStream) -> Result<Self> {
2568            let allow_struct = AllowStruct(true);
2569            Ok(ExprReference {
2570                attrs: Vec::new(),
2571                and_token: input.parse()?,
2572                mutability: input.parse()?,
2573                expr: Box::new(unary_expr(input, allow_struct)?),
2574            })
2575        }
2576    }
2577
2578    #[cfg(feature = "full")]
2579    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2580    impl Parse for ExprBreak {
2581        fn parse(input: ParseStream) -> Result<Self> {
2582            let allow_struct = AllowStruct(true);
2583            expr_break(input, allow_struct)
2584        }
2585    }
2586
2587    #[cfg(feature = "full")]
2588    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2589    impl Parse for ExprReturn {
2590        fn parse(input: ParseStream) -> Result<Self> {
2591            Ok(ExprReturn {
2592                attrs: Vec::new(),
2593                return_token: input.parse()?,
2594                expr: {
2595                    if Expr::peek(input) {
2596                        Some(input.parse()?)
2597                    } else {
2598                        None
2599                    }
2600                },
2601            })
2602        }
2603    }
2604
2605    #[cfg(feature = "full")]
2606    fn expr_become(input: ParseStream) -> Result<Expr> {
2607        let begin = input.cursor();
2608        input.parse::<crate::token::BecomeToken![become]>()?;
2609        input.parse::<Expr>()?;
2610        Ok(Expr::Verbatim(verbatim::between(begin, input.cursor())))
2611    }
2612
2613    #[cfg(feature = "full")]
2614    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2615    impl Parse for ExprTryBlock {
2616        fn parse(input: ParseStream) -> Result<Self> {
2617            Ok(ExprTryBlock {
2618                attrs: Vec::new(),
2619                try_token: input.parse()?,
2620                modifiers: BlockModifiers {},
2621                block: input.parse()?,
2622            })
2623        }
2624    }
2625
2626    #[cfg(feature = "full")]
2627    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2628    impl Parse for ExprYield {
2629        fn parse(input: ParseStream) -> Result<Self> {
2630            Ok(ExprYield {
2631                attrs: Vec::new(),
2632                yield_token: input.parse()?,
2633                expr: {
2634                    if Expr::peek(input) {
2635                        Some(input.parse()?)
2636                    } else {
2637                        None
2638                    }
2639                },
2640            })
2641        }
2642    }
2643
2644    #[cfg(feature = "full")]
2645    fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
2646        let lifetimes: Option<BoundLifetimes> = input.parse()?;
2647        let constness: Option<crate::token::ConstToken![const]> = input.parse()?;
2648        let asyncness: Option<crate::token::AsyncToken![async]> = input.parse()?;
2649        let capture: Option<crate::token::MoveToken![move]> = input.parse()?;
2650        let inputs_begin: crate::token::OrToken![|] = input.parse()?;
2651
2652        let mut inputs = Punctuated::new();
2653        loop {
2654            if input.peek(crate::token::OrToken![|]) {
2655                break;
2656            }
2657            let value = closure_arg(input)?;
2658            inputs.push_value(value);
2659            if input.peek(crate::token::OrToken![|]) {
2660                break;
2661            }
2662            let punct: crate::token::CommaToken![,] = input.parse()?;
2663            inputs.push_punct(punct);
2664        }
2665
2666        let inputs_end: crate::token::OrToken![|] = input.parse()?;
2667
2668        let (output, body) = if input.peek(crate::token::RArrowToken![->]) {
2669            let arrow_token: crate::token::RArrowToken![->] = input.parse()?;
2670            let ty: Type = input.parse()?;
2671            let body: Block = input.parse()?;
2672            let output = ReturnType::Type(arrow_token, Box::new(ty));
2673            let block = Expr::Block(ExprBlock {
2674                attrs: Vec::new(),
2675                label: None,
2676                block: body,
2677            });
2678            (output, block)
2679        } else {
2680            let body = ambiguous_expr(input, allow_struct)?;
2681            (ReturnType::Default, body)
2682        };
2683
2684        Ok(ExprClosure {
2685            attrs: Vec::new(),
2686            lifetimes,
2687            modifiers: ClosureModifiers {},
2688            constness,
2689            asyncness,
2690            capture,
2691            inputs_begin,
2692            inputs,
2693            inputs_end,
2694            output,
2695            body: Box::new(body),
2696        })
2697    }
2698
2699    #[cfg(feature = "full")]
2700    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2701    impl Parse for ExprAsync {
2702        fn parse(input: ParseStream) -> Result<Self> {
2703            Ok(ExprAsync {
2704                attrs: Vec::new(),
2705                async_token: input.parse()?,
2706                capture: input.parse()?,
2707                modifiers: BlockModifiers {},
2708                block: input.parse()?,
2709            })
2710        }
2711    }
2712
2713    #[cfg(feature = "full")]
2714    fn closure_arg(input: ParseStream) -> Result<Pat> {
2715        let attrs = input.call(Attribute::parse_outer)?;
2716        let mut pat = Pat::parse_single(input)?;
2717
2718        if input.peek(crate::token::ColonToken![:]) {
2719            Ok(Pat::Type(PatType {
2720                attrs,
2721                pat: Box::new(pat),
2722                colon_token: input.parse()?,
2723                ty: input.parse()?,
2724            }))
2725        } else {
2726            match &mut pat {
2727                Pat::Const(pat) => pat.attrs = attrs,
2728                Pat::Guard(_) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
2729                Pat::Ident(pat) => pat.attrs = attrs,
2730                Pat::Lit(pat) => pat.attrs = attrs,
2731                Pat::Macro(pat) => pat.attrs = attrs,
2732                Pat::Or(pat) => pat.attrs = attrs,
2733                Pat::Paren(pat) => pat.attrs = attrs,
2734                Pat::Path(pat) => pat.attrs = attrs,
2735                Pat::Range(pat) => pat.attrs = attrs,
2736                Pat::Reference(pat) => pat.attrs = attrs,
2737                Pat::Rest(pat) => pat.attrs = attrs,
2738                Pat::Slice(pat) => pat.attrs = attrs,
2739                Pat::Struct(pat) => pat.attrs = attrs,
2740                Pat::Tuple(pat) => pat.attrs = attrs,
2741                Pat::TupleStruct(pat) => pat.attrs = attrs,
2742                Pat::Type(_) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
2743                Pat::Verbatim(_) => {}
2744                Pat::Wild(pat) => pat.attrs = attrs,
2745            }
2746            Ok(pat)
2747        }
2748    }
2749
2750    #[cfg(feature = "full")]
2751    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2752    impl Parse for ExprWhile {
2753        fn parse(input: ParseStream) -> Result<Self> {
2754            let mut attrs = input.call(Attribute::parse_outer)?;
2755            let label: Option<Label> = input.parse()?;
2756            let while_token: crate::token::WhileToken![while] = input.parse()?;
2757            let cond = Expr::parse_without_eager_brace(input)?;
2758
2759            let content;
2760            let brace_token = match crate::__private::parse_braces(&input) {
    crate::__private::Ok(braces) => {
        content = braces.content;
        _ = content;
        braces.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
}braced!(content in input);
2761            attr::parsing::parse_inner(&content, &mut attrs)?;
2762            let stmts = content.call(Block::parse_within)?;
2763
2764            Ok(ExprWhile {
2765                attrs,
2766                label,
2767                while_token,
2768                cond: Box::new(cond),
2769                body: Block { brace_token, stmts },
2770            })
2771        }
2772    }
2773
2774    #[cfg(feature = "full")]
2775    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2776    impl Parse for ExprConst {
2777        fn parse(input: ParseStream) -> Result<Self> {
2778            let const_token: crate::token::ConstToken![const] = input.parse()?;
2779
2780            let content;
2781            let brace_token = match crate::__private::parse_braces(&input) {
    crate::__private::Ok(braces) => {
        content = braces.content;
        _ = content;
        braces.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
}braced!(content in input);
2782            let inner_attrs = content.call(Attribute::parse_inner)?;
2783            let stmts = content.call(Block::parse_within)?;
2784
2785            Ok(ExprConst {
2786                attrs: inner_attrs,
2787                const_token,
2788                modifiers: BlockModifiers {},
2789                block: Block { brace_token, stmts },
2790            })
2791        }
2792    }
2793
2794    #[cfg(feature = "full")]
2795    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2796    impl Parse for Label {
2797        fn parse(input: ParseStream) -> Result<Self> {
2798            Ok(Label {
2799                name: Lifetime::parse_any(input)?,
2800                colon_token: input.parse()?,
2801            })
2802        }
2803    }
2804
2805    #[cfg(feature = "full")]
2806    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2807    impl Parse for Option<Label> {
2808        fn parse(input: ParseStream) -> Result<Self> {
2809            if input.peek(Lifetime) {
2810                input.parse().map(Some)
2811            } else {
2812                Ok(None)
2813            }
2814        }
2815    }
2816
2817    #[cfg(feature = "full")]
2818    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2819    impl Parse for ExprContinue {
2820        fn parse(input: ParseStream) -> Result<Self> {
2821            Ok(ExprContinue {
2822                attrs: Vec::new(),
2823                continue_token: input.parse()?,
2824                label: Lifetime::parse_optional_any(input),
2825            })
2826        }
2827    }
2828
2829    #[cfg(feature = "full")]
2830    fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2831        let break_token: crate::token::BreakToken![break] = input.parse()?;
2832
2833        let ahead = input.fork();
2834        let label_begin = ahead.cursor();
2835        let label = Lifetime::parse_optional_any(&ahead);
2836        if label.is_some() && ahead.peek(crate::token::ColonToken![:]) {
2837            // Not allowed: `break 'label: loop {...}`
2838            // Parentheses are required. `break ('label: loop {...})`
2839            let _: Expr = input.parse()?;
2840            return Err(Error::new_range(
2841                label_begin..input.cursor(),
2842                "parentheses required",
2843            ));
2844        }
2845
2846        input.advance_to(&ahead);
2847        let expr = if Expr::peek(input) && (allow_struct.0 || !input.peek(token::Brace)) {
2848            Some(input.parse()?)
2849        } else {
2850            None
2851        };
2852
2853        Ok(ExprBreak {
2854            attrs: Vec::new(),
2855            break_token,
2856            label,
2857            expr,
2858        })
2859    }
2860
2861    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2862    impl Parse for FieldValue {
2863        fn parse(input: ParseStream) -> Result<Self> {
2864            let attrs = input.call(Attribute::parse_outer)?;
2865            let member: Member = input.parse()?;
2866            let (colon_token, value) = if input.peek(crate::token::ColonToken![:]) || !member.is_named() {
2867                let colon_token: crate::token::ColonToken![:] = input.parse()?;
2868                let value: Expr = input.parse()?;
2869                (Some(colon_token), value)
2870            } else if let Member::Named(ident) = &member {
2871                let value = Expr::Path(ExprPath {
2872                    attrs: Vec::new(),
2873                    qself: None,
2874                    path: Path::from(ident.clone()),
2875                });
2876                (None, value)
2877            } else {
2878                ::core::panicking::panic("internal error: entered unreachable code")unreachable!()
2879            };
2880
2881            Ok(FieldValue {
2882                attrs,
2883                member,
2884                colon_token,
2885                expr: value,
2886            })
2887        }
2888    }
2889
2890    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2891    impl Parse for ExprStruct {
2892        fn parse(input: ParseStream) -> Result<Self> {
2893            let expr_style = true;
2894            let (qself, path) = path::parsing::qpath(input, expr_style)?;
2895            expr_struct_helper(input, qself, path)
2896        }
2897    }
2898
2899    fn expr_struct_helper(
2900        input: ParseStream,
2901        qself: Option<QSelf>,
2902        path: Path,
2903    ) -> Result<ExprStruct> {
2904        let content;
2905        let brace_token = match crate::__private::parse_braces(&input) {
    crate::__private::Ok(braces) => {
        content = braces.content;
        _ = content;
        braces.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
}braced!(content in input);
2906
2907        let mut fields = Punctuated::new();
2908        while !content.is_empty() {
2909            if content.peek(crate::token::DotDotToken![..]) {
2910                return Ok(ExprStruct {
2911                    attrs: Vec::new(),
2912                    qself,
2913                    path,
2914                    brace_token,
2915                    fields,
2916                    dot2_token: Some(content.parse()?),
2917                    rest: if content.is_empty() {
2918                        None
2919                    } else {
2920                        Some(Box::new(content.parse()?))
2921                    },
2922                });
2923            }
2924
2925            fields.push(content.parse()?);
2926            if content.is_empty() {
2927                break;
2928            }
2929            let punct: crate::token::CommaToken![,] = content.parse()?;
2930            fields.push_punct(punct);
2931        }
2932
2933        Ok(ExprStruct {
2934            attrs: Vec::new(),
2935            qself,
2936            path,
2937            brace_token,
2938            fields,
2939            dot2_token: None,
2940            rest: None,
2941        })
2942    }
2943
2944    #[cfg(feature = "full")]
2945    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2946    impl Parse for ExprUnsafe {
2947        fn parse(input: ParseStream) -> Result<Self> {
2948            let unsafe_token: crate::token::UnsafeToken![unsafe] = input.parse()?;
2949
2950            let content;
2951            let brace_token = match crate::__private::parse_braces(&input) {
    crate::__private::Ok(braces) => {
        content = braces.content;
        _ = content;
        braces.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
}braced!(content in input);
2952            let inner_attrs = content.call(Attribute::parse_inner)?;
2953            let stmts = content.call(Block::parse_within)?;
2954
2955            Ok(ExprUnsafe {
2956                attrs: inner_attrs,
2957                unsafe_token,
2958                block: Block { brace_token, stmts },
2959            })
2960        }
2961    }
2962
2963    #[cfg(feature = "full")]
2964    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2965    impl Parse for ExprBlock {
2966        fn parse(input: ParseStream) -> Result<Self> {
2967            let mut attrs = input.call(Attribute::parse_outer)?;
2968            let label: Option<Label> = input.parse()?;
2969
2970            let content;
2971            let brace_token = match crate::__private::parse_braces(&input) {
    crate::__private::Ok(braces) => {
        content = braces.content;
        _ = content;
        braces.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
}braced!(content in input);
2972            attr::parsing::parse_inner(&content, &mut attrs)?;
2973            let stmts = content.call(Block::parse_within)?;
2974
2975            Ok(ExprBlock {
2976                attrs,
2977                label,
2978                block: Block { brace_token, stmts },
2979            })
2980        }
2981    }
2982
2983    #[cfg(feature = "full")]
2984    fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2985        let limits: RangeLimits = input.parse()?;
2986        let end = parse_range_end(input, &limits, allow_struct)?;
2987        Ok(ExprRange {
2988            attrs: Vec::new(),
2989            start: None,
2990            limits,
2991            end,
2992        })
2993    }
2994
2995    #[cfg(feature = "full")]
2996    fn parse_range_end(
2997        input: ParseStream,
2998        limits: &RangeLimits,
2999        allow_struct: AllowStruct,
3000    ) -> Result<Option<Box<Expr>>> {
3001        if #[allow(non_exhaustive_omitted_patterns)] match limits {
    RangeLimits::HalfOpen(_) => true,
    _ => false,
}matches!(limits, RangeLimits::HalfOpen(_))
3002            && (input.is_empty()
3003                || input.peek(crate::token::CommaToken![,])
3004                || input.peek(crate::token::SemiToken![;])
3005                || input.peek(crate::token::DotToken![.]) && !input.peek(crate::token::DotDotToken![..])
3006                || input.peek(crate::token::QuestionToken![?])
3007                || input.peek(crate::token::FatArrowToken![=>])
3008                || !allow_struct.0 && input.peek(token::Brace)
3009                || input.peek(crate::token::EqToken![=])
3010                || input.peek(crate::token::PlusToken![+])
3011                || input.peek(crate::token::SlashToken![/])
3012                || input.peek(crate::token::PercentToken![%])
3013                || input.peek(crate::token::CaretToken![^])
3014                || input.peek(crate::token::GtToken![>])
3015                || input.peek(crate::token::LeToken![<=])
3016                || input.peek(crate::token::NeToken![!=])
3017                || input.peek(crate::token::MinusEqToken![-=])
3018                || input.peek(crate::token::StarEqToken![*=])
3019                || input.peek(crate::token::AndEqToken![&=])
3020                || input.peek(crate::token::OrEqToken![|=])
3021                || input.peek(crate::token::ShlEqToken![<<=])
3022                || input.peek(crate::token::AsToken![as]))
3023        {
3024            Ok(None)
3025        } else {
3026            let end = parse_binop_rhs(input, allow_struct, Precedence::Range)?;
3027            Ok(Some(end))
3028        }
3029    }
3030
3031    #[cfg(feature = "full")]
3032    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3033    impl Parse for RangeLimits {
3034        fn parse(input: ParseStream) -> Result<Self> {
3035            let lookahead = input.lookahead1();
3036            let dot_dot = lookahead.peek(crate::token::DotDotToken![..]);
3037            let dot_dot_eq = dot_dot && lookahead.peek(crate::token::DotDotEqToken![..=]);
3038            let dot_dot_dot = dot_dot && input.peek(crate::token::DotDotDotToken![...]);
3039            if dot_dot_eq {
3040                input.parse().map(RangeLimits::Closed)
3041            } else if dot_dot && !dot_dot_dot {
3042                input.parse().map(RangeLimits::HalfOpen)
3043            } else {
3044                Err(lookahead.error())
3045            }
3046        }
3047    }
3048
3049    #[cfg(feature = "full")]
3050    impl RangeLimits {
3051        pub(crate) fn parse_obsolete(input: ParseStream) -> Result<Self> {
3052            let lookahead = input.lookahead1();
3053            let dot_dot = lookahead.peek(crate::token::DotDotToken![..]);
3054            let dot_dot_eq = dot_dot && lookahead.peek(crate::token::DotDotEqToken![..=]);
3055            let dot_dot_dot = dot_dot && input.peek(crate::token::DotDotDotToken![...]);
3056            if dot_dot_eq {
3057                input.parse().map(RangeLimits::Closed)
3058            } else if dot_dot_dot {
3059                let dot3: crate::token::DotDotDotToken![...] = input.parse()?;
3060                Ok(RangeLimits::Closed(crate::token::DotDotEqToken![..=](dot3.spans)))
3061            } else if dot_dot {
3062                input.parse().map(RangeLimits::HalfOpen)
3063            } else {
3064                Err(lookahead.error())
3065            }
3066        }
3067    }
3068
3069    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3070    impl Parse for ExprPath {
3071        fn parse(input: ParseStream) -> Result<Self> {
3072            #[cfg(not(feature = "full"))]
3073            let attrs = Vec::new();
3074            #[cfg(feature = "full")]
3075            let attrs = input.call(Attribute::parse_outer)?;
3076
3077            let expr_style = true;
3078            let (qself, path) = path::parsing::qpath(input, expr_style)?;
3079
3080            Ok(ExprPath { attrs, qself, path })
3081        }
3082    }
3083
3084    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3085    impl Parse for Member {
3086        fn parse(input: ParseStream) -> Result<Self> {
3087            if input.peek(Ident) {
3088                input.parse().map(Member::Named)
3089            } else if input.peek(LitInt) {
3090                input.parse().map(Member::Unnamed)
3091            } else {
3092                Err(input.error("expected identifier or integer"))
3093            }
3094        }
3095    }
3096
3097    #[cfg(feature = "full")]
3098    impl Arm {
3099        pub(crate) fn parse_multiple(input: ParseStream) -> Result<Vec<Self>> {
3100            let mut arms = Vec::new();
3101            while !input.is_empty() {
3102                arms.push(input.call(Arm::parse)?);
3103            }
3104            Ok(arms)
3105        }
3106    }
3107
3108    #[cfg(feature = "full")]
3109    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3110    impl Parse for Arm {
3111        fn parse(input: ParseStream) -> Result<Arm> {
3112            let requires_comma;
3113            Ok(Arm {
3114                attrs: input.call(Attribute::parse_outer)?,
3115                pat: Pat::parse_multi_with_leading_vert_and_guard(input)?,
3116                fat_arrow_token: input.parse()?,
3117                body: {
3118                    let body = Expr::parse_with_earlier_boundary_rule(input)?;
3119                    requires_comma = classify::requires_comma_to_be_match_arm(&body);
3120                    Box::new(body)
3121                },
3122                comma: {
3123                    if requires_comma && !input.is_empty() {
3124                        Some(input.parse()?)
3125                    } else {
3126                        input.parse()?
3127                    }
3128                },
3129            })
3130        }
3131    }
3132
3133    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3134    impl Parse for Index {
3135        fn parse(input: ParseStream) -> Result<Self> {
3136            let lit: LitInt = input.parse()?;
3137            if lit.suffix().is_empty() {
3138                Ok(Index {
3139                    index: lit
3140                        .base10_digits()
3141                        .parse()
3142                        .map_err(|err| Error::new(lit.span(), err))?,
3143                    span: lit.span(),
3144                })
3145            } else {
3146                Err(Error::new(lit.span(), "expected unsuffixed integer"))
3147            }
3148        }
3149    }
3150
3151    fn multi_index(e: &mut Expr, dot_token: &mut crate::token::DotToken![.], float: LitFloat) -> Result<bool> {
3152        let float_token = float.token();
3153        let float_span = float_token.span();
3154        let mut float_repr = float_token.to_string();
3155        let trailing_dot = float_repr.ends_with('.');
3156        if trailing_dot {
3157            float_repr.truncate(float_repr.len() - 1);
3158        }
3159
3160        let mut offset = 0;
3161        for part in float_repr.split('.') {
3162            let mut index: Index =
3163                crate::parse_str(part).map_err(|err| Error::new(float_span, err))?;
3164            let part_end = offset + part.len();
3165            index.span = float_token.subspan(offset..part_end).unwrap_or(float_span);
3166
3167            let base = mem::replace(e, Expr::PLACEHOLDER);
3168            *e = Expr::Field(ExprField {
3169                attrs: Vec::new(),
3170                base: Box::new(base),
3171                dot_token: crate::token::DotToken![.](dot_token.span),
3172                member: Member::Unnamed(index),
3173            });
3174
3175            let dot_span = float_token
3176                .subspan(part_end..part_end + 1)
3177                .unwrap_or(float_span);
3178            *dot_token = crate::token::DotToken![.](dot_span);
3179            offset = part_end + 1;
3180        }
3181
3182        Ok(!trailing_dot)
3183    }
3184
3185    fn check_cast(input: ParseStream) -> Result<()> {
3186        let kind = if input.peek(crate::token::DotToken![.]) && !input.peek(crate::token::DotDotToken![..]) {
3187            if input.peek2(crate::token::AwaitToken![await]) {
3188                "`.await`"
3189            } else if input.peek2(Ident) && (input.peek3(token::Paren) || input.peek3(crate::token::PathSepToken![::])) {
3190                "a method call"
3191            } else {
3192                "a field access"
3193            }
3194        } else if input.peek(crate::token::QuestionToken![?]) {
3195            "`?`"
3196        } else if input.peek(token::Bracket) {
3197            "indexing"
3198        } else if input.peek(token::Paren) {
3199            "a function call"
3200        } else {
3201            return Ok(());
3202        };
3203        let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("casts cannot be followed by {0}",
                kind))
    })format!("casts cannot be followed by {}", kind);
3204        Err(input.error(msg))
3205    }
3206}
3207
3208#[cfg(feature = "printing")]
3209pub(crate) mod printing {
3210    use crate::attr::Attribute;
3211    #[cfg(feature = "full")]
3212    use crate::attr::FilterAttrs;
3213    #[cfg(feature = "full")]
3214    use crate::classify;
3215    #[cfg(feature = "full")]
3216    use crate::expr::{
3217        Arm, ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure,
3218        ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch,
3219        ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprUnsafe,
3220        ExprWhile, ExprYield, Label, RangeLimits,
3221    };
3222    use crate::expr::{
3223        Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro,
3224        ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprTuple, ExprUnary,
3225        FieldValue, Index, Member,
3226    };
3227    use crate::fixup::FixupContext;
3228    use crate::op::BinOp;
3229    use crate::path;
3230    use crate::path::printing::PathStyle;
3231    use crate::precedence::Precedence;
3232    use crate::token;
3233    #[cfg(feature = "full")]
3234    use crate::ty::ReturnType;
3235    use proc_macro2::{Literal, Span, TokenStream};
3236    use quote::{ToTokens, TokenStreamExt as _};
3237
3238    #[cfg(feature = "full")]
3239    pub(crate) fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3240        tokens.append_all(attrs.outer());
3241    }
3242
3243    #[cfg(feature = "full")]
3244    fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3245        tokens.append_all(attrs.inner());
3246    }
3247
3248    #[cfg(not(feature = "full"))]
3249    pub(crate) fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3250
3251    pub(crate) fn print_subexpression(
3252        expr: &Expr,
3253        needs_group: bool,
3254        tokens: &mut TokenStream,
3255        mut fixup: FixupContext,
3256    ) {
3257        if needs_group {
3258            // If we are surrounding the whole cond in parentheses, such as:
3259            //
3260            //     if (return Struct {}) {}
3261            //
3262            // then there is no need for parenthesizing the individual struct
3263            // expressions within. On the other hand if the whole cond is not
3264            // parenthesized, then print_expr must parenthesize exterior struct
3265            // literals.
3266            //
3267            //     if x == (Struct {}) {}
3268            //
3269            fixup = FixupContext::NONE;
3270        }
3271
3272        let do_print_expr = |tokens: &mut TokenStream| print_expr(expr, tokens, fixup);
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    pub(crate) fn print_expr(expr: &Expr, tokens: &mut TokenStream, mut fixup: FixupContext) {
3282        #[cfg(feature = "full")]
3283        let needs_group = fixup.parenthesize(expr);
3284        #[cfg(not(feature = "full"))]
3285        let needs_group = false;
3286
3287        if needs_group {
3288            fixup = FixupContext::NONE;
3289        }
3290
3291        let do_print_expr = |tokens: &mut TokenStream| match expr {
3292            #[cfg(feature = "full")]
3293            Expr::Array(e) => e.to_tokens(tokens),
3294            #[cfg(feature = "full")]
3295            Expr::Assign(e) => print_expr_assign(e, tokens, fixup),
3296            #[cfg(feature = "full")]
3297            Expr::Async(e) => e.to_tokens(tokens),
3298            #[cfg(feature = "full")]
3299            Expr::Await(e) => print_expr_await(e, tokens, fixup),
3300            Expr::Binary(e) => print_expr_binary(e, tokens, fixup),
3301            #[cfg(feature = "full")]
3302            Expr::Block(e) => e.to_tokens(tokens),
3303            #[cfg(feature = "full")]
3304            Expr::Break(e) => print_expr_break(e, tokens, fixup),
3305            Expr::Call(e) => print_expr_call(e, tokens, fixup),
3306            Expr::Cast(e) => print_expr_cast(e, tokens, fixup),
3307            #[cfg(feature = "full")]
3308            Expr::Closure(e) => print_expr_closure(e, tokens, fixup),
3309            #[cfg(feature = "full")]
3310            Expr::Const(e) => e.to_tokens(tokens),
3311            #[cfg(feature = "full")]
3312            Expr::Continue(e) => e.to_tokens(tokens),
3313            Expr::Field(e) => print_expr_field(e, tokens, fixup),
3314            #[cfg(feature = "full")]
3315            Expr::ForLoop(e) => e.to_tokens(tokens),
3316            Expr::Group(e) => e.to_tokens(tokens),
3317            #[cfg(feature = "full")]
3318            Expr::If(e) => e.to_tokens(tokens),
3319            Expr::Index(e) => print_expr_index(e, tokens, fixup),
3320            #[cfg(feature = "full")]
3321            Expr::Infer(e) => e.to_tokens(tokens),
3322            #[cfg(feature = "full")]
3323            Expr::Let(e) => print_expr_let(e, tokens, fixup),
3324            Expr::Lit(e) => e.to_tokens(tokens),
3325            #[cfg(feature = "full")]
3326            Expr::Loop(e) => e.to_tokens(tokens),
3327            Expr::Macro(e) => e.to_tokens(tokens),
3328            #[cfg(feature = "full")]
3329            Expr::Match(e) => e.to_tokens(tokens),
3330            Expr::MethodCall(e) => print_expr_method_call(e, tokens, fixup),
3331            Expr::Paren(e) => e.to_tokens(tokens),
3332            Expr::Path(e) => e.to_tokens(tokens),
3333            #[cfg(feature = "full")]
3334            Expr::Range(e) => print_expr_range(e, tokens, fixup),
3335            #[cfg(feature = "full")]
3336            Expr::RawAddr(e) => print_expr_raw_addr(e, tokens, fixup),
3337            Expr::Reference(e) => print_expr_reference(e, tokens, fixup),
3338            #[cfg(feature = "full")]
3339            Expr::Repeat(e) => e.to_tokens(tokens),
3340            #[cfg(feature = "full")]
3341            Expr::Return(e) => print_expr_return(e, tokens, fixup),
3342            Expr::Struct(e) => e.to_tokens(tokens),
3343            #[cfg(feature = "full")]
3344            Expr::Try(e) => print_expr_try(e, tokens, fixup),
3345            #[cfg(feature = "full")]
3346            Expr::TryBlock(e) => e.to_tokens(tokens),
3347            Expr::Tuple(e) => e.to_tokens(tokens),
3348            Expr::Unary(e) => print_expr_unary(e, tokens, fixup),
3349            #[cfg(feature = "full")]
3350            Expr::Unsafe(e) => e.to_tokens(tokens),
3351            Expr::Verbatim(e) => e.to_tokens(tokens),
3352            #[cfg(feature = "full")]
3353            Expr::While(e) => e.to_tokens(tokens),
3354            #[cfg(feature = "full")]
3355            Expr::Yield(e) => print_expr_yield(e, tokens, fixup),
3356
3357            #[cfg(not(feature = "full"))]
3358            _ => unreachable!(),
3359        };
3360
3361        if needs_group {
3362            token::Paren::default().surround(tokens, do_print_expr);
3363        } else {
3364            do_print_expr(tokens);
3365        }
3366    }
3367
3368    #[cfg(feature = "full")]
3369    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3370    impl ToTokens for ExprArray {
3371        fn to_tokens(&self, tokens: &mut TokenStream) {
3372            outer_attrs_to_tokens(&self.attrs, tokens);
3373            self.bracket_token.surround(tokens, |tokens| {
3374                self.elems.to_tokens(tokens);
3375            });
3376        }
3377    }
3378
3379    #[cfg(feature = "full")]
3380    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3381    impl ToTokens for ExprAssign {
3382        fn to_tokens(&self, tokens: &mut TokenStream) {
3383            print_expr_assign(self, tokens, FixupContext::NONE);
3384        }
3385    }
3386
3387    #[cfg(feature = "full")]
3388    fn print_expr_assign(e: &ExprAssign, tokens: &mut TokenStream, mut fixup: FixupContext) {
3389        outer_attrs_to_tokens(&e.attrs, tokens);
3390
3391        let needs_group = !e.attrs.is_empty();
3392        if needs_group {
3393            fixup = FixupContext::NONE;
3394        }
3395
3396        let do_print_expr = |tokens: &mut TokenStream| {
3397            let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3398                &e.left,
3399                false,
3400                false,
3401                Precedence::Assign,
3402            );
3403            print_subexpression(&e.left, left_prec <= Precedence::Range, tokens, left_fixup);
3404            e.eq_token.to_tokens(tokens);
3405            print_expr(
3406                &e.right,
3407                tokens,
3408                fixup.rightmost_subexpression_fixup(false, false, Precedence::Assign),
3409            );
3410        };
3411
3412        if needs_group {
3413            token::Paren::default().surround(tokens, do_print_expr);
3414        } else {
3415            do_print_expr(tokens);
3416        }
3417    }
3418
3419    #[cfg(feature = "full")]
3420    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3421    impl ToTokens for ExprAsync {
3422        fn to_tokens(&self, tokens: &mut TokenStream) {
3423            outer_attrs_to_tokens(&self.attrs, tokens);
3424            self.async_token.to_tokens(tokens);
3425            self.capture.to_tokens(tokens);
3426            self.block.to_tokens(tokens);
3427        }
3428    }
3429
3430    #[cfg(feature = "full")]
3431    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3432    impl ToTokens for ExprAwait {
3433        fn to_tokens(&self, tokens: &mut TokenStream) {
3434            print_expr_await(self, tokens, FixupContext::NONE);
3435        }
3436    }
3437
3438    #[cfg(feature = "full")]
3439    fn print_expr_await(e: &ExprAwait, tokens: &mut TokenStream, fixup: FixupContext) {
3440        outer_attrs_to_tokens(&e.attrs, tokens);
3441        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.base);
3442        print_subexpression(
3443            &e.base,
3444            left_prec < Precedence::Unambiguous,
3445            tokens,
3446            left_fixup,
3447        );
3448        e.dot_token.to_tokens(tokens);
3449        e.await_token.to_tokens(tokens);
3450    }
3451
3452    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3453    impl ToTokens for ExprBinary {
3454        fn to_tokens(&self, tokens: &mut TokenStream) {
3455            print_expr_binary(self, tokens, FixupContext::NONE);
3456        }
3457    }
3458
3459    fn print_expr_binary(e: &ExprBinary, tokens: &mut TokenStream, mut fixup: FixupContext) {
3460        outer_attrs_to_tokens(&e.attrs, tokens);
3461
3462        let needs_group = !e.attrs.is_empty();
3463        if needs_group {
3464            fixup = FixupContext::NONE;
3465        }
3466
3467        let do_print_expr = |tokens: &mut TokenStream| {
3468            let binop_prec = Precedence::of_binop(&e.op);
3469            let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3470                &e.left,
3471                #[cfg(feature = "full")]
3472                match &e.op {
3473                    BinOp::Sub(_)
3474                    | BinOp::Mul(_)
3475                    | BinOp::And(_)
3476                    | BinOp::Or(_)
3477                    | BinOp::BitAnd(_)
3478                    | BinOp::BitOr(_)
3479                    | BinOp::Shl(_)
3480                    | BinOp::Lt(_) => true,
3481                    _ => false,
3482                },
3483                match &e.op {
3484                    BinOp::Shl(_) | BinOp::Lt(_) => true,
3485                    _ => false,
3486                },
3487                #[cfg(feature = "full")]
3488                binop_prec,
3489            );
3490            let left_needs_group = match binop_prec {
3491                Precedence::Assign => left_prec <= Precedence::Range,
3492                Precedence::Compare => left_prec <= binop_prec,
3493                _ => left_prec < binop_prec,
3494            };
3495
3496            let right_fixup = fixup.rightmost_subexpression_fixup(
3497                #[cfg(feature = "full")]
3498                false,
3499                #[cfg(feature = "full")]
3500                false,
3501                #[cfg(feature = "full")]
3502                binop_prec,
3503            );
3504            let right_needs_group = binop_prec != Precedence::Assign
3505                && right_fixup.rightmost_subexpression_precedence(&e.right) <= binop_prec;
3506
3507            print_subexpression(&e.left, left_needs_group, tokens, left_fixup);
3508            e.op.to_tokens(tokens);
3509            print_subexpression(&e.right, right_needs_group, tokens, right_fixup);
3510        };
3511
3512        if needs_group {
3513            token::Paren::default().surround(tokens, do_print_expr);
3514        } else {
3515            do_print_expr(tokens);
3516        }
3517    }
3518
3519    #[cfg(feature = "full")]
3520    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3521    impl ToTokens for ExprBlock {
3522        fn to_tokens(&self, tokens: &mut TokenStream) {
3523            outer_attrs_to_tokens(&self.attrs, tokens);
3524            self.label.to_tokens(tokens);
3525            self.block.brace_token.surround(tokens, |tokens| {
3526                inner_attrs_to_tokens(&self.attrs, tokens);
3527                tokens.append_all(&self.block.stmts);
3528            });
3529        }
3530    }
3531
3532    #[cfg(feature = "full")]
3533    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3534    impl ToTokens for ExprBreak {
3535        fn to_tokens(&self, tokens: &mut TokenStream) {
3536            print_expr_break(self, tokens, FixupContext::NONE);
3537        }
3538    }
3539
3540    #[cfg(feature = "full")]
3541    fn print_expr_break(e: &ExprBreak, tokens: &mut TokenStream, fixup: FixupContext) {
3542        outer_attrs_to_tokens(&e.attrs, tokens);
3543        e.break_token.to_tokens(tokens);
3544        e.label.to_tokens(tokens);
3545        if let Some(value) = &e.expr {
3546            print_subexpression(
3547                value,
3548                // Parenthesize `break 'inner: loop { break 'inner 1 } + 1`
3549                //                     ^---------------------------------^
3550                e.label.is_none() && classify::expr_leading_label(value),
3551                tokens,
3552                fixup.rightmost_subexpression_fixup(true, true, Precedence::Jump),
3553            );
3554        }
3555    }
3556
3557    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3558    impl ToTokens for ExprCall {
3559        fn to_tokens(&self, tokens: &mut TokenStream) {
3560            print_expr_call(self, tokens, FixupContext::NONE);
3561        }
3562    }
3563
3564    fn print_expr_call(e: &ExprCall, tokens: &mut TokenStream, fixup: FixupContext) {
3565        outer_attrs_to_tokens(&e.attrs, tokens);
3566
3567        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3568            &e.func,
3569            #[cfg(feature = "full")]
3570            true,
3571            false,
3572            #[cfg(feature = "full")]
3573            Precedence::Unambiguous,
3574        );
3575        let needs_group = if let Expr::Field(func) = &*e.func {
3576            func.member.is_named()
3577        } else {
3578            left_prec < Precedence::Unambiguous
3579        };
3580        print_subexpression(&e.func, needs_group, tokens, left_fixup);
3581
3582        e.paren_token.surround(tokens, |tokens| {
3583            e.args.to_tokens(tokens);
3584        });
3585    }
3586
3587    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3588    impl ToTokens for ExprCast {
3589        fn to_tokens(&self, tokens: &mut TokenStream) {
3590            print_expr_cast(self, tokens, FixupContext::NONE);
3591        }
3592    }
3593
3594    fn print_expr_cast(e: &ExprCast, tokens: &mut TokenStream, mut fixup: FixupContext) {
3595        outer_attrs_to_tokens(&e.attrs, tokens);
3596
3597        let needs_group = !e.attrs.is_empty();
3598        if needs_group {
3599            fixup = FixupContext::NONE;
3600        }
3601
3602        let do_print_expr = |tokens: &mut TokenStream| {
3603            let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3604                &e.expr,
3605                #[cfg(feature = "full")]
3606                false,
3607                false,
3608                #[cfg(feature = "full")]
3609                Precedence::Cast,
3610            );
3611            print_subexpression(&e.expr, left_prec < Precedence::Cast, tokens, left_fixup);
3612            e.as_token.to_tokens(tokens);
3613            e.ty.to_tokens(tokens);
3614        };
3615
3616        if needs_group {
3617            token::Paren::default().surround(tokens, do_print_expr);
3618        } else {
3619            do_print_expr(tokens);
3620        }
3621    }
3622
3623    #[cfg(feature = "full")]
3624    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3625    impl ToTokens for ExprClosure {
3626        fn to_tokens(&self, tokens: &mut TokenStream) {
3627            print_expr_closure(self, tokens, FixupContext::NONE);
3628        }
3629    }
3630
3631    #[cfg(feature = "full")]
3632    fn print_expr_closure(e: &ExprClosure, tokens: &mut TokenStream, fixup: FixupContext) {
3633        outer_attrs_to_tokens(&e.attrs, tokens);
3634        e.lifetimes.to_tokens(tokens);
3635        e.constness.to_tokens(tokens);
3636        e.asyncness.to_tokens(tokens);
3637        e.capture.to_tokens(tokens);
3638        e.inputs_begin.to_tokens(tokens);
3639        e.inputs.to_tokens(tokens);
3640        e.inputs_end.to_tokens(tokens);
3641        e.output.to_tokens(tokens);
3642        if #[allow(non_exhaustive_omitted_patterns)] match e.output {
    ReturnType::Default => true,
    _ => false,
}matches!(e.output, ReturnType::Default)
3643            || #[allow(non_exhaustive_omitted_patterns)] match &*e.body {
    Expr::Block(body) if body.attrs.is_empty() && body.label.is_none() =>
        true,
    _ => false,
}matches!(&*e.body, Expr::Block(body) if body.attrs.is_empty() && body.label.is_none())
3644        {
3645            print_expr(
3646                &e.body,
3647                tokens,
3648                fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump),
3649            );
3650        } else {
3651            token::Brace::default().surround(tokens, |tokens| {
3652                print_expr(&e.body, tokens, FixupContext::new_stmt());
3653            });
3654        }
3655    }
3656
3657    #[cfg(feature = "full")]
3658    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3659    impl ToTokens for ExprConst {
3660        fn to_tokens(&self, tokens: &mut TokenStream) {
3661            outer_attrs_to_tokens(&self.attrs, tokens);
3662            self.const_token.to_tokens(tokens);
3663            self.block.brace_token.surround(tokens, |tokens| {
3664                inner_attrs_to_tokens(&self.attrs, tokens);
3665                tokens.append_all(&self.block.stmts);
3666            });
3667        }
3668    }
3669
3670    #[cfg(feature = "full")]
3671    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3672    impl ToTokens for ExprContinue {
3673        fn to_tokens(&self, tokens: &mut TokenStream) {
3674            outer_attrs_to_tokens(&self.attrs, tokens);
3675            self.continue_token.to_tokens(tokens);
3676            self.label.to_tokens(tokens);
3677        }
3678    }
3679
3680    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3681    impl ToTokens for ExprField {
3682        fn to_tokens(&self, tokens: &mut TokenStream) {
3683            print_expr_field(self, tokens, FixupContext::NONE);
3684        }
3685    }
3686
3687    fn print_expr_field(e: &ExprField, tokens: &mut TokenStream, fixup: FixupContext) {
3688        outer_attrs_to_tokens(&e.attrs, tokens);
3689        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.base);
3690        print_subexpression(
3691            &e.base,
3692            left_prec < Precedence::Unambiguous,
3693            tokens,
3694            left_fixup,
3695        );
3696        e.dot_token.to_tokens(tokens);
3697        e.member.to_tokens(tokens);
3698    }
3699
3700    #[cfg(feature = "full")]
3701    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3702    impl ToTokens for ExprForLoop {
3703        fn to_tokens(&self, tokens: &mut TokenStream) {
3704            outer_attrs_to_tokens(&self.attrs, tokens);
3705            self.label.to_tokens(tokens);
3706            self.for_token.to_tokens(tokens);
3707            self.pat.to_tokens(tokens);
3708            self.in_token.to_tokens(tokens);
3709            print_expr(&self.expr, tokens, FixupContext::new_condition());
3710            self.body.brace_token.surround(tokens, |tokens| {
3711                inner_attrs_to_tokens(&self.attrs, tokens);
3712                tokens.append_all(&self.body.stmts);
3713            });
3714        }
3715    }
3716
3717    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3718    impl ToTokens for ExprGroup {
3719        fn to_tokens(&self, tokens: &mut TokenStream) {
3720            outer_attrs_to_tokens(&self.attrs, tokens);
3721            self.group_token.surround(tokens, |tokens| {
3722                self.expr.to_tokens(tokens);
3723            });
3724        }
3725    }
3726
3727    #[cfg(feature = "full")]
3728    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3729    impl ToTokens for ExprIf {
3730        fn to_tokens(&self, tokens: &mut TokenStream) {
3731            outer_attrs_to_tokens(&self.attrs, tokens);
3732
3733            let mut expr = self;
3734            loop {
3735                expr.if_token.to_tokens(tokens);
3736                print_expr(&expr.cond, tokens, FixupContext::new_condition());
3737                expr.then_branch.to_tokens(tokens);
3738
3739                let (else_token, else_) = match &expr.else_branch {
3740                    Some(else_branch) => else_branch,
3741                    None => break,
3742                };
3743
3744                else_token.to_tokens(tokens);
3745                match &**else_ {
3746                    Expr::If(next) => {
3747                        expr = next;
3748                    }
3749                    Expr::Block(last) => {
3750                        last.to_tokens(tokens);
3751                        break;
3752                    }
3753                    // If this is not one of the valid expressions to exist in
3754                    // an else clause, wrap it in a block.
3755                    other => {
3756                        token::Brace::default().surround(tokens, |tokens| {
3757                            print_expr(other, tokens, FixupContext::new_stmt());
3758                        });
3759                        break;
3760                    }
3761                }
3762            }
3763        }
3764    }
3765
3766    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3767    impl ToTokens for ExprIndex {
3768        fn to_tokens(&self, tokens: &mut TokenStream) {
3769            print_expr_index(self, tokens, FixupContext::NONE);
3770        }
3771    }
3772
3773    fn print_expr_index(e: &ExprIndex, tokens: &mut TokenStream, fixup: FixupContext) {
3774        outer_attrs_to_tokens(&e.attrs, tokens);
3775        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3776            &e.expr,
3777            #[cfg(feature = "full")]
3778            true,
3779            false,
3780            #[cfg(feature = "full")]
3781            Precedence::Unambiguous,
3782        );
3783        print_subexpression(
3784            &e.expr,
3785            left_prec < Precedence::Unambiguous,
3786            tokens,
3787            left_fixup,
3788        );
3789        e.bracket_token.surround(tokens, |tokens| {
3790            e.index.to_tokens(tokens);
3791        });
3792    }
3793
3794    #[cfg(feature = "full")]
3795    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3796    impl ToTokens for ExprInfer {
3797        fn to_tokens(&self, tokens: &mut TokenStream) {
3798            outer_attrs_to_tokens(&self.attrs, tokens);
3799            self.underscore_token.to_tokens(tokens);
3800        }
3801    }
3802
3803    #[cfg(feature = "full")]
3804    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3805    impl ToTokens for ExprLet {
3806        fn to_tokens(&self, tokens: &mut TokenStream) {
3807            print_expr_let(self, tokens, FixupContext::NONE);
3808        }
3809    }
3810
3811    #[cfg(feature = "full")]
3812    fn print_expr_let(e: &ExprLet, tokens: &mut TokenStream, fixup: FixupContext) {
3813        outer_attrs_to_tokens(&e.attrs, tokens);
3814        e.let_token.to_tokens(tokens);
3815        e.pat.to_tokens(tokens);
3816        e.eq_token.to_tokens(tokens);
3817        let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Let);
3818        print_subexpression(&e.expr, right_prec < Precedence::Let, tokens, right_fixup);
3819    }
3820
3821    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3822    impl ToTokens for ExprLit {
3823        fn to_tokens(&self, tokens: &mut TokenStream) {
3824            outer_attrs_to_tokens(&self.attrs, tokens);
3825            self.lit.to_tokens(tokens);
3826        }
3827    }
3828
3829    #[cfg(feature = "full")]
3830    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3831    impl ToTokens for ExprLoop {
3832        fn to_tokens(&self, tokens: &mut TokenStream) {
3833            outer_attrs_to_tokens(&self.attrs, tokens);
3834            self.label.to_tokens(tokens);
3835            self.loop_token.to_tokens(tokens);
3836            self.body.brace_token.surround(tokens, |tokens| {
3837                inner_attrs_to_tokens(&self.attrs, tokens);
3838                tokens.append_all(&self.body.stmts);
3839            });
3840        }
3841    }
3842
3843    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3844    impl ToTokens for ExprMacro {
3845        fn to_tokens(&self, tokens: &mut TokenStream) {
3846            outer_attrs_to_tokens(&self.attrs, tokens);
3847            self.mac.to_tokens(tokens);
3848        }
3849    }
3850
3851    #[cfg(feature = "full")]
3852    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3853    impl ToTokens for ExprMatch {
3854        fn to_tokens(&self, tokens: &mut TokenStream) {
3855            outer_attrs_to_tokens(&self.attrs, tokens);
3856            self.match_token.to_tokens(tokens);
3857            print_expr(&self.expr, tokens, FixupContext::new_condition());
3858            self.brace_token.surround(tokens, |tokens| {
3859                inner_attrs_to_tokens(&self.attrs, tokens);
3860                for (i, arm) in self.arms.iter().enumerate() {
3861                    arm.to_tokens(tokens);
3862                    // Ensure that we have a comma after a non-block arm, except
3863                    // for the last one.
3864                    let is_last = i == self.arms.len() - 1;
3865                    if !is_last
3866                        && classify::requires_comma_to_be_match_arm(&arm.body)
3867                        && arm.comma.is_none()
3868                    {
3869                        <crate::token::CommaToken![,]>::default().to_tokens(tokens);
3870                    }
3871                }
3872            });
3873        }
3874    }
3875
3876    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3877    impl ToTokens for ExprMethodCall {
3878        fn to_tokens(&self, tokens: &mut TokenStream) {
3879            print_expr_method_call(self, tokens, FixupContext::NONE);
3880        }
3881    }
3882
3883    fn print_expr_method_call(e: &ExprMethodCall, tokens: &mut TokenStream, fixup: FixupContext) {
3884        outer_attrs_to_tokens(&e.attrs, tokens);
3885        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.receiver);
3886        print_subexpression(
3887            &e.receiver,
3888            left_prec < Precedence::Unambiguous,
3889            tokens,
3890            left_fixup,
3891        );
3892        e.dot_token.to_tokens(tokens);
3893        e.method.to_tokens(tokens);
3894        if let Some(turbofish) = &e.turbofish {
3895            path::printing::print_angle_bracketed_generic_arguments(
3896                tokens,
3897                turbofish,
3898                PathStyle::Expr,
3899            );
3900        }
3901        e.paren_token.surround(tokens, |tokens| {
3902            e.args.to_tokens(tokens);
3903        });
3904    }
3905
3906    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3907    impl ToTokens for ExprParen {
3908        fn to_tokens(&self, tokens: &mut TokenStream) {
3909            outer_attrs_to_tokens(&self.attrs, tokens);
3910            self.paren_token.surround(tokens, |tokens| {
3911                self.expr.to_tokens(tokens);
3912            });
3913        }
3914    }
3915
3916    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3917    impl ToTokens for ExprPath {
3918        fn to_tokens(&self, tokens: &mut TokenStream) {
3919            outer_attrs_to_tokens(&self.attrs, tokens);
3920            path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
3921        }
3922    }
3923
3924    #[cfg(feature = "full")]
3925    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3926    impl ToTokens for ExprRange {
3927        fn to_tokens(&self, tokens: &mut TokenStream) {
3928            print_expr_range(self, tokens, FixupContext::NONE);
3929        }
3930    }
3931
3932    #[cfg(feature = "full")]
3933    fn print_expr_range(e: &ExprRange, tokens: &mut TokenStream, mut fixup: FixupContext) {
3934        outer_attrs_to_tokens(&e.attrs, tokens);
3935
3936        let needs_group = !e.attrs.is_empty();
3937        if needs_group {
3938            fixup = FixupContext::NONE;
3939        }
3940
3941        let do_print_expr = |tokens: &mut TokenStream| {
3942            if let Some(start) = &e.start {
3943                let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3944                    start,
3945                    true,
3946                    false,
3947                    Precedence::Range,
3948                );
3949                print_subexpression(start, left_prec <= Precedence::Range, tokens, left_fixup);
3950            }
3951            e.limits.to_tokens(tokens);
3952            if let Some(end) = &e.end {
3953                let right_fixup =
3954                    fixup.rightmost_subexpression_fixup(false, true, Precedence::Range);
3955                let right_prec = right_fixup.rightmost_subexpression_precedence(end);
3956                print_subexpression(end, right_prec <= Precedence::Range, tokens, right_fixup);
3957            }
3958        };
3959
3960        if needs_group {
3961            token::Paren::default().surround(tokens, do_print_expr);
3962        } else {
3963            do_print_expr(tokens);
3964        }
3965    }
3966
3967    #[cfg(feature = "full")]
3968    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3969    impl ToTokens for ExprRawAddr {
3970        fn to_tokens(&self, tokens: &mut TokenStream) {
3971            print_expr_raw_addr(self, tokens, FixupContext::NONE);
3972        }
3973    }
3974
3975    #[cfg(feature = "full")]
3976    fn print_expr_raw_addr(e: &ExprRawAddr, tokens: &mut TokenStream, fixup: FixupContext) {
3977        outer_attrs_to_tokens(&e.attrs, tokens);
3978        e.and_token.to_tokens(tokens);
3979        e.raw.to_tokens(tokens);
3980        e.mutability.to_tokens(tokens);
3981        let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Prefix);
3982        print_subexpression(
3983            &e.expr,
3984            right_prec < Precedence::Prefix,
3985            tokens,
3986            right_fixup,
3987        );
3988    }
3989
3990    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3991    impl ToTokens for ExprReference {
3992        fn to_tokens(&self, tokens: &mut TokenStream) {
3993            print_expr_reference(self, tokens, FixupContext::NONE);
3994        }
3995    }
3996
3997    fn print_expr_reference(e: &ExprReference, tokens: &mut TokenStream, fixup: FixupContext) {
3998        outer_attrs_to_tokens(&e.attrs, tokens);
3999        e.and_token.to_tokens(tokens);
4000        e.mutability.to_tokens(tokens);
4001        let (right_prec, right_fixup) = fixup.rightmost_subexpression(
4002            &e.expr,
4003            #[cfg(feature = "full")]
4004            Precedence::Prefix,
4005        );
4006        print_subexpression(
4007            &e.expr,
4008            right_prec < Precedence::Prefix,
4009            tokens,
4010            right_fixup,
4011        );
4012    }
4013
4014    #[cfg(feature = "full")]
4015    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4016    impl ToTokens for ExprRepeat {
4017        fn to_tokens(&self, tokens: &mut TokenStream) {
4018            outer_attrs_to_tokens(&self.attrs, tokens);
4019            self.bracket_token.surround(tokens, |tokens| {
4020                self.expr.to_tokens(tokens);
4021                self.semi_token.to_tokens(tokens);
4022                self.len.to_tokens(tokens);
4023            });
4024        }
4025    }
4026
4027    #[cfg(feature = "full")]
4028    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4029    impl ToTokens for ExprReturn {
4030        fn to_tokens(&self, tokens: &mut TokenStream) {
4031            print_expr_return(self, tokens, FixupContext::NONE);
4032        }
4033    }
4034
4035    #[cfg(feature = "full")]
4036    fn print_expr_return(e: &ExprReturn, tokens: &mut TokenStream, fixup: FixupContext) {
4037        outer_attrs_to_tokens(&e.attrs, tokens);
4038        e.return_token.to_tokens(tokens);
4039        if let Some(expr) = &e.expr {
4040            print_expr(
4041                expr,
4042                tokens,
4043                fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
4044            );
4045        }
4046    }
4047
4048    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4049    impl ToTokens for ExprStruct {
4050        fn to_tokens(&self, tokens: &mut TokenStream) {
4051            outer_attrs_to_tokens(&self.attrs, tokens);
4052            path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
4053            self.brace_token.surround(tokens, |tokens| {
4054                self.fields.to_tokens(tokens);
4055                if let Some(dot2_token) = &self.dot2_token {
4056                    dot2_token.to_tokens(tokens);
4057                } else if self.rest.is_some() {
4058                    crate::token::DotDotToken![..](Span::call_site()).to_tokens(tokens);
4059                }
4060                self.rest.to_tokens(tokens);
4061            });
4062        }
4063    }
4064
4065    #[cfg(feature = "full")]
4066    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4067    impl ToTokens for ExprTry {
4068        fn to_tokens(&self, tokens: &mut TokenStream) {
4069            print_expr_try(self, tokens, FixupContext::NONE);
4070        }
4071    }
4072
4073    #[cfg(feature = "full")]
4074    fn print_expr_try(e: &ExprTry, tokens: &mut TokenStream, fixup: FixupContext) {
4075        outer_attrs_to_tokens(&e.attrs, tokens);
4076        let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.expr);
4077        print_subexpression(
4078            &e.expr,
4079            left_prec < Precedence::Unambiguous,
4080            tokens,
4081            left_fixup,
4082        );
4083        e.question_token.to_tokens(tokens);
4084    }
4085
4086    #[cfg(feature = "full")]
4087    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4088    impl ToTokens for ExprTryBlock {
4089        fn to_tokens(&self, tokens: &mut TokenStream) {
4090            outer_attrs_to_tokens(&self.attrs, tokens);
4091            self.try_token.to_tokens(tokens);
4092            self.block.to_tokens(tokens);
4093        }
4094    }
4095
4096    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4097    impl ToTokens for ExprTuple {
4098        fn to_tokens(&self, tokens: &mut TokenStream) {
4099            outer_attrs_to_tokens(&self.attrs, tokens);
4100            self.paren_token.surround(tokens, |tokens| {
4101                self.elems.to_tokens(tokens);
4102                // If we only have one argument, we need a trailing comma to
4103                // distinguish ExprTuple from ExprParen.
4104                if self.elems.len() == 1 && !self.elems.trailing_punct() {
4105                    <crate::token::CommaToken![,]>::default().to_tokens(tokens);
4106                }
4107            });
4108        }
4109    }
4110
4111    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4112    impl ToTokens for ExprUnary {
4113        fn to_tokens(&self, tokens: &mut TokenStream) {
4114            print_expr_unary(self, tokens, FixupContext::NONE);
4115        }
4116    }
4117
4118    fn print_expr_unary(e: &ExprUnary, tokens: &mut TokenStream, fixup: FixupContext) {
4119        outer_attrs_to_tokens(&e.attrs, tokens);
4120        e.op.to_tokens(tokens);
4121        let (right_prec, right_fixup) = fixup.rightmost_subexpression(
4122            &e.expr,
4123            #[cfg(feature = "full")]
4124            Precedence::Prefix,
4125        );
4126        print_subexpression(
4127            &e.expr,
4128            right_prec < Precedence::Prefix,
4129            tokens,
4130            right_fixup,
4131        );
4132    }
4133
4134    #[cfg(feature = "full")]
4135    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4136    impl ToTokens for ExprUnsafe {
4137        fn to_tokens(&self, tokens: &mut TokenStream) {
4138            outer_attrs_to_tokens(&self.attrs, tokens);
4139            self.unsafe_token.to_tokens(tokens);
4140            self.block.brace_token.surround(tokens, |tokens| {
4141                inner_attrs_to_tokens(&self.attrs, tokens);
4142                tokens.append_all(&self.block.stmts);
4143            });
4144        }
4145    }
4146
4147    #[cfg(feature = "full")]
4148    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4149    impl ToTokens for ExprWhile {
4150        fn to_tokens(&self, tokens: &mut TokenStream) {
4151            outer_attrs_to_tokens(&self.attrs, tokens);
4152            self.label.to_tokens(tokens);
4153            self.while_token.to_tokens(tokens);
4154            print_expr(&self.cond, tokens, FixupContext::new_condition());
4155            self.body.brace_token.surround(tokens, |tokens| {
4156                inner_attrs_to_tokens(&self.attrs, tokens);
4157                tokens.append_all(&self.body.stmts);
4158            });
4159        }
4160    }
4161
4162    #[cfg(feature = "full")]
4163    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4164    impl ToTokens for ExprYield {
4165        fn to_tokens(&self, tokens: &mut TokenStream) {
4166            print_expr_yield(self, tokens, FixupContext::NONE);
4167        }
4168    }
4169
4170    #[cfg(feature = "full")]
4171    fn print_expr_yield(e: &ExprYield, tokens: &mut TokenStream, fixup: FixupContext) {
4172        outer_attrs_to_tokens(&e.attrs, tokens);
4173        e.yield_token.to_tokens(tokens);
4174        if let Some(expr) = &e.expr {
4175            print_expr(
4176                expr,
4177                tokens,
4178                fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
4179            );
4180        }
4181    }
4182
4183    #[cfg(feature = "full")]
4184    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4185    impl ToTokens for Arm {
4186        fn to_tokens(&self, tokens: &mut TokenStream) {
4187            tokens.append_all(&self.attrs);
4188            self.pat.to_tokens(tokens);
4189            self.fat_arrow_token.to_tokens(tokens);
4190            print_expr(&self.body, tokens, FixupContext::new_match_arm());
4191            self.comma.to_tokens(tokens);
4192        }
4193    }
4194
4195    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4196    impl ToTokens for FieldValue {
4197        fn to_tokens(&self, tokens: &mut TokenStream) {
4198            outer_attrs_to_tokens(&self.attrs, tokens);
4199            self.member.to_tokens(tokens);
4200            if let Some(colon_token) = &self.colon_token {
4201                colon_token.to_tokens(tokens);
4202                self.expr.to_tokens(tokens);
4203            }
4204        }
4205    }
4206
4207    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4208    impl ToTokens for Index {
4209        fn to_tokens(&self, tokens: &mut TokenStream) {
4210            let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
4211            lit.set_span(self.span);
4212            tokens.append(lit);
4213        }
4214    }
4215
4216    #[cfg(feature = "full")]
4217    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4218    impl ToTokens for Label {
4219        fn to_tokens(&self, tokens: &mut TokenStream) {
4220            self.name.to_tokens(tokens);
4221            self.colon_token.to_tokens(tokens);
4222        }
4223    }
4224
4225    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4226    impl ToTokens for Member {
4227        fn to_tokens(&self, tokens: &mut TokenStream) {
4228            match self {
4229                Member::Named(ident) => ident.to_tokens(tokens),
4230                Member::Unnamed(index) => index.to_tokens(tokens),
4231            }
4232        }
4233    }
4234
4235    #[cfg(feature = "full")]
4236    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4237    impl ToTokens for RangeLimits {
4238        fn to_tokens(&self, tokens: &mut TokenStream) {
4239            match self {
4240                RangeLimits::HalfOpen(t) => t.to_tokens(tokens),
4241                RangeLimits::Closed(t) => t.to_tokens(tokens),
4242            }
4243        }
4244    }
4245}