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