// SPDX-License-Identifier: Apache-2.0 OR MIT use crate::attr::Attribute;#[cfg(all(feature = "parsing", feature = "full"))]use crate::error::Result;#[cfg(feature = "parsing")]use crate::ext::IdentExt as _;#[cfg(feature = "full")]use crate::generics::BoundLifetimes;use crate::ident::Ident;#[cfg(any(feature = "parsing", feature = "full"))]use crate::lifetime::Lifetime;use crate::lit::Lit;use crate::mac::Macro;use crate::op::{BinOp, UnOp};#[cfg(feature = "parsing")]use crate::parse::ParseStream;#[cfg(feature = "full")]use crate::pat::Pat;use crate::path::{AngleBracketedGenericArguments, Path, QSelf};use crate::punctuated::Punctuated;#[cfg(feature = "full")]use crate::stmt::Block;use crate::token;#[cfg(feature = "full")]use crate::ty::ReturnType;use crate::ty::Type;use proc_macro2::{Span, TokenStream};#[cfg(feature = "printing")]use quote::IdentFragment;#[cfg(feature = "printing")]use std::fmt::{self, Display};use std::hash::{Hash, Hasher};#[cfg(all(feature = "parsing", feature = "full"))]use std::mem; ast_enum_of_structs! { /// A Rust expression. /// /// *This type is available only if Syn is built with the `"derive"` or `"full"` /// feature, but most of the variants are not available unless "full" is enabled.* /// /// # Syntax tree enums /// /// This type is a syntax tree enum. In Syn this and other syntax tree enums /// are designed to be traversed using the following rebinding idiom. /// /// ``` /// # use syn::Expr; /// # /// # fn example(expr: Expr) { /// # const IGNORE: &str = stringify! { /// let expr: Expr = /* ... */; /// # }; /// match expr { /// Expr::MethodCall(expr) => { /// /* ... */ /// } /// Expr::Cast(expr) => { /// /* ... */ /// } /// Expr::If(expr) => { /// /* ... */ /// } /// /// /* ... */ /// # _ => {} /// # } /// # } /// ``` /// /// We begin with a variable `expr` of type `Expr` that has no fields /// (because it is an enum), and by matching on it and rebinding a variable /// with the same name `expr` we effectively imbue our variable with all of /// the data fields provided by the variant that it turned out to be. So for /// example above if we ended up in the `MethodCall` case then we get to use /// `expr.receiver`, `expr.args` etc; if we ended up in the `If` case we get /// to use `expr.cond`, `expr.then_branch`, `expr.else_branch`. /// /// This approach avoids repeating the variant names twice on every line. /// /// ``` /// # use syn::{Expr, ExprMethodCall}; /// # /// # fn example(expr: Expr) { /// // Repetitive; recommend not doing this. /// match expr { /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => { /// # } /// # _ => {} /// # } /// # } /// ``` /// /// In general, the name to which a syntax tree enum variant is bound should /// be a suitable name for the complete syntax tree enum type. /// /// ``` /// # use syn::{Expr, ExprField}; /// # /// # fn example(discriminant: ExprField) { /// // Binding is called `base` which is the name I would use if I were /// // assigning `*discriminant.base` without an `if let`. /// if let Expr::Tuple(base) = *discriminant.base { /// # } /// # } /// ``` /// /// A sign that you may not be choosing the right variable names is if you /// see names getting repeated in your code, like accessing /// `receiver.receiver` or `pat.pat` or `cond.cond`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] #[non_exhaustive] pub enum Expr { /// A slice literal expression: `[a, b, c, d]`. Array(ExprArray), /// An assignment expression: `a = compute()`. Assign(ExprAssign), /// An async block: `async { ... }`. Async(ExprAsync), /// An await expression: `fut.await`. Await(ExprAwait), /// A binary operation: `a + b`, `a += b`. Binary(ExprBinary), /// A blocked scope: `{ ... }`. Block(ExprBlock), /// A `break`, with an optional label to break and an optional /// expression. Break(ExprBreak), /// A function call expression: `invoke(a, b)`. Call(ExprCall), /// A cast expression: `foo as f64`. Cast(ExprCast), /// A closure expression: `|a, b| a + b`. Closure(ExprClosure), /// A const block: `const { ... }`. Const(ExprConst), /// A `continue`, with an optional label. Continue(ExprContinue), /// Access of a named struct field (`obj.k`) or unnamed tuple struct /// field (`obj.0`). Field(ExprField), /// A for loop: `for pat in expr { ... }`. ForLoop(ExprForLoop), /// An expression contained within invisible delimiters. /// /// This variant is important for faithfully representing the precedence /// of expressions and is related to `None`-delimited spans in a /// `TokenStream`. Group(ExprGroup), /// An `if` expression with an optional `else` block: `if expr { ... } /// else { ... }`. /// /// The `else` branch expression may only be an `If` or `Block` /// expression, not any of the other types of expression. If(ExprIf), /// A square bracketed indexing expression: `vector[2]`. Index(ExprIndex), /// The inferred value of a const generic argument, denoted `_`. Infer(ExprInfer), /// A `let` guard: `let Some(x) = opt`. Let(ExprLet), /// A literal in place of an expression: `1`, `"foo"`. Lit(ExprLit), /// Conditionless loop: `loop { ... }`. Loop(ExprLoop), /// A macro invocation expression: `format!("{}", q)`. Macro(ExprMacro), /// A `match` expression: `match n { Some(n) => {}, None => {} }`. Match(ExprMatch), /// A method call expression: `x.foo::<T>(a, b)`. MethodCall(ExprMethodCall), /// A parenthesized expression: `(a + b)`. Paren(ExprParen), /// A path like `std::mem::replace` possibly containing generic /// parameters and a qualified self-type. /// /// A plain identifier like `x` is a path of length 1. Path(ExprPath), /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`. Range(ExprRange), /// Address-of operation: `&raw const place` or `&raw mut place`. RawAddr(ExprRawAddr), /// A referencing operation: `&a` or `&mut a`. Reference(ExprReference), /// An array literal constructed from one repeated element: `[0u8; N]`. Repeat(ExprRepeat), /// A `return`, with an optional value to be returned. Return(ExprReturn), /// A struct literal expression: `Point { x: 1, y: 1 }`. /// /// The `rest` provides the value of the remaining fields as in `S { a: /// 1, b: 1, ..rest }`. Struct(ExprStruct), /// A try-expression: `expr?`. Try(ExprTry), /// A try block: `try { ... }`. TryBlock(ExprTryBlock), /// A tuple expression: `(a, b, c, d)`. Tuple(ExprTuple), /// A unary operation: `!x`, `*x`. Unary(ExprUnary), /// An unsafe block: `unsafe { ... }`. Unsafe(ExprUnsafe), /// Tokens in expression position not interpreted by Syn. Verbatim(TokenStream), /// A while loop: `while expr { ... }`. While(ExprWhile), /// A yield expression: `yield expr`. Yield(ExprYield), // For testing exhaustiveness in downstream code, use the following idiom: // // match expr { // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))] // // Expr::Array(expr) => {...} // Expr::Assign(expr) => {...} // ... // Expr::Yield(expr) => {...} // // _ => { /* some sane fallback */ } // } // // This way we fail your tests but don't break your library when adding // a variant. You will be notified by a test failure when a variant is // added, so that you can add code to handle it, but your library will // continue to compile and work for downstream users in the interim. }} ast_struct! { /// A slice literal expression: `[a, b, c, d]`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprArray #full { pub attrs: Vec<Attribute>, pub bracket_token: token::Bracket, pub elems: Punctuated<Expr, Token![,]>, }} ast_struct! { /// An assignment expression: `a = compute()`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprAssign #full { pub attrs: Vec<Attribute>, pub left: Box<Expr>, pub eq_token: Token![=], pub right: Box<Expr>, }} ast_struct! { /// An async block: `async { ... }`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprAsync #full { pub attrs: Vec<Attribute>, pub async_token: Token![async], pub capture: Option<Token![move]>, pub block: Block, }} ast_struct! { /// An await expression: `fut.await`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprAwait #full { pub attrs: Vec<Attribute>, pub base: Box<Expr>, pub dot_token: Token![.], pub await_token: Token![await], }} ast_struct! { /// A binary operation: `a + b`, `a += b`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct ExprBinary { pub attrs: Vec<Attribute>, pub left: Box<Expr>, pub op: BinOp, pub right: Box<Expr>, }} ast_struct! { /// A blocked scope: `{ ... }`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprBlock #full { pub attrs: Vec<Attribute>, pub label: Option<Label>, pub block: Block, }} ast_struct! { /// A `break`, with an optional label to break and an optional /// expression. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprBreak #full { pub attrs: Vec<Attribute>, pub break_token: Token![break], pub label: Option<Lifetime>, pub expr: Option<Box<Expr>>, }} ast_struct! { /// A function call expression: `invoke(a, b)`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct ExprCall { pub attrs: Vec<Attribute>, pub func: Box<Expr>, pub paren_token: token::Paren, pub args: Punctuated<Expr, Token![,]>, }} ast_struct! { /// A cast expression: `foo as f64`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct ExprCast { pub attrs: Vec<Attribute>, pub expr: Box<Expr>, pub as_token: Token![as], pub ty: Box<Type>, }} ast_struct! { /// A closure expression: `|a, b| a + b`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprClosure #full { pub attrs: Vec<Attribute>, pub lifetimes: Option<BoundLifetimes>, pub constness: Option<Token![const]>, pub movability: Option<Token![static]>, pub asyncness: Option<Token![async]>, pub capture: Option<Token![move]>, pub or1_token: Token![|], pub inputs: Punctuated<Pat, Token![,]>, pub or2_token: Token![|], pub output: ReturnType, pub body: Box<Expr>, }} ast_struct! { /// A const block: `const { ... }`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprConst #full { pub attrs: Vec<Attribute>, pub const_token: Token![const], pub block: Block, }} ast_struct! { /// A `continue`, with an optional label. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprContinue #full { pub attrs: Vec<Attribute>, pub continue_token: Token![continue], pub label: Option<Lifetime>, }} ast_struct! { /// Access of a named struct field (`obj.k`) or unnamed tuple struct /// field (`obj.0`). #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct ExprField { pub attrs: Vec<Attribute>, pub base: Box<Expr>, pub dot_token: Token![.], pub member: Member, }} ast_struct! { /// A for loop: `for pat in expr { ... }`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprForLoop #full { pub attrs: Vec<Attribute>, pub label: Option<Label>, pub for_token: Token![for], pub pat: Box<Pat>, pub in_token: Token![in], pub expr: Box<Expr>, pub body: Block, }} ast_struct! { /// An expression contained within invisible delimiters. /// /// This variant is important for faithfully representing the precedence /// of expressions and is related to `None`-delimited spans in a /// `TokenStream`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprGroup { pub attrs: Vec<Attribute>, pub group_token: token::Group, pub expr: Box<Expr>, }} ast_struct! { /// An `if` expression with an optional `else` block: `if expr { ... } /// else { ... }`. /// /// The `else` branch expression may only be an `If` or `Block` /// expression, not any of the other types of expression. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprIf #full { pub attrs: Vec<Attribute>, pub if_token: Token![if], pub cond: Box<Expr>, pub then_branch: Block, pub else_branch: Option<(Token![else], Box<Expr>)>, }} ast_struct! { /// A square bracketed indexing expression: `vector[2]`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct ExprIndex { pub attrs: Vec<Attribute>, pub expr: Box<Expr>, pub bracket_token: token::Bracket, pub index: Box<Expr>, }} ast_struct! { /// The inferred value of a const generic argument, denoted `_`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprInfer #full { pub attrs: Vec<Attribute>, pub underscore_token: Token![_], }} ast_struct! { /// A `let` guard: `let Some(x) = opt`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprLet #full { pub attrs: Vec<Attribute>, pub let_token: Token![let], pub pat: Box<Pat>, pub eq_token: Token![=], pub expr: Box<Expr>, }} ast_struct! { /// A literal in place of an expression: `1`, `"foo"`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct ExprLit { pub attrs: Vec<Attribute>, pub lit: Lit,Lines 1–500 of 4175. Load more
// SPDX-License-Identifier: Apache-2.0 OR MIT use crate::attr::Attribute; #[cfg(all(feature = "parsing", feature = "full"))] use crate::error::Result; #[cfg(feature = "parsing")] use crate::ext::IdentExt as _; #[cfg(feature = "full")] use crate::generics::BoundLifetimes; use crate::ident::Ident; #[cfg(any(feature = "parsing", feature = "full"))] use crate::lifetime::Lifetime; use crate::lit::Lit; use crate::mac::Macro; use crate::op::{BinOp, UnOp}; #[cfg(feature = "parsing")] use crate::parse::ParseStream; #[cfg(feature = "full")] use crate::pat::Pat; use crate::path::{AngleBracketedGenericArguments, Path, QSelf}; use crate::punctuated::Punctuated; #[cfg(feature = "full")] use crate::stmt::Block; use crate::token; #[cfg(feature = "full")] use crate::ty::ReturnType; use crate::ty::Type; use proc_macro2::{Span, TokenStream}; #[cfg(feature = "printing")] use quote::IdentFragment; #[cfg(feature = "printing")] use std::fmt::{self, Display}; use std::hash::{Hash, Hasher}; #[cfg(all(feature = "parsing", feature = "full"))] use std::mem; ast_enum_of_structs! { /// A Rust expression. /// /// *This type is available only if Syn is built with the `"derive"` or `"full"` /// feature, but most of the variants are not available unless "full" is enabled.* /// /// # Syntax tree enums /// /// This type is a syntax tree enum. In Syn this and other syntax tree enums /// are designed to be traversed using the following rebinding idiom. /// /// ``` /// # use syn::Expr; /// # /// # fn example(expr: Expr) { /// # const IGNORE: &str = stringify! { /// let expr: Expr = /* ... */; /// # }; /// match expr { /// Expr::MethodCall(expr) => { /// /* ... */ /// } /// Expr::Cast(expr) => { /// /* ... */ /// } /// Expr::If(expr) => { /// /* ... */ /// } /// /// /* ... */ /// # _ => {} /// # } /// # } /// ``` /// /// We begin with a variable `expr` of type `Expr` that has no fields /// (because it is an enum), and by matching on it and rebinding a variable /// with the same name `expr` we effectively imbue our variable with all of /// the data fields provided by the variant that it turned out to be. So for /// example above if we ended up in the `MethodCall` case then we get to use /// `expr.receiver`, `expr.args` etc; if we ended up in the `If` case we get /// to use `expr.cond`, `expr.then_branch`, `expr.else_branch`. /// /// This approach avoids repeating the variant names twice on every line. /// /// ``` /// # use syn::{Expr, ExprMethodCall}; /// # /// # fn example(expr: Expr) { /// // Repetitive; recommend not doing this. /// match expr { /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => { /// # } /// # _ => {} /// # } /// # } /// ``` /// /// In general, the name to which a syntax tree enum variant is bound should /// be a suitable name for the complete syntax tree enum type. /// /// ``` /// # use syn::{Expr, ExprField}; /// # /// # fn example(discriminant: ExprField) { /// // Binding is called `base` which is the name I would use if I were /// // assigning `*discriminant.base` without an `if let`. /// if let Expr::Tuple(base) = *discriminant.base { /// # } /// # } /// ``` /// /// A sign that you may not be choosing the right variable names is if you /// see names getting repeated in your code, like accessing /// `receiver.receiver` or `pat.pat` or `cond.cond`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] #[non_exhaustive] pub enum Expr { /// A slice literal expression: `[a, b, c, d]`. Array(ExprArray), /// An assignment expression: `a = compute()`. Assign(ExprAssign), /// An async block: `async { ... }`. Async(ExprAsync), /// An await expression: `fut.await`. Await(ExprAwait), /// A binary operation: `a + b`, `a += b`. Binary(ExprBinary), /// A blocked scope: `{ ... }`. Block(ExprBlock), /// A `break`, with an optional label to break and an optional /// expression. Break(ExprBreak), /// A function call expression: `invoke(a, b)`. Call(ExprCall), /// A cast expression: `foo as f64`. Cast(ExprCast), /// A closure expression: `|a, b| a + b`. Closure(ExprClosure), /// A const block: `const { ... }`. Const(ExprConst), /// A `continue`, with an optional label. Continue(ExprContinue), /// Access of a named struct field (`obj.k`) or unnamed tuple struct /// field (`obj.0`). Field(ExprField), /// A for loop: `for pat in expr { ... }`. ForLoop(ExprForLoop), /// An expression contained within invisible delimiters. /// /// This variant is important for faithfully representing the precedence /// of expressions and is related to `None`-delimited spans in a /// `TokenStream`. Group(ExprGroup), /// An `if` expression with an optional `else` block: `if expr { ... } /// else { ... }`. /// /// The `else` branch expression may only be an `If` or `Block` /// expression, not any of the other types of expression. If(ExprIf), /// A square bracketed indexing expression: `vector[2]`. Index(ExprIndex), /// The inferred value of a const generic argument, denoted `_`. Infer(ExprInfer), /// A `let` guard: `let Some(x) = opt`. Let(ExprLet), /// A literal in place of an expression: `1`, `"foo"`. Lit(ExprLit), /// Conditionless loop: `loop { ... }`. Loop(ExprLoop), /// A macro invocation expression: `format!("{}", q)`. Macro(ExprMacro), /// A `match` expression: `match n { Some(n) => {}, None => {} }`. Match(ExprMatch), /// A method call expression: `x.foo::<T>(a, b)`. MethodCall(ExprMethodCall), /// A parenthesized expression: `(a + b)`. Paren(ExprParen), /// A path like `std::mem::replace` possibly containing generic /// parameters and a qualified self-type. /// /// A plain identifier like `x` is a path of length 1. Path(ExprPath), /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`. Range(ExprRange), /// Address-of operation: `&raw const place` or `&raw mut place`. RawAddr(ExprRawAddr), /// A referencing operation: `&a` or `&mut a`. Reference(ExprReference), /// An array literal constructed from one repeated element: `[0u8; N]`. Repeat(ExprRepeat), /// A `return`, with an optional value to be returned. Return(ExprReturn), /// A struct literal expression: `Point { x: 1, y: 1 }`. /// /// The `rest` provides the value of the remaining fields as in `S { a: /// 1, b: 1, ..rest }`. Struct(ExprStruct), /// A try-expression: `expr?`. Try(ExprTry), /// A try block: `try { ... }`. TryBlock(ExprTryBlock), /// A tuple expression: `(a, b, c, d)`. Tuple(ExprTuple), /// A unary operation: `!x`, `*x`. Unary(ExprUnary), /// An unsafe block: `unsafe { ... }`. Unsafe(ExprUnsafe), /// Tokens in expression position not interpreted by Syn. Verbatim(TokenStream), /// A while loop: `while expr { ... }`. While(ExprWhile), /// A yield expression: `yield expr`. Yield(ExprYield), // For testing exhaustiveness in downstream code, use the following idiom: // // match expr { // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))] // // Expr::Array(expr) => {...} // Expr::Assign(expr) => {...} // ... // Expr::Yield(expr) => {...} // // _ => { /* some sane fallback */ } // } // // This way we fail your tests but don't break your library when adding // a variant. You will be notified by a test failure when a variant is // added, so that you can add code to handle it, but your library will // continue to compile and work for downstream users in the interim. } } ast_struct! { /// A slice literal expression: `[a, b, c, d]`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprArray #full { pub attrs: Vec<Attribute>, pub bracket_token: token::Bracket, pub elems: Punctuated<Expr, Token![,]>, } } ast_struct! { /// An assignment expression: `a = compute()`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprAssign #full { pub attrs: Vec<Attribute>, pub left: Box<Expr>, pub eq_token: Token![=], pub right: Box<Expr>, } } ast_struct! { /// An async block: `async { ... }`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprAsync #full { pub attrs: Vec<Attribute>, pub async_token: Token![async], pub capture: Option<Token![move]>, pub block: Block, } } ast_struct! { /// An await expression: `fut.await`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprAwait #full { pub attrs: Vec<Attribute>, pub base: Box<Expr>, pub dot_token: Token![.], pub await_token: Token![await], } } ast_struct! { /// A binary operation: `a + b`, `a += b`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct ExprBinary { pub attrs: Vec<Attribute>, pub left: Box<Expr>, pub op: BinOp, pub right: Box<Expr>, } } ast_struct! { /// A blocked scope: `{ ... }`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprBlock #full { pub attrs: Vec<Attribute>, pub label: Option<Label>, pub block: Block, } } ast_struct! { /// A `break`, with an optional label to break and an optional /// expression. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprBreak #full { pub attrs: Vec<Attribute>, pub break_token: Token![break], pub label: Option<Lifetime>, pub expr: Option<Box<Expr>>, } } ast_struct! { /// A function call expression: `invoke(a, b)`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct ExprCall { pub attrs: Vec<Attribute>, pub func: Box<Expr>, pub paren_token: token::Paren, pub args: Punctuated<Expr, Token![,]>, } } ast_struct! { /// A cast expression: `foo as f64`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct ExprCast { pub attrs: Vec<Attribute>, pub expr: Box<Expr>, pub as_token: Token![as], pub ty: Box<Type>, } } ast_struct! { /// A closure expression: `|a, b| a + b`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprClosure #full { pub attrs: Vec<Attribute>, pub lifetimes: Option<BoundLifetimes>, pub constness: Option<Token![const]>, pub movability: Option<Token![static]>, pub asyncness: Option<Token![async]>, pub capture: Option<Token![move]>, pub or1_token: Token![|], pub inputs: Punctuated<Pat, Token![,]>, pub or2_token: Token![|], pub output: ReturnType, pub body: Box<Expr>, } } ast_struct! { /// A const block: `const { ... }`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprConst #full { pub attrs: Vec<Attribute>, pub const_token: Token![const], pub block: Block, } } ast_struct! { /// A `continue`, with an optional label. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprContinue #full { pub attrs: Vec<Attribute>, pub continue_token: Token![continue], pub label: Option<Lifetime>, } } ast_struct! { /// Access of a named struct field (`obj.k`) or unnamed tuple struct /// field (`obj.0`). #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct ExprField { pub attrs: Vec<Attribute>, pub base: Box<Expr>, pub dot_token: Token![.], pub member: Member, } } ast_struct! { /// A for loop: `for pat in expr { ... }`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprForLoop #full { pub attrs: Vec<Attribute>, pub label: Option<Label>, pub for_token: Token![for], pub pat: Box<Pat>, pub in_token: Token![in], pub expr: Box<Expr>, pub body: Block, } } ast_struct! { /// An expression contained within invisible delimiters. /// /// This variant is important for faithfully representing the precedence /// of expressions and is related to `None`-delimited spans in a /// `TokenStream`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprGroup { pub attrs: Vec<Attribute>, pub group_token: token::Group, pub expr: Box<Expr>, } } ast_struct! { /// An `if` expression with an optional `else` block: `if expr { ... } /// else { ... }`. /// /// The `else` branch expression may only be an `If` or `Block` /// expression, not any of the other types of expression. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprIf #full { pub attrs: Vec<Attribute>, pub if_token: Token![if], pub cond: Box<Expr>, pub then_branch: Block, pub else_branch: Option<(Token![else], Box<Expr>)>, } } ast_struct! { /// A square bracketed indexing expression: `vector[2]`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct ExprIndex { pub attrs: Vec<Attribute>, pub expr: Box<Expr>, pub bracket_token: token::Bracket, pub index: Box<Expr>, } } ast_struct! { /// The inferred value of a const generic argument, denoted `_`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprInfer #full { pub attrs: Vec<Attribute>, pub underscore_token: Token![_], } } ast_struct! { /// A `let` guard: `let Some(x) = opt`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct ExprLet #full { pub attrs: Vec<Attribute>, pub let_token: Token![let], pub pat: Box<Pat>, pub eq_token: Token![=], pub expr: Box<Expr>, } } ast_struct! { /// A literal in place of an expression: `1`, `"foo"`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct ExprLit { pub attrs: Vec<Attribute>, pub lit: Lit,