syn/
expr.rs

1use crate::attr::Attribute;
2#[cfg(all(feature = "parsing", feature = "full"))]
3use crate::error::Result;
4#[cfg(feature = "parsing")]
5use crate::ext::IdentExt as _;
6#[cfg(feature = "full")]
7use crate::generics::BoundLifetimes;
8use crate::ident::Ident;
9#[cfg(any(feature = "parsing", feature = "full"))]
10use crate::lifetime::Lifetime;
11use crate::lit::Lit;
12use crate::mac::Macro;
13use crate::op::{BinOp, UnOp};
14#[cfg(feature = "parsing")]
15use crate::parse::ParseStream;
16#[cfg(feature = "full")]
17use crate::pat::Pat;
18use crate::path::{AngleBracketedGenericArguments, Path, QSelf};
19use crate::punctuated::Punctuated;
20#[cfg(feature = "full")]
21use crate::stmt::Block;
22use crate::token;
23#[cfg(feature = "full")]
24use crate::ty::ReturnType;
25use crate::ty::Type;
26use 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`."]
#[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 blocked scope: `{ ... }`."]
    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 `let` guard: `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`."]
    Unary(ExprUnary),

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

    #[doc = r" Tokens in expression position not interpreted by Syn."]
    Verbatim(TokenStream),

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

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