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