4175 lines · 138.5 KB · Rust
RawDownload
// 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.