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