diff options
Diffstat (limited to 'syn/src/expr.rs')
-rw-r--r-- | syn/src/expr.rs | 3236 |
1 files changed, 0 insertions, 3236 deletions
diff --git a/syn/src/expr.rs b/syn/src/expr.rs deleted file mode 100644 index 603dc32..0000000 --- a/syn/src/expr.rs +++ /dev/null @@ -1,3236 +0,0 @@ -use super::*; -use crate::punctuated::Punctuated; -#[cfg(feature = "extra-traits")] -use crate::tt::TokenStreamHelper; -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 if Syn is built with the `"derive"` or `"full"` - /// feature.* - /// - /// # 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`. - pub enum Expr #manual_extra_traits { - /// A slice literal expression: `[a, b, c, d]`. - Array(ExprArray), - - /// An assignment expression: `a = compute()`. - Assign(ExprAssign), - - /// A compound assignment expression: `counter += 1`. - AssignOp(ExprAssignOp), - - /// 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 box expression: `box f`. - Box(ExprBox), - - /// 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 `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), - - /// 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), - - /// 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 type ascription expression: `foo: f64`. - Type(ExprType), - - /// 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), - - #[doc(hidden)] - __Nonexhaustive, - } -} - -ast_struct! { - /// A slice literal expression: `[a, b, c, d]`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - 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()`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprAssign #full { - pub attrs: Vec<Attribute>, - pub left: Box<Expr>, - pub eq_token: Token![=], - pub right: Box<Expr>, - } -} - -ast_struct! { - /// A compound assignment expression: `counter += 1`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprAssignOp #full { - pub attrs: Vec<Attribute>, - pub left: Box<Expr>, - pub op: BinOp, - pub right: Box<Expr>, - } -} - -ast_struct! { - /// An async block: `async { ... }`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - 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`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - 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`. - /// - /// *This type is available if Syn is built with the `"derive"` or - /// `"full"` feature.* - pub struct ExprBinary { - pub attrs: Vec<Attribute>, - pub left: Box<Expr>, - pub op: BinOp, - pub right: Box<Expr>, - } -} - -ast_struct! { - /// A blocked scope: `{ ... }`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprBlock #full { - pub attrs: Vec<Attribute>, - pub label: Option<Label>, - pub block: Block, - } -} - -ast_struct! { - /// A box expression: `box f`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprBox #full { - pub attrs: Vec<Attribute>, - pub box_token: Token![box], - pub expr: Box<Expr>, - } -} - -ast_struct! { - /// A `break`, with an optional label to break and an optional - /// expression. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - 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)`. - /// - /// *This type is available if Syn is built with the `"derive"` or - /// `"full"` feature.* - 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`. - /// - /// *This type is available if Syn is built with the `"derive"` or - /// `"full"` feature.* - 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`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprClosure #full { - pub attrs: Vec<Attribute>, - pub asyncness: Option<Token![async]>, - pub movability: Option<Token![static]>, - 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 `continue`, with an optional label. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - 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`). - /// - /// *This type is available if Syn is built with the `"full"` feature.* - 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 { ... }`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprForLoop #full { - pub attrs: Vec<Attribute>, - pub label: Option<Label>, - pub for_token: Token![for], - pub pat: 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`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprGroup #full { - 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. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - 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]`. - /// - /// *This type is available if Syn is built with the `"derive"` or - /// `"full"` feature.* - pub struct ExprIndex { - pub attrs: Vec<Attribute>, - pub expr: Box<Expr>, - pub bracket_token: token::Bracket, - pub index: Box<Expr>, - } -} - -ast_struct! { - /// A `let` guard: `let Some(x) = opt`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprLet #full { - pub attrs: Vec<Attribute>, - pub let_token: Token![let], - pub pat: Pat, - pub eq_token: Token![=], - pub expr: Box<Expr>, - } -} - -ast_struct! { - /// A literal in place of an expression: `1`, `"foo"`. - /// - /// *This type is available if Syn is built with the `"derive"` or - /// `"full"` feature.* - pub struct ExprLit { - pub attrs: Vec<Attribute>, - pub lit: Lit, - } -} - -ast_struct! { - /// Conditionless loop: `loop { ... }`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprLoop #full { - pub attrs: Vec<Attribute>, - pub label: Option<Label>, - pub loop_token: Token![loop], - pub body: Block, - } -} - -ast_struct! { - /// A macro invocation expression: `format!("{}", q)`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprMacro #full { - pub attrs: Vec<Attribute>, - pub mac: Macro, - } -} - -ast_struct! { - /// A `match` expression: `match n { Some(n) => {}, None => {} }`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprMatch #full { - pub attrs: Vec<Attribute>, - pub match_token: Token![match], - pub expr: Box<Expr>, - pub brace_token: token::Brace, - pub arms: Vec<Arm>, - } -} - -ast_struct! { - /// A method call expression: `x.foo::<T>(a, b)`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprMethodCall #full { - pub attrs: Vec<Attribute>, - pub receiver: Box<Expr>, - pub dot_token: Token![.], - pub method: Ident, - pub turbofish: Option<MethodTurbofish>, - pub paren_token: token::Paren, - pub args: Punctuated<Expr, Token![,]>, - } -} - -ast_struct! { - /// A parenthesized expression: `(a + b)`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprParen { - pub attrs: Vec<Attribute>, - pub paren_token: token::Paren, - pub expr: Box<Expr>, - } -} - -ast_struct! { - /// 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. - /// - /// *This type is available if Syn is built with the `"derive"` or - /// `"full"` feature.* - pub struct ExprPath { - pub attrs: Vec<Attribute>, - pub qself: Option<QSelf>, - pub path: Path, - } -} - -ast_struct! { - /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprRange #full { - pub attrs: Vec<Attribute>, - pub from: Option<Box<Expr>>, - pub limits: RangeLimits, - pub to: Option<Box<Expr>>, - } -} - -ast_struct! { - /// A referencing operation: `&a` or `&mut a`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprReference #full { - pub attrs: Vec<Attribute>, - pub and_token: Token![&], - pub raw: Reserved, - pub mutability: Option<Token![mut]>, - pub expr: Box<Expr>, - } -} - -ast_struct! { - /// An array literal constructed from one repeated element: `[0u8; N]`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprRepeat #full { - pub attrs: Vec<Attribute>, - pub bracket_token: token::Bracket, - pub expr: Box<Expr>, - pub semi_token: Token![;], - pub len: Box<Expr>, - } -} - -ast_struct! { - /// A `return`, with an optional value to be returned. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprReturn #full { - pub attrs: Vec<Attribute>, - pub return_token: Token![return], - pub expr: Option<Box<Expr>>, - } -} - -ast_struct! { - /// 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 }`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprStruct #full { - pub attrs: Vec<Attribute>, - pub path: Path, - pub brace_token: token::Brace, - pub fields: Punctuated<FieldValue, Token![,]>, - pub dot2_token: Option<Token![..]>, - pub rest: Option<Box<Expr>>, - } -} - -ast_struct! { - /// A try-expression: `expr?`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprTry #full { - pub attrs: Vec<Attribute>, - pub expr: Box<Expr>, - pub question_token: Token![?], - } -} - -ast_struct! { - /// A try block: `try { ... }`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprTryBlock #full { - pub attrs: Vec<Attribute>, - pub try_token: Token![try], - pub block: Block, - } -} - -ast_struct! { - /// A tuple expression: `(a, b, c, d)`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprTuple #full { - pub attrs: Vec<Attribute>, - pub paren_token: token::Paren, - pub elems: Punctuated<Expr, Token![,]>, - } -} - -ast_struct! { - /// A type ascription expression: `foo: f64`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprType #full { - pub attrs: Vec<Attribute>, - pub expr: Box<Expr>, - pub colon_token: Token![:], - pub ty: Box<Type>, - } -} - -ast_struct! { - /// A unary operation: `!x`, `*x`. - /// - /// *This type is available if Syn is built with the `"derive"` or - /// `"full"` feature.* - pub struct ExprUnary { - pub attrs: Vec<Attribute>, - pub op: UnOp, - pub expr: Box<Expr>, - } -} - -ast_struct! { - /// An unsafe block: `unsafe { ... }`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprUnsafe #full { - pub attrs: Vec<Attribute>, - pub unsafe_token: Token![unsafe], - pub block: Block, - } -} - -ast_struct! { - /// A while loop: `while expr { ... }`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprWhile #full { - pub attrs: Vec<Attribute>, - pub label: Option<Label>, - pub while_token: Token![while], - pub cond: Box<Expr>, - pub body: Block, - } -} - -ast_struct! { - /// A yield expression: `yield expr`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct ExprYield #full { - pub attrs: Vec<Attribute>, - pub yield_token: Token![yield], - pub expr: Option<Box<Expr>>, - } -} - -#[cfg(feature = "extra-traits")] -impl Eq for Expr {} - -#[cfg(feature = "extra-traits")] -impl PartialEq for Expr { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - (Expr::Array(this), Expr::Array(other)) => this == other, - (Expr::Assign(this), Expr::Assign(other)) => this == other, - (Expr::AssignOp(this), Expr::AssignOp(other)) => this == other, - (Expr::Async(this), Expr::Async(other)) => this == other, - (Expr::Await(this), Expr::Await(other)) => this == other, - (Expr::Binary(this), Expr::Binary(other)) => this == other, - (Expr::Block(this), Expr::Block(other)) => this == other, - (Expr::Box(this), Expr::Box(other)) => this == other, - (Expr::Break(this), Expr::Break(other)) => this == other, - (Expr::Call(this), Expr::Call(other)) => this == other, - (Expr::Cast(this), Expr::Cast(other)) => this == other, - (Expr::Closure(this), Expr::Closure(other)) => this == other, - (Expr::Continue(this), Expr::Continue(other)) => this == other, - (Expr::Field(this), Expr::Field(other)) => this == other, - (Expr::ForLoop(this), Expr::ForLoop(other)) => this == other, - (Expr::Group(this), Expr::Group(other)) => this == other, - (Expr::If(this), Expr::If(other)) => this == other, - (Expr::Index(this), Expr::Index(other)) => this == other, - (Expr::Let(this), Expr::Let(other)) => this == other, - (Expr::Lit(this), Expr::Lit(other)) => this == other, - (Expr::Loop(this), Expr::Loop(other)) => this == other, - (Expr::Macro(this), Expr::Macro(other)) => this == other, - (Expr::Match(this), Expr::Match(other)) => this == other, - (Expr::MethodCall(this), Expr::MethodCall(other)) => this == other, - (Expr::Paren(this), Expr::Paren(other)) => this == other, - (Expr::Path(this), Expr::Path(other)) => this == other, - (Expr::Range(this), Expr::Range(other)) => this == other, - (Expr::Reference(this), Expr::Reference(other)) => this == other, - (Expr::Repeat(this), Expr::Repeat(other)) => this == other, - (Expr::Return(this), Expr::Return(other)) => this == other, - (Expr::Struct(this), Expr::Struct(other)) => this == other, - (Expr::Try(this), Expr::Try(other)) => this == other, - (Expr::TryBlock(this), Expr::TryBlock(other)) => this == other, - (Expr::Tuple(this), Expr::Tuple(other)) => this == other, - (Expr::Type(this), Expr::Type(other)) => this == other, - (Expr::Unary(this), Expr::Unary(other)) => this == other, - (Expr::Unsafe(this), Expr::Unsafe(other)) => this == other, - (Expr::Verbatim(this), Expr::Verbatim(other)) => { - TokenStreamHelper(this) == TokenStreamHelper(other) - } - (Expr::While(this), Expr::While(other)) => this == other, - (Expr::Yield(this), Expr::Yield(other)) => this == other, - _ => false, - } - } -} - -#[cfg(feature = "extra-traits")] -impl Hash for Expr { - fn hash<H>(&self, hash: &mut H) - where - H: Hasher, - { - match self { - Expr::Array(expr) => { - hash.write_u8(0); - expr.hash(hash); - } - Expr::Assign(expr) => { - hash.write_u8(1); - expr.hash(hash); - } - Expr::AssignOp(expr) => { - hash.write_u8(2); - expr.hash(hash); - } - Expr::Async(expr) => { - hash.write_u8(3); - expr.hash(hash); - } - Expr::Await(expr) => { - hash.write_u8(4); - expr.hash(hash); - } - Expr::Binary(expr) => { - hash.write_u8(5); - expr.hash(hash); - } - Expr::Block(expr) => { - hash.write_u8(6); - expr.hash(hash); - } - Expr::Box(expr) => { - hash.write_u8(7); - expr.hash(hash); - } - Expr::Break(expr) => { - hash.write_u8(8); - expr.hash(hash); - } - Expr::Call(expr) => { - hash.write_u8(9); - expr.hash(hash); - } - Expr::Cast(expr) => { - hash.write_u8(10); - expr.hash(hash); - } - Expr::Closure(expr) => { - hash.write_u8(11); - expr.hash(hash); - } - Expr::Continue(expr) => { - hash.write_u8(12); - expr.hash(hash); - } - Expr::Field(expr) => { - hash.write_u8(13); - expr.hash(hash); - } - Expr::ForLoop(expr) => { - hash.write_u8(14); - expr.hash(hash); - } - Expr::Group(expr) => { - hash.write_u8(15); - expr.hash(hash); - } - Expr::If(expr) => { - hash.write_u8(16); - expr.hash(hash); - } - Expr::Index(expr) => { - hash.write_u8(17); - expr.hash(hash); - } - Expr::Let(expr) => { - hash.write_u8(18); - expr.hash(hash); - } - Expr::Lit(expr) => { - hash.write_u8(19); - expr.hash(hash); - } - Expr::Loop(expr) => { - hash.write_u8(20); - expr.hash(hash); - } - Expr::Macro(expr) => { - hash.write_u8(21); - expr.hash(hash); - } - Expr::Match(expr) => { - hash.write_u8(22); - expr.hash(hash); - } - Expr::MethodCall(expr) => { - hash.write_u8(23); - expr.hash(hash); - } - Expr::Paren(expr) => { - hash.write_u8(24); - expr.hash(hash); - } - Expr::Path(expr) => { - hash.write_u8(25); - expr.hash(hash); - } - Expr::Range(expr) => { - hash.write_u8(26); - expr.hash(hash); - } - Expr::Reference(expr) => { - hash.write_u8(27); - expr.hash(hash); - } - Expr::Repeat(expr) => { - hash.write_u8(28); - expr.hash(hash); - } - Expr::Return(expr) => { - hash.write_u8(29); - expr.hash(hash); - } - Expr::Struct(expr) => { - hash.write_u8(30); - expr.hash(hash); - } - Expr::Try(expr) => { - hash.write_u8(31); - expr.hash(hash); - } - Expr::TryBlock(expr) => { - hash.write_u8(32); - expr.hash(hash); - } - Expr::Tuple(expr) => { - hash.write_u8(33); - expr.hash(hash); - } - Expr::Type(expr) => { - hash.write_u8(34); - expr.hash(hash); - } - Expr::Unary(expr) => { - hash.write_u8(35); - expr.hash(hash); - } - Expr::Unsafe(expr) => { - hash.write_u8(36); - expr.hash(hash); - } - Expr::Verbatim(expr) => { - hash.write_u8(37); - TokenStreamHelper(expr).hash(hash); - } - Expr::While(expr) => { - hash.write_u8(38); - expr.hash(hash); - } - Expr::Yield(expr) => { - hash.write_u8(39); - expr.hash(hash); - } - Expr::__Nonexhaustive => unreachable!(), - } - } -} - -impl Expr { - #[cfg(all(feature = "parsing", feature = "full"))] - pub(crate) fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> { - match self { - Expr::Box(ExprBox { attrs, .. }) - | Expr::Array(ExprArray { attrs, .. }) - | Expr::Call(ExprCall { attrs, .. }) - | Expr::MethodCall(ExprMethodCall { attrs, .. }) - | Expr::Tuple(ExprTuple { attrs, .. }) - | Expr::Binary(ExprBinary { attrs, .. }) - | Expr::Unary(ExprUnary { attrs, .. }) - | Expr::Lit(ExprLit { attrs, .. }) - | Expr::Cast(ExprCast { attrs, .. }) - | Expr::Type(ExprType { attrs, .. }) - | Expr::Let(ExprLet { attrs, .. }) - | Expr::If(ExprIf { attrs, .. }) - | Expr::While(ExprWhile { attrs, .. }) - | Expr::ForLoop(ExprForLoop { attrs, .. }) - | Expr::Loop(ExprLoop { attrs, .. }) - | Expr::Match(ExprMatch { attrs, .. }) - | Expr::Closure(ExprClosure { attrs, .. }) - | Expr::Unsafe(ExprUnsafe { attrs, .. }) - | Expr::Block(ExprBlock { attrs, .. }) - | Expr::Assign(ExprAssign { attrs, .. }) - | Expr::AssignOp(ExprAssignOp { attrs, .. }) - | Expr::Field(ExprField { attrs, .. }) - | Expr::Index(ExprIndex { attrs, .. }) - | Expr::Range(ExprRange { attrs, .. }) - | Expr::Path(ExprPath { attrs, .. }) - | Expr::Reference(ExprReference { attrs, .. }) - | Expr::Break(ExprBreak { attrs, .. }) - | Expr::Continue(ExprContinue { attrs, .. }) - | Expr::Return(ExprReturn { attrs, .. }) - | Expr::Macro(ExprMacro { attrs, .. }) - | Expr::Struct(ExprStruct { attrs, .. }) - | Expr::Repeat(ExprRepeat { attrs, .. }) - | Expr::Paren(ExprParen { attrs, .. }) - | Expr::Group(ExprGroup { attrs, .. }) - | Expr::Try(ExprTry { attrs, .. }) - | Expr::Async(ExprAsync { attrs, .. }) - | Expr::Await(ExprAwait { attrs, .. }) - | Expr::TryBlock(ExprTryBlock { attrs, .. }) - | Expr::Yield(ExprYield { attrs, .. }) => mem::replace(attrs, new), - Expr::Verbatim(_) => Vec::new(), - Expr::__Nonexhaustive => unreachable!(), - } - } -} - -ast_enum! { - /// A struct or tuple struct field accessed in a struct literal or field - /// expression. - /// - /// *This type is available if Syn is built with the `"derive"` or `"full"` - /// feature.* - #[derive(Eq, PartialEq, Hash)] - pub enum Member #manual_extra_traits { - /// A named field like `self.x`. - Named(Ident), - /// An unnamed field like `self.0`. - Unnamed(Index), - } -} - -#[cfg(feature = "printing")] -impl IdentFragment for Member { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - match self { - Member::Named(m) => Display::fmt(m, formatter), - Member::Unnamed(m) => Display::fmt(&m.index, formatter), - } - } - - fn span(&self) -> Option<Span> { - match self { - Member::Named(m) => Some(m.span()), - Member::Unnamed(m) => Some(m.span), - } - } -} - -ast_struct! { - /// The index of an unnamed tuple struct field. - /// - /// *This type is available if Syn is built with the `"derive"` or `"full"` - /// feature.* - pub struct Index #manual_extra_traits { - pub index: u32, - pub span: Span, - } -} - -impl From<usize> for Index { - fn from(index: usize) -> Index { - assert!(index < u32::max_value() as usize); - Index { - index: index as u32, - span: Span::call_site(), - } - } -} - -impl Eq for Index {} - -impl PartialEq for Index { - fn eq(&self, other: &Self) -> bool { - self.index == other.index - } -} - -impl Hash for Index { - fn hash<H: Hasher>(&self, state: &mut H) { - self.index.hash(state); - } -} - -#[cfg(feature = "printing")] -impl IdentFragment for Index { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - Display::fmt(&self.index, formatter) - } - - fn span(&self) -> Option<Span> { - Some(self.span) - } -} - -#[cfg(feature = "full")] -ast_struct! { - #[derive(Default)] - pub struct Reserved { - _private: (), - } -} - -#[cfg(feature = "full")] -ast_struct! { - /// The `::<>` explicit type parameters passed to a method call: - /// `parse::<u64>()`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct MethodTurbofish { - pub colon2_token: Token![::], - pub lt_token: Token![<], - pub args: Punctuated<GenericMethodArgument, Token![,]>, - pub gt_token: Token![>], - } -} - -#[cfg(feature = "full")] -ast_enum! { - /// An individual generic argument to a method, like `T`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub enum GenericMethodArgument { - /// A type argument. - Type(Type), - /// A const expression. Must be inside of a block. - /// - /// NOTE: Identity expressions are represented as Type arguments, as - /// they are indistinguishable syntactically. - Const(Expr), - } -} - -#[cfg(feature = "full")] -ast_struct! { - /// A field-value pair in a struct literal. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct FieldValue { - /// Attributes tagged on the field. - pub attrs: Vec<Attribute>, - - /// Name or index of the field. - pub member: Member, - - /// The colon in `Struct { x: x }`. If written in shorthand like - /// `Struct { x }`, there is no colon. - pub colon_token: Option<Token![:]>, - - /// Value of the field. - pub expr: Expr, - } -} - -#[cfg(feature = "full")] -ast_struct! { - /// A lifetime labeling a `for`, `while`, or `loop`. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct Label { - pub name: Lifetime, - pub colon_token: Token![:], - } -} - -#[cfg(feature = "full")] -ast_struct! { - /// One arm of a `match` expression: `0...10 => { return true; }`. - /// - /// As in: - /// - /// ``` - /// # fn f() -> bool { - /// # let n = 0; - /// match n { - /// 0...10 => { - /// return true; - /// } - /// // ... - /// # _ => {} - /// } - /// # false - /// # } - /// ``` - /// - /// *This type is available if Syn is built with the `"full"` feature.* - pub struct Arm { - pub attrs: Vec<Attribute>, - pub pat: Pat, - pub guard: Option<(Token![if], Box<Expr>)>, - pub fat_arrow_token: Token![=>], - pub body: Box<Expr>, - pub comma: Option<Token![,]>, - } -} - -#[cfg(feature = "full")] -ast_enum! { - /// Limit types of a range, inclusive or exclusive. - /// - /// *This type is available if Syn is built with the `"full"` feature.* - #[cfg_attr(feature = "clone-impls", derive(Copy))] - pub enum RangeLimits { - /// Inclusive at the beginning, exclusive at the end. - HalfOpen(Token![..]), - /// Inclusive at the beginning and end. - Closed(Token![..=]), - } -} - -#[cfg(any(feature = "parsing", feature = "printing"))] -#[cfg(feature = "full")] -pub(crate) fn requires_terminator(expr: &Expr) -> bool { - // see https://github.com/rust-lang/rust/blob/eb8f2586e/src/libsyntax/parse/classify.rs#L17-L37 - match *expr { - Expr::Unsafe(..) - | Expr::Block(..) - | Expr::If(..) - | Expr::Match(..) - | Expr::While(..) - | Expr::Loop(..) - | Expr::ForLoop(..) - | Expr::Async(..) - | Expr::TryBlock(..) => false, - _ => true, - } -} - -#[cfg(feature = "parsing")] -pub(crate) mod parsing { - use super::*; - - use crate::parse::discouraged::Speculative; - use crate::parse::{Parse, ParseStream, Result}; - use crate::path; - - // When we're parsing expressions which occur before blocks, like in an if - // statement's condition, we cannot parse a struct literal. - // - // Struct literals are ambiguous in certain positions - // https://github.com/rust-lang/rfcs/pull/92 - #[derive(Copy, Clone)] - pub struct AllowStruct(bool); - - #[derive(Copy, Clone, PartialEq, PartialOrd)] - enum Precedence { - Any, - Assign, - Range, - Or, - And, - Compare, - BitOr, - BitXor, - BitAnd, - Shift, - Arithmetic, - Term, - Cast, - } - - impl Precedence { - fn of(op: &BinOp) -> Self { - match *op { - BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic, - BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term, - BinOp::And(_) => Precedence::And, - BinOp::Or(_) => Precedence::Or, - BinOp::BitXor(_) => Precedence::BitXor, - BinOp::BitAnd(_) => Precedence::BitAnd, - BinOp::BitOr(_) => Precedence::BitOr, - BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift, - BinOp::Eq(_) - | BinOp::Lt(_) - | BinOp::Le(_) - | BinOp::Ne(_) - | BinOp::Ge(_) - | BinOp::Gt(_) => Precedence::Compare, - BinOp::AddEq(_) - | BinOp::SubEq(_) - | BinOp::MulEq(_) - | BinOp::DivEq(_) - | BinOp::RemEq(_) - | BinOp::BitXorEq(_) - | BinOp::BitAndEq(_) - | BinOp::BitOrEq(_) - | BinOp::ShlEq(_) - | BinOp::ShrEq(_) => Precedence::Assign, - } - } - } - - impl Parse for Expr { - fn parse(input: ParseStream) -> Result<Self> { - ambiguous_expr(input, AllowStruct(true)) - } - } - - #[cfg(feature = "full")] - fn expr_no_struct(input: ParseStream) -> Result<Expr> { - ambiguous_expr(input, AllowStruct(false)) - } - - #[cfg(feature = "full")] - fn parse_expr( - input: ParseStream, - mut lhs: Expr, - allow_struct: AllowStruct, - base: Precedence, - ) -> Result<Expr> { - loop { - if input - .fork() - .parse::<BinOp>() - .ok() - .map_or(false, |op| Precedence::of(&op) >= base) - { - let op: BinOp = input.parse()?; - let precedence = Precedence::of(&op); - let mut rhs = unary_expr(input, allow_struct)?; - loop { - let next = peek_precedence(input); - if next > precedence || next == precedence && precedence == Precedence::Assign { - rhs = parse_expr(input, rhs, allow_struct, next)?; - } else { - break; - } - } - lhs = if precedence == Precedence::Assign { - Expr::AssignOp(ExprAssignOp { - attrs: Vec::new(), - left: Box::new(lhs), - op, - right: Box::new(rhs), - }) - } else { - Expr::Binary(ExprBinary { - attrs: Vec::new(), - left: Box::new(lhs), - op, - right: Box::new(rhs), - }) - }; - } else if Precedence::Assign >= base - && input.peek(Token![=]) - && !input.peek(Token![==]) - && !input.peek(Token![=>]) - { - let eq_token: Token![=] = input.parse()?; - let mut rhs = unary_expr(input, allow_struct)?; - loop { - let next = peek_precedence(input); - if next >= Precedence::Assign { - rhs = parse_expr(input, rhs, allow_struct, next)?; - } else { - break; - } - } - lhs = Expr::Assign(ExprAssign { - attrs: Vec::new(), - left: Box::new(lhs), - eq_token, - right: Box::new(rhs), - }); - } else if Precedence::Range >= base && input.peek(Token![..]) { - let limits: RangeLimits = input.parse()?; - let rhs = if input.is_empty() - || input.peek(Token![,]) - || input.peek(Token![;]) - || !allow_struct.0 && input.peek(token::Brace) - { - None - } else { - let mut rhs = unary_expr(input, allow_struct)?; - loop { - let next = peek_precedence(input); - if next > Precedence::Range { - rhs = parse_expr(input, rhs, allow_struct, next)?; - } else { - break; - } - } - Some(rhs) - }; - lhs = Expr::Range(ExprRange { - attrs: Vec::new(), - from: Some(Box::new(lhs)), - limits, - to: rhs.map(Box::new), - }); - } else if Precedence::Cast >= base && input.peek(Token![as]) { - let as_token: Token![as] = input.parse()?; - let ty = input.call(Type::without_plus)?; - lhs = Expr::Cast(ExprCast { - attrs: Vec::new(), - expr: Box::new(lhs), - as_token, - ty: Box::new(ty), - }); - } else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) { - let colon_token: Token![:] = input.parse()?; - let ty = input.call(Type::without_plus)?; - lhs = Expr::Type(ExprType { - attrs: Vec::new(), - expr: Box::new(lhs), - colon_token, - ty: Box::new(ty), - }); - } else { - break; - } - } - Ok(lhs) - } - - #[cfg(not(feature = "full"))] - fn parse_expr( - input: ParseStream, - mut lhs: Expr, - allow_struct: AllowStruct, - base: Precedence, - ) -> Result<Expr> { - loop { - if input - .fork() - .parse::<BinOp>() - .ok() - .map_or(false, |op| Precedence::of(&op) >= base) - { - let op: BinOp = input.parse()?; - let precedence = Precedence::of(&op); - let mut rhs = unary_expr(input, allow_struct)?; - loop { - let next = peek_precedence(input); - if next > precedence || next == precedence && precedence == Precedence::Assign { - rhs = parse_expr(input, rhs, allow_struct, next)?; - } else { - break; - } - } - lhs = Expr::Binary(ExprBinary { - attrs: Vec::new(), - left: Box::new(lhs), - op, - right: Box::new(rhs), - }); - } else if Precedence::Cast >= base && input.peek(Token![as]) { - let as_token: Token![as] = input.parse()?; - let ty = input.call(Type::without_plus)?; - lhs = Expr::Cast(ExprCast { - attrs: Vec::new(), - expr: Box::new(lhs), - as_token, - ty: Box::new(ty), - }); - } else { - break; - } - } - Ok(lhs) - } - - fn peek_precedence(input: ParseStream) -> Precedence { - if let Ok(op) = input.fork().parse() { - Precedence::of(&op) - } else if input.peek(Token![=]) && !input.peek(Token![=>]) { - Precedence::Assign - } else if input.peek(Token![..]) { - Precedence::Range - } else if input.peek(Token![as]) || input.peek(Token![:]) && !input.peek(Token![::]) { - Precedence::Cast - } else { - Precedence::Any - } - } - - // Parse an arbitrary expression. - fn ambiguous_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> { - let lhs = unary_expr(input, allow_struct)?; - parse_expr(input, lhs, allow_struct, Precedence::Any) - } - - // <UnOp> <trailer> - // & <trailer> - // &mut <trailer> - // box <trailer> - #[cfg(feature = "full")] - fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> { - let ahead = input.fork(); - let attrs = ahead.call(Attribute::parse_outer)?; - if ahead.peek(Token![&]) - || ahead.peek(Token![box]) - || ahead.peek(Token![*]) - || ahead.peek(Token![!]) - || ahead.peek(Token![-]) - { - input.advance_to(&ahead); - if input.peek(Token![&]) { - Ok(Expr::Reference(ExprReference { - attrs, - and_token: input.parse()?, - raw: Reserved::default(), - mutability: input.parse()?, - expr: Box::new(unary_expr(input, allow_struct)?), - })) - } else if input.peek(Token![box]) { - Ok(Expr::Box(ExprBox { - attrs, - box_token: input.parse()?, - expr: Box::new(unary_expr(input, allow_struct)?), - })) - } else { - Ok(Expr::Unary(ExprUnary { - attrs, - op: input.parse()?, - expr: Box::new(unary_expr(input, allow_struct)?), - })) - } - } else { - trailer_expr(input, allow_struct) - } - } - - #[cfg(not(feature = "full"))] - fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> { - let ahead = input.fork(); - let attrs = ahead.call(Attribute::parse_outer)?; - if ahead.peek(Token![*]) || ahead.peek(Token![!]) || ahead.peek(Token![-]) { - input.advance_to(&ahead); - Ok(Expr::Unary(ExprUnary { - attrs, - op: input.parse()?, - expr: Box::new(unary_expr(input, allow_struct)?), - })) - } else { - trailer_expr(input, allow_struct) - } - } - - // <atom> (..<args>) ... - // <atom> . <ident> (..<args>) ... - // <atom> . <ident> ... - // <atom> . <lit> ... - // <atom> [ <expr> ] ... - // <atom> ? ... - #[cfg(feature = "full")] - fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> { - if input.peek(token::Group) { - return input.call(expr_group).map(Expr::Group); - } - - let outer_attrs = input.call(Attribute::parse_outer)?; - - let atom = atom_expr(input, allow_struct)?; - let mut e = trailer_helper(input, atom)?; - - let inner_attrs = e.replace_attrs(Vec::new()); - let attrs = private::attrs(outer_attrs, inner_attrs); - e.replace_attrs(attrs); - Ok(e) - } - - #[cfg(feature = "full")] - fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> { - loop { - if input.peek(token::Paren) { - let content; - e = Expr::Call(ExprCall { - attrs: Vec::new(), - func: Box::new(e), - paren_token: parenthesized!(content in input), - args: content.parse_terminated(Expr::parse)?, - }); - } else if input.peek(Token![.]) && !input.peek(Token![..]) { - let dot_token: Token![.] = input.parse()?; - - if input.peek(token::Await) { - e = Expr::Await(ExprAwait { - attrs: Vec::new(), - base: Box::new(e), - dot_token, - await_token: input.parse()?, - }); - continue; - } - - let member: Member = input.parse()?; - let turbofish = if member.is_named() && input.peek(Token![::]) { - Some(MethodTurbofish { - colon2_token: input.parse()?, - lt_token: input.parse()?, - args: { - let mut args = Punctuated::new(); - loop { - if input.peek(Token![>]) { - break; - } - let value = input.call(generic_method_argument)?; - args.push_value(value); - if input.peek(Token![>]) { - break; - } - let punct = input.parse()?; - args.push_punct(punct); - } - args - }, - gt_token: input.parse()?, - }) - } else { - None - }; - - if turbofish.is_some() || input.peek(token::Paren) { - if let Member::Named(method) = member { - let content; - e = Expr::MethodCall(ExprMethodCall { - attrs: Vec::new(), - receiver: Box::new(e), - dot_token, - method, - turbofish, - paren_token: parenthesized!(content in input), - args: content.parse_terminated(Expr::parse)?, - }); - continue; - } - } - - e = Expr::Field(ExprField { - attrs: Vec::new(), - base: Box::new(e), - dot_token, - member, - }); - } else if input.peek(token::Bracket) { - let content; - e = Expr::Index(ExprIndex { - attrs: Vec::new(), - expr: Box::new(e), - bracket_token: bracketed!(content in input), - index: content.parse()?, - }); - } else if input.peek(Token![?]) { - e = Expr::Try(ExprTry { - attrs: Vec::new(), - expr: Box::new(e), - question_token: input.parse()?, - }); - } else { - break; - } - } - Ok(e) - } - - #[cfg(not(feature = "full"))] - fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> { - let mut e = atom_expr(input, allow_struct)?; - - loop { - if input.peek(token::Paren) { - let content; - e = Expr::Call(ExprCall { - attrs: Vec::new(), - func: Box::new(e), - paren_token: parenthesized!(content in input), - args: content.parse_terminated(Expr::parse)?, - }); - } else if input.peek(Token![.]) && !input.peek(Token![..]) && !input.peek2(token::Await) - { - e = Expr::Field(ExprField { - attrs: Vec::new(), - base: Box::new(e), - dot_token: input.parse()?, - member: input.parse()?, - }); - } else if input.peek(token::Bracket) { - let content; - e = Expr::Index(ExprIndex { - attrs: Vec::new(), - expr: Box::new(e), - bracket_token: bracketed!(content in input), - index: content.parse()?, - }); - } else { - break; - } - } - - Ok(e) - } - - // Parse all atomic expressions which don't have to worry about precedence - // interactions, as they are fully contained. - #[cfg(feature = "full")] - fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> { - if input.peek(token::Group) { - input.call(expr_group).map(Expr::Group) - } else if input.peek(Lit) { - input.parse().map(Expr::Lit) - } else if input.peek(Token![async]) - && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace)) - { - input.call(expr_async).map(Expr::Async) - } else if input.peek(Token![try]) && input.peek2(token::Brace) { - input.call(expr_try_block).map(Expr::TryBlock) - } else if input.peek(Token![|]) - || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move])) - || input.peek(Token![static]) - || input.peek(Token![move]) - { - expr_closure(input, allow_struct).map(Expr::Closure) - } else if input.peek(Ident) - || input.peek(Token![::]) - || input.peek(Token![<]) - || input.peek(Token![self]) - || input.peek(Token![Self]) - || input.peek(Token![super]) - || input.peek(Token![extern]) - || input.peek(Token![crate]) - { - path_or_macro_or_struct(input, allow_struct) - } else if input.peek(token::Paren) { - paren_or_tuple(input) - } else if input.peek(Token![break]) { - expr_break(input, allow_struct).map(Expr::Break) - } else if input.peek(Token![continue]) { - input.call(expr_continue).map(Expr::Continue) - } else if input.peek(Token![return]) { - expr_ret(input, allow_struct).map(Expr::Return) - } else if input.peek(token::Bracket) { - array_or_repeat(input) - } else if input.peek(Token![let]) { - input.call(expr_let).map(Expr::Let) - } else if input.peek(Token![if]) { - input.parse().map(Expr::If) - } else if input.peek(Token![while]) { - input.parse().map(Expr::While) - } else if input.peek(Token![for]) { - input.parse().map(Expr::ForLoop) - } else if input.peek(Token![loop]) { - input.parse().map(Expr::Loop) - } else if input.peek(Token![match]) { - input.parse().map(Expr::Match) - } else if input.peek(Token![yield]) { - input.call(expr_yield).map(Expr::Yield) - } else if input.peek(Token![unsafe]) { - input.call(expr_unsafe).map(Expr::Unsafe) - } else if input.peek(token::Brace) { - input.call(expr_block).map(Expr::Block) - } else if input.peek(Token![..]) { - expr_range(input, allow_struct).map(Expr::Range) - } else if input.peek(Lifetime) { - let the_label: Label = input.parse()?; - let mut expr = if input.peek(Token![while]) { - Expr::While(input.parse()?) - } else if input.peek(Token![for]) { - Expr::ForLoop(input.parse()?) - } else if input.peek(Token![loop]) { - Expr::Loop(input.parse()?) - } else if input.peek(token::Brace) { - Expr::Block(input.call(expr_block)?) - } else { - return Err(input.error("expected loop or block expression")); - }; - match &mut expr { - Expr::While(ExprWhile { label, .. }) - | Expr::ForLoop(ExprForLoop { label, .. }) - | Expr::Loop(ExprLoop { label, .. }) - | Expr::Block(ExprBlock { label, .. }) => *label = Some(the_label), - _ => unreachable!(), - } - Ok(expr) - } else { - Err(input.error("expected expression")) - } - } - - #[cfg(not(feature = "full"))] - fn atom_expr(input: ParseStream, _allow_struct: AllowStruct) -> Result<Expr> { - if input.peek(Lit) { - input.parse().map(Expr::Lit) - } else if input.peek(token::Paren) { - input.call(expr_paren).map(Expr::Paren) - } else if input.peek(Ident) - || input.peek(Token![::]) - || input.peek(Token![<]) - || input.peek(Token![self]) - || input.peek(Token![Self]) - || input.peek(Token![super]) - || input.peek(Token![extern]) - || input.peek(Token![crate]) - { - input.parse().map(Expr::Path) - } else { - Err(input.error("unsupported expression; enable syn's features=[\"full\"]")) - } - } - - #[cfg(feature = "full")] - fn path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> { - let expr: ExprPath = input.parse()?; - if expr.qself.is_some() { - return Ok(Expr::Path(expr)); - } - - if input.peek(Token![!]) && !input.peek(Token![!=]) { - let mut contains_arguments = false; - for segment in &expr.path.segments { - match segment.arguments { - PathArguments::None => {} - PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => { - contains_arguments = true; - } - } - } - - if !contains_arguments { - let bang_token: Token![!] = input.parse()?; - let (delimiter, tokens) = mac::parse_delimiter(input)?; - return Ok(Expr::Macro(ExprMacro { - attrs: Vec::new(), - mac: Macro { - path: expr.path, - bang_token, - delimiter, - tokens, - }, - })); - } - } - - if allow_struct.0 && input.peek(token::Brace) { - let outer_attrs = Vec::new(); - expr_struct_helper(input, outer_attrs, expr.path).map(Expr::Struct) - } else { - Ok(Expr::Path(expr)) - } - } - - #[cfg(feature = "full")] - fn paren_or_tuple(input: ParseStream) -> Result<Expr> { - let content; - let paren_token = parenthesized!(content in input); - let inner_attrs = content.call(Attribute::parse_inner)?; - if content.is_empty() { - return Ok(Expr::Tuple(ExprTuple { - attrs: inner_attrs, - paren_token, - elems: Punctuated::new(), - })); - } - - let first: Expr = content.parse()?; - if content.is_empty() { - return Ok(Expr::Paren(ExprParen { - attrs: inner_attrs, - paren_token, - expr: Box::new(first), - })); - } - - let mut elems = Punctuated::new(); - elems.push_value(first); - while !content.is_empty() { - let punct = content.parse()?; - elems.push_punct(punct); - if content.is_empty() { - break; - } - let value = content.parse()?; - elems.push_value(value); - } - Ok(Expr::Tuple(ExprTuple { - attrs: inner_attrs, - paren_token, - elems, - })) - } - - #[cfg(feature = "full")] - fn array_or_repeat(input: ParseStream) -> Result<Expr> { - let content; - let bracket_token = bracketed!(content in input); - let inner_attrs = content.call(Attribute::parse_inner)?; - if content.is_empty() { - return Ok(Expr::Array(ExprArray { - attrs: inner_attrs, - bracket_token, - elems: Punctuated::new(), - })); - } - - let first: Expr = content.parse()?; - if content.is_empty() || content.peek(Token![,]) { - let mut elems = Punctuated::new(); - elems.push_value(first); - while !content.is_empty() { - let punct = content.parse()?; - elems.push_punct(punct); - if content.is_empty() { - break; - } - let value = content.parse()?; - elems.push_value(value); - } - Ok(Expr::Array(ExprArray { - attrs: inner_attrs, - bracket_token, - elems, - })) - } else if content.peek(Token![;]) { - let semi_token: Token![;] = content.parse()?; - let len: Expr = content.parse()?; - Ok(Expr::Repeat(ExprRepeat { - attrs: inner_attrs, - bracket_token, - expr: Box::new(first), - semi_token, - len: Box::new(len), - })) - } else { - Err(content.error("expected `,` or `;`")) - } - } - - #[cfg(feature = "full")] - pub(crate) fn expr_early(input: ParseStream) -> Result<Expr> { - let mut attrs = input.call(Attribute::parse_outer)?; - let mut expr = if input.peek(Token![if]) { - Expr::If(input.parse()?) - } else if input.peek(Token![while]) { - Expr::While(input.parse()?) - } else if input.peek(Token![for]) { - Expr::ForLoop(input.parse()?) - } else if input.peek(Token![loop]) { - Expr::Loop(input.parse()?) - } else if input.peek(Token![match]) { - Expr::Match(input.parse()?) - } else if input.peek(Token![try]) && input.peek2(token::Brace) { - Expr::TryBlock(input.call(expr_try_block)?) - } else if input.peek(Token![unsafe]) { - Expr::Unsafe(input.call(expr_unsafe)?) - } else if input.peek(token::Brace) { - Expr::Block(input.call(expr_block)?) - } else { - let allow_struct = AllowStruct(true); - let mut expr = unary_expr(input, allow_struct)?; - - attrs.extend(expr.replace_attrs(Vec::new())); - expr.replace_attrs(attrs); - - return parse_expr(input, expr, allow_struct, Precedence::Any); - }; - - if input.peek(Token![.]) || input.peek(Token![?]) { - expr = trailer_helper(input, expr)?; - - attrs.extend(expr.replace_attrs(Vec::new())); - expr.replace_attrs(attrs); - - let allow_struct = AllowStruct(true); - return parse_expr(input, expr, allow_struct, Precedence::Any); - } - - attrs.extend(expr.replace_attrs(Vec::new())); - expr.replace_attrs(attrs); - Ok(expr) - } - - impl Parse for ExprLit { - fn parse(input: ParseStream) -> Result<Self> { - Ok(ExprLit { - attrs: Vec::new(), - lit: input.parse()?, - }) - } - } - - #[cfg(feature = "full")] - fn expr_group(input: ParseStream) -> Result<ExprGroup> { - let group = crate::group::parse_group(input)?; - Ok(ExprGroup { - attrs: Vec::new(), - group_token: group.token, - expr: group.content.parse()?, - }) - } - - #[cfg(not(feature = "full"))] - fn expr_paren(input: ParseStream) -> Result<ExprParen> { - let content; - Ok(ExprParen { - attrs: Vec::new(), - paren_token: parenthesized!(content in input), - expr: content.parse()?, - }) - } - - #[cfg(feature = "full")] - fn generic_method_argument(input: ParseStream) -> Result<GenericMethodArgument> { - // TODO parse const generics as well - input.parse().map(GenericMethodArgument::Type) - } - - #[cfg(feature = "full")] - fn expr_let(input: ParseStream) -> Result<ExprLet> { - Ok(ExprLet { - attrs: Vec::new(), - let_token: input.parse()?, - pat: { - let leading_vert: Option<Token![|]> = input.parse()?; - let pat: Pat = input.parse()?; - if leading_vert.is_some() - || input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) - { - let mut cases = Punctuated::new(); - cases.push_value(pat); - while input.peek(Token![|]) - && !input.peek(Token![||]) - && !input.peek(Token![|=]) - { - let punct = input.parse()?; - cases.push_punct(punct); - let pat: Pat = input.parse()?; - cases.push_value(pat); - } - Pat::Or(PatOr { - attrs: Vec::new(), - leading_vert, - cases, - }) - } else { - pat - } - }, - eq_token: input.parse()?, - expr: Box::new(input.call(expr_no_struct)?), - }) - } - - #[cfg(feature = "full")] - impl Parse for ExprIf { - fn parse(input: ParseStream) -> Result<Self> { - Ok(ExprIf { - attrs: Vec::new(), - if_token: input.parse()?, - cond: Box::new(input.call(expr_no_struct)?), - then_branch: input.parse()?, - else_branch: { - if input.peek(Token![else]) { - Some(input.call(else_block)?) - } else { - None - } - }, - }) - } - } - - #[cfg(feature = "full")] - fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> { - let else_token: Token![else] = input.parse()?; - - let lookahead = input.lookahead1(); - let else_branch = if input.peek(Token![if]) { - input.parse().map(Expr::If)? - } else if input.peek(token::Brace) { - Expr::Block(ExprBlock { - attrs: Vec::new(), - label: None, - block: input.parse()?, - }) - } else { - return Err(lookahead.error()); - }; - - Ok((else_token, Box::new(else_branch))) - } - - #[cfg(feature = "full")] - impl Parse for ExprForLoop { - fn parse(input: ParseStream) -> Result<Self> { - let label: Option<Label> = input.parse()?; - let for_token: Token![for] = input.parse()?; - - let leading_vert: Option<Token![|]> = input.parse()?; - let mut pat: Pat = input.parse()?; - if leading_vert.is_some() || input.peek(Token![|]) { - let mut cases = Punctuated::new(); - cases.push_value(pat); - while input.peek(Token![|]) { - let punct = input.parse()?; - cases.push_punct(punct); - let pat: Pat = input.parse()?; - cases.push_value(pat); - } - pat = Pat::Or(PatOr { - attrs: Vec::new(), - leading_vert, - cases, - }); - } - - let in_token: Token![in] = input.parse()?; - let expr: Expr = input.call(expr_no_struct)?; - - let content; - let brace_token = braced!(content in input); - let inner_attrs = content.call(Attribute::parse_inner)?; - let stmts = content.call(Block::parse_within)?; - - Ok(ExprForLoop { - attrs: inner_attrs, - label, - for_token, - pat, - in_token, - expr: Box::new(expr), - body: Block { brace_token, stmts }, - }) - } - } - - #[cfg(feature = "full")] - impl Parse for ExprLoop { - fn parse(input: ParseStream) -> Result<Self> { - let label: Option<Label> = input.parse()?; - let loop_token: Token![loop] = input.parse()?; - - let content; - let brace_token = braced!(content in input); - let inner_attrs = content.call(Attribute::parse_inner)?; - let stmts = content.call(Block::parse_within)?; - - Ok(ExprLoop { - attrs: inner_attrs, - label, - loop_token, - body: Block { brace_token, stmts }, - }) - } - } - - #[cfg(feature = "full")] - impl Parse for ExprMatch { - fn parse(input: ParseStream) -> Result<Self> { - let match_token: Token![match] = input.parse()?; - let expr = expr_no_struct(input)?; - - let content; - let brace_token = braced!(content in input); - let inner_attrs = content.call(Attribute::parse_inner)?; - - let mut arms = Vec::new(); - while !content.is_empty() { - arms.push(content.call(Arm::parse)?); - } - - Ok(ExprMatch { - attrs: inner_attrs, - match_token, - expr: Box::new(expr), - brace_token, - arms, - }) - } - } - - macro_rules! impl_by_parsing_expr { - ( - $( - $expr_type:ty, $variant:ident, $msg:expr, - )* - ) => { - $( - #[cfg(all(feature = "full", feature = "printing"))] - impl Parse for $expr_type { - fn parse(input: ParseStream) -> Result<Self> { - let mut expr: Expr = input.parse()?; - loop { - match expr { - Expr::$variant(inner) => return Ok(inner), - Expr::Group(next) => expr = *next.expr, - _ => return Err(Error::new_spanned(expr, $msg)), - } - } - } - } - )* - }; - } - - impl_by_parsing_expr! { - ExprBox, Box, "expected box expression", - ExprArray, Array, "expected slice literal expression", - ExprCall, Call, "expected function call expression", - ExprMethodCall, MethodCall, "expected method call expression", - ExprTuple, Tuple, "expected tuple expression", - ExprBinary, Binary, "expected binary operation", - ExprUnary, Unary, "expected unary operation", - ExprCast, Cast, "expected cast expression", - ExprType, Type, "expected type ascription expression", - ExprLet, Let, "expected let guard", - ExprClosure, Closure, "expected closure expression", - ExprUnsafe, Unsafe, "expected unsafe block", - ExprBlock, Block, "expected blocked scope", - ExprAssign, Assign, "expected assignment expression", - ExprAssignOp, AssignOp, "expected compound assignment expression", - ExprField, Field, "expected struct field access", - ExprIndex, Index, "expected indexing expression", - ExprRange, Range, "expected range expression", - ExprReference, Reference, "expected referencing operation", - ExprBreak, Break, "expected break expression", - ExprContinue, Continue, "expected continue expression", - ExprReturn, Return, "expected return expression", - ExprMacro, Macro, "expected macro invocation expression", - ExprStruct, Struct, "expected struct literal expression", - ExprRepeat, Repeat, "expected array literal constructed from one repeated element", - ExprParen, Paren, "expected parenthesized expression", - ExprTry, Try, "expected try expression", - ExprAsync, Async, "expected async block", - ExprTryBlock, TryBlock, "expected try block", - ExprYield, Yield, "expected yield expression", - } - - #[cfg(feature = "full")] - fn expr_try_block(input: ParseStream) -> Result<ExprTryBlock> { - Ok(ExprTryBlock { - attrs: Vec::new(), - try_token: input.parse()?, - block: input.parse()?, - }) - } - - #[cfg(feature = "full")] - fn expr_yield(input: ParseStream) -> Result<ExprYield> { - Ok(ExprYield { - attrs: Vec::new(), - yield_token: input.parse()?, - expr: { - if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) { - Some(input.parse()?) - } else { - None - } - }, - }) - } - - #[cfg(feature = "full")] - fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> { - let asyncness: Option<Token![async]> = input.parse()?; - let movability: Option<Token![static]> = if asyncness.is_none() { - input.parse()? - } else { - None - }; - let capture: Option<Token![move]> = input.parse()?; - let or1_token: Token![|] = input.parse()?; - - let mut inputs = Punctuated::new(); - loop { - if input.peek(Token![|]) { - break; - } - let value = closure_arg(input)?; - inputs.push_value(value); - if input.peek(Token![|]) { - break; - } - let punct: Token![,] = input.parse()?; - inputs.push_punct(punct); - } - - let or2_token: Token![|] = input.parse()?; - - let (output, body) = if input.peek(Token![->]) { - let arrow_token: Token![->] = input.parse()?; - let ty: Type = input.parse()?; - let body: Block = input.parse()?; - let output = ReturnType::Type(arrow_token, Box::new(ty)); - let block = Expr::Block(ExprBlock { - attrs: Vec::new(), - label: None, - block: body, - }); - (output, block) - } else { - let body = ambiguous_expr(input, allow_struct)?; - (ReturnType::Default, body) - }; - - Ok(ExprClosure { - attrs: Vec::new(), - asyncness, - movability, - capture, - or1_token, - inputs, - or2_token, - output, - body: Box::new(body), - }) - } - - #[cfg(feature = "full")] - fn expr_async(input: ParseStream) -> Result<ExprAsync> { - Ok(ExprAsync { - attrs: Vec::new(), - async_token: input.parse()?, - capture: input.parse()?, - block: input.parse()?, - }) - } - - #[cfg(feature = "full")] - fn closure_arg(input: ParseStream) -> Result<Pat> { - let attrs = input.call(Attribute::parse_outer)?; - let mut pat: Pat = input.parse()?; - - if input.peek(Token![:]) { - Ok(Pat::Type(PatType { - attrs, - pat: Box::new(pat), - colon_token: input.parse()?, - ty: input.parse()?, - })) - } else { - match &mut pat { - Pat::Box(pat) => pat.attrs = attrs, - Pat::Ident(pat) => pat.attrs = attrs, - Pat::Lit(pat) => pat.attrs = attrs, - Pat::Macro(pat) => pat.attrs = attrs, - Pat::Or(pat) => pat.attrs = attrs, - Pat::Path(pat) => pat.attrs = attrs, - Pat::Range(pat) => pat.attrs = attrs, - Pat::Reference(pat) => pat.attrs = attrs, - Pat::Rest(pat) => pat.attrs = attrs, - Pat::Slice(pat) => pat.attrs = attrs, - Pat::Struct(pat) => pat.attrs = attrs, - Pat::Tuple(pat) => pat.attrs = attrs, - Pat::TupleStruct(pat) => pat.attrs = attrs, - Pat::Type(_) => unreachable!(), - Pat::Verbatim(_) => {} - Pat::Wild(pat) => pat.attrs = attrs, - Pat::__Nonexhaustive => unreachable!(), - } - Ok(pat) - } - } - - #[cfg(feature = "full")] - impl Parse for ExprWhile { - fn parse(input: ParseStream) -> Result<Self> { - let label: Option<Label> = input.parse()?; - let while_token: Token![while] = input.parse()?; - let cond = expr_no_struct(input)?; - - let content; - let brace_token = braced!(content in input); - let inner_attrs = content.call(Attribute::parse_inner)?; - let stmts = content.call(Block::parse_within)?; - - Ok(ExprWhile { - attrs: inner_attrs, - label, - while_token, - cond: Box::new(cond), - body: Block { brace_token, stmts }, - }) - } - } - - #[cfg(feature = "full")] - impl Parse for Label { - fn parse(input: ParseStream) -> Result<Self> { - Ok(Label { - name: input.parse()?, - colon_token: input.parse()?, - }) - } - } - - #[cfg(feature = "full")] - impl Parse for Option<Label> { - fn parse(input: ParseStream) -> Result<Self> { - if input.peek(Lifetime) { - input.parse().map(Some) - } else { - Ok(None) - } - } - } - - #[cfg(feature = "full")] - fn expr_continue(input: ParseStream) -> Result<ExprContinue> { - Ok(ExprContinue { - attrs: Vec::new(), - continue_token: input.parse()?, - label: input.parse()?, - }) - } - - #[cfg(feature = "full")] - fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> { - Ok(ExprBreak { - attrs: Vec::new(), - break_token: input.parse()?, - label: input.parse()?, - expr: { - if input.is_empty() - || input.peek(Token![,]) - || input.peek(Token![;]) - || !allow_struct.0 && input.peek(token::Brace) - { - None - } else { - let expr = ambiguous_expr(input, allow_struct)?; - Some(Box::new(expr)) - } - }, - }) - } - - #[cfg(feature = "full")] - fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> { - Ok(ExprReturn { - attrs: Vec::new(), - return_token: input.parse()?, - expr: { - if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) { - None - } else { - // NOTE: return is greedy and eats blocks after it even when in a - // position where structs are not allowed, such as in if statement - // conditions. For example: - // - // if return { println!("A") } {} // Prints "A" - let expr = ambiguous_expr(input, allow_struct)?; - Some(Box::new(expr)) - } - }, - }) - } - - #[cfg(feature = "full")] - impl Parse for FieldValue { - fn parse(input: ParseStream) -> Result<Self> { - let attrs = input.call(Attribute::parse_outer)?; - let member: Member = input.parse()?; - let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() { - let colon_token: Token![:] = input.parse()?; - let value: Expr = input.parse()?; - (Some(colon_token), value) - } else if let Member::Named(ident) = &member { - let value = Expr::Path(ExprPath { - attrs: Vec::new(), - qself: None, - path: Path::from(ident.clone()), - }); - (None, value) - } else { - unreachable!() - }; - - Ok(FieldValue { - attrs, - member, - colon_token, - expr: value, - }) - } - } - - #[cfg(feature = "full")] - fn expr_struct_helper( - input: ParseStream, - outer_attrs: Vec<Attribute>, - path: Path, - ) -> Result<ExprStruct> { - let content; - let brace_token = braced!(content in input); - let inner_attrs = content.call(Attribute::parse_inner)?; - let attrs = private::attrs(outer_attrs, inner_attrs); - - let mut fields = Punctuated::new(); - while !content.is_empty() { - if content.peek(Token![..]) { - return Ok(ExprStruct { - attrs, - brace_token, - path, - fields, - dot2_token: Some(content.parse()?), - rest: Some(Box::new(content.parse()?)), - }); - } - - fields.push(content.parse()?); - if !content.peek(Token![,]) { - break; - } - let punct: Token![,] = content.parse()?; - fields.push_punct(punct); - } - - Ok(ExprStruct { - attrs, - brace_token, - path, - fields, - dot2_token: None, - rest: None, - }) - } - - #[cfg(feature = "full")] - fn expr_unsafe(input: ParseStream) -> Result<ExprUnsafe> { - let unsafe_token: Token![unsafe] = input.parse()?; - - let content; - let brace_token = braced!(content in input); - let inner_attrs = content.call(Attribute::parse_inner)?; - let stmts = content.call(Block::parse_within)?; - - Ok(ExprUnsafe { - attrs: inner_attrs, - unsafe_token, - block: Block { brace_token, stmts }, - }) - } - - #[cfg(feature = "full")] - pub fn expr_block(input: ParseStream) -> Result<ExprBlock> { - let label: Option<Label> = input.parse()?; - - let content; - let brace_token = braced!(content in input); - let inner_attrs = content.call(Attribute::parse_inner)?; - let stmts = content.call(Block::parse_within)?; - - Ok(ExprBlock { - attrs: inner_attrs, - label, - block: Block { brace_token, stmts }, - }) - } - - #[cfg(feature = "full")] - fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> { - Ok(ExprRange { - attrs: Vec::new(), - from: None, - limits: input.parse()?, - to: { - if input.is_empty() - || input.peek(Token![,]) - || input.peek(Token![;]) - || !allow_struct.0 && input.peek(token::Brace) - { - None - } else { - let to = ambiguous_expr(input, allow_struct)?; - Some(Box::new(to)) - } - }, - }) - } - - #[cfg(feature = "full")] - impl Parse for RangeLimits { - fn parse(input: ParseStream) -> Result<Self> { - let lookahead = input.lookahead1(); - if lookahead.peek(Token![..=]) { - input.parse().map(RangeLimits::Closed) - } else if lookahead.peek(Token![...]) { - let dot3: Token![...] = input.parse()?; - Ok(RangeLimits::Closed(Token![..=](dot3.spans))) - } else if lookahead.peek(Token![..]) { - input.parse().map(RangeLimits::HalfOpen) - } else { - Err(lookahead.error()) - } - } - } - - impl Parse for ExprPath { - fn parse(input: ParseStream) -> Result<Self> { - #[cfg(not(feature = "full"))] - let attrs = Vec::new(); - #[cfg(feature = "full")] - let attrs = input.call(Attribute::parse_outer)?; - - let (qself, path) = path::parsing::qpath(input, true)?; - - Ok(ExprPath { attrs, qself, path }) - } - } - - impl Parse for Member { - fn parse(input: ParseStream) -> Result<Self> { - if input.peek(Ident) { - input.parse().map(Member::Named) - } else if input.peek(LitInt) { - input.parse().map(Member::Unnamed) - } else { - Err(input.error("expected identifier or integer")) - } - } - } - - #[cfg(feature = "full")] - impl Parse for Arm { - fn parse(input: ParseStream) -> Result<Arm> { - let requires_comma; - Ok(Arm { - attrs: input.call(Attribute::parse_outer)?, - pat: { - let leading_vert: Option<Token![|]> = input.parse()?; - let pat: Pat = input.parse()?; - if leading_vert.is_some() || input.peek(Token![|]) { - let mut cases = Punctuated::new(); - cases.push_value(pat); - while input.peek(Token![|]) { - let punct = input.parse()?; - cases.push_punct(punct); - let pat: Pat = input.parse()?; - cases.push_value(pat); - } - Pat::Or(PatOr { - attrs: Vec::new(), - leading_vert, - cases, - }) - } else { - pat - } - }, - guard: { - if input.peek(Token![if]) { - let if_token: Token![if] = input.parse()?; - let guard: Expr = input.parse()?; - Some((if_token, Box::new(guard))) - } else { - None - } - }, - fat_arrow_token: input.parse()?, - body: { - let body = input.call(expr_early)?; - requires_comma = requires_terminator(&body); - Box::new(body) - }, - comma: { - if requires_comma && !input.is_empty() { - Some(input.parse()?) - } else { - input.parse()? - } - }, - }) - } - } - - impl Parse for Index { - fn parse(input: ParseStream) -> Result<Self> { - let lit: LitInt = input.parse()?; - if lit.suffix().is_empty() { - Ok(Index { - index: lit - .base10_digits() - .parse() - .map_err(|err| Error::new(lit.span(), err))?, - span: lit.span(), - }) - } else { - Err(Error::new(lit.span(), "expected unsuffixed integer")) - } - } - } - - #[cfg(feature = "full")] - impl Member { - fn is_named(&self) -> bool { - match *self { - Member::Named(_) => true, - Member::Unnamed(_) => false, - } - } - } -} - -#[cfg(feature = "printing")] -pub(crate) mod printing { - use super::*; - - use proc_macro2::{Literal, TokenStream}; - use quote::{ToTokens, TokenStreamExt}; - - #[cfg(feature = "full")] - use crate::attr::FilterAttrs; - #[cfg(feature = "full")] - use crate::print::TokensOrDefault; - - // If the given expression is a bare `ExprStruct`, wraps it in parenthesis - // before appending it to `TokenStream`. - #[cfg(feature = "full")] - fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) { - if let Expr::Struct(_) = *e { - token::Paren::default().surround(tokens, |tokens| { - e.to_tokens(tokens); - }); - } else { - e.to_tokens(tokens); - } - } - - #[cfg(feature = "full")] - pub(crate) fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) { - tokens.append_all(attrs.outer()); - } - - #[cfg(feature = "full")] - fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) { - tokens.append_all(attrs.inner()); - } - - #[cfg(not(feature = "full"))] - pub(crate) fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {} - - #[cfg(not(feature = "full"))] - fn inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {} - - #[cfg(feature = "full")] - impl ToTokens for ExprBox { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.box_token.to_tokens(tokens); - self.expr.to_tokens(tokens); - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprArray { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.bracket_token.surround(tokens, |tokens| { - inner_attrs_to_tokens(&self.attrs, tokens); - self.elems.to_tokens(tokens); - }) - } - } - - impl ToTokens for ExprCall { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.func.to_tokens(tokens); - self.paren_token.surround(tokens, |tokens| { - self.args.to_tokens(tokens); - }) - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprMethodCall { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.receiver.to_tokens(tokens); - self.dot_token.to_tokens(tokens); - self.method.to_tokens(tokens); - self.turbofish.to_tokens(tokens); - self.paren_token.surround(tokens, |tokens| { - self.args.to_tokens(tokens); - }); - } - } - - #[cfg(feature = "full")] - impl ToTokens for MethodTurbofish { - fn to_tokens(&self, tokens: &mut TokenStream) { - self.colon2_token.to_tokens(tokens); - self.lt_token.to_tokens(tokens); - self.args.to_tokens(tokens); - self.gt_token.to_tokens(tokens); - } - } - - #[cfg(feature = "full")] - impl ToTokens for GenericMethodArgument { - fn to_tokens(&self, tokens: &mut TokenStream) { - match self { - GenericMethodArgument::Type(t) => t.to_tokens(tokens), - GenericMethodArgument::Const(c) => c.to_tokens(tokens), - } - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprTuple { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.paren_token.surround(tokens, |tokens| { - inner_attrs_to_tokens(&self.attrs, tokens); - self.elems.to_tokens(tokens); - // If we only have one argument, we need a trailing comma to - // distinguish ExprTuple from ExprParen. - if self.elems.len() == 1 && !self.elems.trailing_punct() { - <Token![,]>::default().to_tokens(tokens); - } - }) - } - } - - impl ToTokens for ExprBinary { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.left.to_tokens(tokens); - self.op.to_tokens(tokens); - self.right.to_tokens(tokens); - } - } - - impl ToTokens for ExprUnary { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.op.to_tokens(tokens); - self.expr.to_tokens(tokens); - } - } - - impl ToTokens for ExprLit { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.lit.to_tokens(tokens); - } - } - - impl ToTokens for ExprCast { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.expr.to_tokens(tokens); - self.as_token.to_tokens(tokens); - self.ty.to_tokens(tokens); - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprType { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.expr.to_tokens(tokens); - self.colon_token.to_tokens(tokens); - self.ty.to_tokens(tokens); - } - } - - #[cfg(feature = "full")] - fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>) { - if let Some((else_token, else_)) = else_ { - else_token.to_tokens(tokens); - - // If we are not one of the valid expressions to exist in an else - // clause, wrap ourselves in a block. - match **else_ { - Expr::If(_) | Expr::Block(_) => { - else_.to_tokens(tokens); - } - _ => { - token::Brace::default().surround(tokens, |tokens| { - else_.to_tokens(tokens); - }); - } - } - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprLet { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.let_token.to_tokens(tokens); - self.pat.to_tokens(tokens); - self.eq_token.to_tokens(tokens); - wrap_bare_struct(tokens, &self.expr); - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprIf { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.if_token.to_tokens(tokens); - wrap_bare_struct(tokens, &self.cond); - self.then_branch.to_tokens(tokens); - maybe_wrap_else(tokens, &self.else_branch); - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprWhile { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.label.to_tokens(tokens); - self.while_token.to_tokens(tokens); - wrap_bare_struct(tokens, &self.cond); - self.body.brace_token.surround(tokens, |tokens| { - inner_attrs_to_tokens(&self.attrs, tokens); - tokens.append_all(&self.body.stmts); - }); - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprForLoop { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.label.to_tokens(tokens); - self.for_token.to_tokens(tokens); - self.pat.to_tokens(tokens); - self.in_token.to_tokens(tokens); - wrap_bare_struct(tokens, &self.expr); - self.body.brace_token.surround(tokens, |tokens| { - inner_attrs_to_tokens(&self.attrs, tokens); - tokens.append_all(&self.body.stmts); - }); - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprLoop { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.label.to_tokens(tokens); - self.loop_token.to_tokens(tokens); - self.body.brace_token.surround(tokens, |tokens| { - inner_attrs_to_tokens(&self.attrs, tokens); - tokens.append_all(&self.body.stmts); - }); - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprMatch { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.match_token.to_tokens(tokens); - wrap_bare_struct(tokens, &self.expr); - self.brace_token.surround(tokens, |tokens| { - inner_attrs_to_tokens(&self.attrs, tokens); - for (i, arm) in self.arms.iter().enumerate() { - arm.to_tokens(tokens); - // Ensure that we have a comma after a non-block arm, except - // for the last one. - let is_last = i == self.arms.len() - 1; - if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() { - <Token![,]>::default().to_tokens(tokens); - } - } - }); - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprAsync { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.async_token.to_tokens(tokens); - self.capture.to_tokens(tokens); - self.block.to_tokens(tokens); - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprAwait { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.base.to_tokens(tokens); - self.dot_token.to_tokens(tokens); - self.await_token.to_tokens(tokens); - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprTryBlock { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.try_token.to_tokens(tokens); - self.block.to_tokens(tokens); - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprYield { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.yield_token.to_tokens(tokens); - self.expr.to_tokens(tokens); - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprClosure { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.asyncness.to_tokens(tokens); - self.movability.to_tokens(tokens); - self.capture.to_tokens(tokens); - self.or1_token.to_tokens(tokens); - self.inputs.to_tokens(tokens); - self.or2_token.to_tokens(tokens); - self.output.to_tokens(tokens); - self.body.to_tokens(tokens); - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprUnsafe { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.unsafe_token.to_tokens(tokens); - self.block.brace_token.surround(tokens, |tokens| { - inner_attrs_to_tokens(&self.attrs, tokens); - tokens.append_all(&self.block.stmts); - }); - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprBlock { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.label.to_tokens(tokens); - self.block.brace_token.surround(tokens, |tokens| { - inner_attrs_to_tokens(&self.attrs, tokens); - tokens.append_all(&self.block.stmts); - }); - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprAssign { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.left.to_tokens(tokens); - self.eq_token.to_tokens(tokens); - self.right.to_tokens(tokens); - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprAssignOp { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.left.to_tokens(tokens); - self.op.to_tokens(tokens); - self.right.to_tokens(tokens); - } - } - - impl ToTokens for ExprField { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.base.to_tokens(tokens); - self.dot_token.to_tokens(tokens); - self.member.to_tokens(tokens); - } - } - - impl ToTokens for Member { - fn to_tokens(&self, tokens: &mut TokenStream) { - match self { - Member::Named(ident) => ident.to_tokens(tokens), - Member::Unnamed(index) => index.to_tokens(tokens), - } - } - } - - impl ToTokens for Index { - fn to_tokens(&self, tokens: &mut TokenStream) { - let mut lit = Literal::i64_unsuffixed(i64::from(self.index)); - lit.set_span(self.span); - tokens.append(lit); - } - } - - impl ToTokens for ExprIndex { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.expr.to_tokens(tokens); - self.bracket_token.surround(tokens, |tokens| { - self.index.to_tokens(tokens); - }); - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprRange { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.from.to_tokens(tokens); - match &self.limits { - RangeLimits::HalfOpen(t) => t.to_tokens(tokens), - RangeLimits::Closed(t) => t.to_tokens(tokens), - } - self.to.to_tokens(tokens); - } - } - - impl ToTokens for ExprPath { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - private::print_path(tokens, &self.qself, &self.path); - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprReference { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.and_token.to_tokens(tokens); - self.mutability.to_tokens(tokens); - self.expr.to_tokens(tokens); - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprBreak { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.break_token.to_tokens(tokens); - self.label.to_tokens(tokens); - self.expr.to_tokens(tokens); - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprContinue { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.continue_token.to_tokens(tokens); - self.label.to_tokens(tokens); - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprReturn { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.return_token.to_tokens(tokens); - self.expr.to_tokens(tokens); - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprMacro { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.mac.to_tokens(tokens); - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprStruct { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.path.to_tokens(tokens); - self.brace_token.surround(tokens, |tokens| { - inner_attrs_to_tokens(&self.attrs, tokens); - self.fields.to_tokens(tokens); - if self.rest.is_some() { - TokensOrDefault(&self.dot2_token).to_tokens(tokens); - self.rest.to_tokens(tokens); - } - }) - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprRepeat { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.bracket_token.surround(tokens, |tokens| { - inner_attrs_to_tokens(&self.attrs, tokens); - self.expr.to_tokens(tokens); - self.semi_token.to_tokens(tokens); - self.len.to_tokens(tokens); - }) - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprGroup { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.group_token.surround(tokens, |tokens| { - self.expr.to_tokens(tokens); - }); - } - } - - impl ToTokens for ExprParen { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.paren_token.surround(tokens, |tokens| { - inner_attrs_to_tokens(&self.attrs, tokens); - self.expr.to_tokens(tokens); - }); - } - } - - #[cfg(feature = "full")] - impl ToTokens for ExprTry { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.expr.to_tokens(tokens); - self.question_token.to_tokens(tokens); - } - } - - #[cfg(feature = "full")] - impl ToTokens for Label { - fn to_tokens(&self, tokens: &mut TokenStream) { - self.name.to_tokens(tokens); - self.colon_token.to_tokens(tokens); - } - } - - #[cfg(feature = "full")] - impl ToTokens for FieldValue { - fn to_tokens(&self, tokens: &mut TokenStream) { - outer_attrs_to_tokens(&self.attrs, tokens); - self.member.to_tokens(tokens); - if let Some(colon_token) = &self.colon_token { - colon_token.to_tokens(tokens); - self.expr.to_tokens(tokens); - } - } - } - - #[cfg(feature = "full")] - impl ToTokens for Arm { - fn to_tokens(&self, tokens: &mut TokenStream) { - tokens.append_all(&self.attrs); - self.pat.to_tokens(tokens); - if let Some((if_token, guard)) = &self.guard { - if_token.to_tokens(tokens); - guard.to_tokens(tokens); - } - self.fat_arrow_token.to_tokens(tokens); - self.body.to_tokens(tokens); - self.comma.to_tokens(tokens); - } - } -} |