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."]
#[non_exhaustive]
pub enum Expr {

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

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

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

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

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

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

    #[doc = r" A `break`, with an optional label to break and an optional"]
    #[doc = r" expression."]
    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`."]
    Closure(ExprClosure),

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

    #[doc = r" A `continue`, with an optional label."]
    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 { ... }`."]
    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."]
    If(ExprIf),

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

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

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

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

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

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

    #[doc =
    r" A `match` expression: `match n { Some(n) => {}, None => {} }`."]
    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`."]
    Range(ExprRange),

    #[doc = r" Address-of operation: `&raw const place` or `&raw mut place`."]
    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]`."]
    Repeat(ExprRepeat),

    #[doc = r" A `return`, with an optional value to be returned."]
    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?`."]
    Try(ExprTry),

    #[doc = r" A try block: `try { ... }`."]
    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 { ... }`."]
    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 { ... }`."]
    While(ExprWhile),

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