| use super::*; | 
 | use crate::punctuated::Punctuated; | 
 | use proc_macro2::TokenStream; | 
 |  | 
 | ast_enum_of_structs! { | 
 |     /// A pattern in a local binding, function signature, match expression, or | 
 |     /// various other places. | 
 |     /// | 
 |     /// *This type is available only if Syn is built with the `"full"` feature.* | 
 |     /// | 
 |     /// # Syntax tree enum | 
 |     /// | 
 |     /// This type is a [syntax tree enum]. | 
 |     /// | 
 |     /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums | 
 |     // | 
 |     // TODO: change syntax-tree-enum link to an intra rustdoc link, currently | 
 |     // blocked on https://github.com/rust-lang/rust/issues/62833 | 
 |     pub enum Pat { | 
 |         /// A box pattern: `box v`. | 
 |         Box(PatBox), | 
 |  | 
 |         /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`. | 
 |         Ident(PatIdent), | 
 |  | 
 |         /// A literal pattern: `0`. | 
 |         /// | 
 |         /// This holds an `Expr` rather than a `Lit` because negative numbers | 
 |         /// are represented as an `Expr::Unary`. | 
 |         Lit(PatLit), | 
 |  | 
 |         /// A macro in pattern position. | 
 |         Macro(PatMacro), | 
 |  | 
 |         /// A pattern that matches any one of a set of cases. | 
 |         Or(PatOr), | 
 |  | 
 |         /// A path pattern like `Color::Red`, optionally qualified with a | 
 |         /// self-type. | 
 |         /// | 
 |         /// Unqualified path patterns can legally refer to variants, structs, | 
 |         /// constants or associated constants. Qualified path patterns like | 
 |         /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to | 
 |         /// associated constants. | 
 |         Path(PatPath), | 
 |  | 
 |         /// A range pattern: `1..=2`. | 
 |         Range(PatRange), | 
 |  | 
 |         /// A reference pattern: `&mut var`. | 
 |         Reference(PatReference), | 
 |  | 
 |         /// The dots in a tuple or slice pattern: `[0, 1, ..]` | 
 |         Rest(PatRest), | 
 |  | 
 |         /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`. | 
 |         Slice(PatSlice), | 
 |  | 
 |         /// A struct or struct variant pattern: `Variant { x, y, .. }`. | 
 |         Struct(PatStruct), | 
 |  | 
 |         /// A tuple pattern: `(a, b)`. | 
 |         Tuple(PatTuple), | 
 |  | 
 |         /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`. | 
 |         TupleStruct(PatTupleStruct), | 
 |  | 
 |         /// A type ascription pattern: `foo: f64`. | 
 |         Type(PatType), | 
 |  | 
 |         /// Tokens in pattern position not interpreted by Syn. | 
 |         Verbatim(TokenStream), | 
 |  | 
 |         /// A pattern that matches any value: `_`. | 
 |         Wild(PatWild), | 
 |  | 
 |         #[doc(hidden)] | 
 |         __Nonexhaustive, | 
 |     } | 
 | } | 
 |  | 
 | ast_struct! { | 
 |     /// A box pattern: `box v`. | 
 |     /// | 
 |     /// *This type is available only if Syn is built with the `"full"` feature.* | 
 |     pub struct PatBox { | 
 |         pub attrs: Vec<Attribute>, | 
 |         pub box_token: Token![box], | 
 |         pub pat: Box<Pat>, | 
 |     } | 
 | } | 
 |  | 
 | ast_struct! { | 
 |     /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`. | 
 |     /// | 
 |     /// It may also be a unit struct or struct variant (e.g. `None`), or a | 
 |     /// constant; these cannot be distinguished syntactically. | 
 |     /// | 
 |     /// *This type is available only if Syn is built with the `"full"` feature.* | 
 |     pub struct PatIdent { | 
 |         pub attrs: Vec<Attribute>, | 
 |         pub by_ref: Option<Token![ref]>, | 
 |         pub mutability: Option<Token![mut]>, | 
 |         pub ident: Ident, | 
 |         pub subpat: Option<(Token![@], Box<Pat>)>, | 
 |     } | 
 | } | 
 |  | 
 | ast_struct! { | 
 |     /// A literal pattern: `0`. | 
 |     /// | 
 |     /// This holds an `Expr` rather than a `Lit` because negative numbers | 
 |     /// are represented as an `Expr::Unary`. | 
 |     /// | 
 |     /// *This type is available only if Syn is built with the `"full"` feature.* | 
 |     pub struct PatLit { | 
 |         pub attrs: Vec<Attribute>, | 
 |         pub expr: Box<Expr>, | 
 |     } | 
 | } | 
 |  | 
 | ast_struct! { | 
 |     /// A macro in pattern position. | 
 |     /// | 
 |     /// *This type is available only if Syn is built with the `"full"` feature.* | 
 |     pub struct PatMacro { | 
 |         pub attrs: Vec<Attribute>, | 
 |         pub mac: Macro, | 
 |     } | 
 | } | 
 |  | 
 | ast_struct! { | 
 |     /// A pattern that matches any one of a set of cases. | 
 |     /// | 
 |     /// *This type is available only if Syn is built with the `"full"` feature.* | 
 |     pub struct PatOr { | 
 |         pub attrs: Vec<Attribute>, | 
 |         pub leading_vert: Option<Token![|]>, | 
 |         pub cases: Punctuated<Pat, Token![|]>, | 
 |     } | 
 | } | 
 |  | 
 | ast_struct! { | 
 |     /// A path pattern like `Color::Red`, optionally qualified with a | 
 |     /// self-type. | 
 |     /// | 
 |     /// Unqualified path patterns can legally refer to variants, structs, | 
 |     /// constants or associated constants. Qualified path patterns like | 
 |     /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to | 
 |     /// associated constants. | 
 |     /// | 
 |     /// *This type is available only if Syn is built with the `"full"` feature.* | 
 |     pub struct PatPath { | 
 |         pub attrs: Vec<Attribute>, | 
 |         pub qself: Option<QSelf>, | 
 |         pub path: Path, | 
 |     } | 
 | } | 
 |  | 
 | ast_struct! { | 
 |     /// A range pattern: `1..=2`. | 
 |     /// | 
 |     /// *This type is available only if Syn is built with the `"full"` feature.* | 
 |     pub struct PatRange { | 
 |         pub attrs: Vec<Attribute>, | 
 |         pub lo: Box<Expr>, | 
 |         pub limits: RangeLimits, | 
 |         pub hi: Box<Expr>, | 
 |     } | 
 | } | 
 |  | 
 | ast_struct! { | 
 |     /// A reference pattern: `&mut var`. | 
 |     /// | 
 |     /// *This type is available only if Syn is built with the `"full"` feature.* | 
 |     pub struct PatReference { | 
 |         pub attrs: Vec<Attribute>, | 
 |         pub and_token: Token![&], | 
 |         pub mutability: Option<Token![mut]>, | 
 |         pub pat: Box<Pat>, | 
 |     } | 
 | } | 
 |  | 
 | ast_struct! { | 
 |     /// The dots in a tuple or slice pattern: `[0, 1, ..]` | 
 |     /// | 
 |     /// *This type is available only if Syn is built with the `"full"` feature.* | 
 |     pub struct PatRest { | 
 |         pub attrs: Vec<Attribute>, | 
 |         pub dot2_token: Token![..], | 
 |     } | 
 | } | 
 |  | 
 | ast_struct! { | 
 |     /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`. | 
 |     /// | 
 |     /// *This type is available only if Syn is built with the `"full"` feature.* | 
 |     pub struct PatSlice { | 
 |         pub attrs: Vec<Attribute>, | 
 |         pub bracket_token: token::Bracket, | 
 |         pub elems: Punctuated<Pat, Token![,]>, | 
 |     } | 
 | } | 
 |  | 
 | ast_struct! { | 
 |     /// A struct or struct variant pattern: `Variant { x, y, .. }`. | 
 |     /// | 
 |     /// *This type is available only if Syn is built with the `"full"` feature.* | 
 |     pub struct PatStruct { | 
 |         pub attrs: Vec<Attribute>, | 
 |         pub path: Path, | 
 |         pub brace_token: token::Brace, | 
 |         pub fields: Punctuated<FieldPat, Token![,]>, | 
 |         pub dot2_token: Option<Token![..]>, | 
 |     } | 
 | } | 
 |  | 
 | ast_struct! { | 
 |     /// A tuple pattern: `(a, b)`. | 
 |     /// | 
 |     /// *This type is available only if Syn is built with the `"full"` feature.* | 
 |     pub struct PatTuple { | 
 |         pub attrs: Vec<Attribute>, | 
 |         pub paren_token: token::Paren, | 
 |         pub elems: Punctuated<Pat, Token![,]>, | 
 |     } | 
 | } | 
 |  | 
 | ast_struct! { | 
 |     /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`. | 
 |     /// | 
 |     /// *This type is available only if Syn is built with the `"full"` feature.* | 
 |     pub struct PatTupleStruct { | 
 |         pub attrs: Vec<Attribute>, | 
 |         pub path: Path, | 
 |         pub pat: PatTuple, | 
 |     } | 
 | } | 
 |  | 
 | ast_struct! { | 
 |     /// A type ascription pattern: `foo: f64`. | 
 |     /// | 
 |     /// *This type is available only if Syn is built with the `"full"` feature.* | 
 |     pub struct PatType { | 
 |         pub attrs: Vec<Attribute>, | 
 |         pub pat: Box<Pat>, | 
 |         pub colon_token: Token![:], | 
 |         pub ty: Box<Type>, | 
 |     } | 
 | } | 
 |  | 
 | ast_struct! { | 
 |     /// A pattern that matches any value: `_`. | 
 |     /// | 
 |     /// *This type is available only if Syn is built with the `"full"` feature.* | 
 |     pub struct PatWild { | 
 |         pub attrs: Vec<Attribute>, | 
 |         pub underscore_token: Token![_], | 
 |     } | 
 | } | 
 |  | 
 | ast_struct! { | 
 |     /// A single field in a struct pattern. | 
 |     /// | 
 |     /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated | 
 |     /// the same as `x: x, y: ref y, z: ref mut z` but there is no colon token. | 
 |     /// | 
 |     /// *This type is available only if Syn is built with the `"full"` feature.* | 
 |     pub struct FieldPat { | 
 |         pub attrs: Vec<Attribute>, | 
 |         pub member: Member, | 
 |         pub colon_token: Option<Token![:]>, | 
 |         pub pat: Box<Pat>, | 
 |     } | 
 | } | 
 |  | 
 | #[cfg(feature = "parsing")] | 
 | pub mod parsing { | 
 |     use super::*; | 
 |     use crate::ext::IdentExt; | 
 |     use crate::parse::{Parse, ParseBuffer, ParseStream, Result}; | 
 |     use crate::path; | 
 |  | 
 |     impl Parse for Pat { | 
 |         fn parse(input: ParseStream) -> Result<Self> { | 
 |             let begin = input.fork(); | 
 |             let lookahead = input.lookahead1(); | 
 |             if lookahead.peek(Ident) | 
 |                 && ({ | 
 |                     input.peek2(Token![::]) | 
 |                         || input.peek2(Token![!]) | 
 |                         || input.peek2(token::Brace) | 
 |                         || input.peek2(token::Paren) | 
 |                         || input.peek2(Token![..]) | 
 |                             && !{ | 
 |                                 let ahead = input.fork(); | 
 |                                 ahead.parse::<Ident>()?; | 
 |                                 ahead.parse::<RangeLimits>()?; | 
 |                                 ahead.is_empty() || ahead.peek(Token![,]) | 
 |                             } | 
 |                 }) | 
 |                 || input.peek(Token![self]) && input.peek2(Token![::]) | 
 |                 || lookahead.peek(Token![::]) | 
 |                 || lookahead.peek(Token![<]) | 
 |                 || input.peek(Token![Self]) | 
 |                 || input.peek(Token![super]) | 
 |                 || input.peek(Token![crate]) | 
 |             { | 
 |                 pat_path_or_macro_or_struct_or_range(input) | 
 |             } else if lookahead.peek(Token![_]) { | 
 |                 input.call(pat_wild).map(Pat::Wild) | 
 |             } else if input.peek(Token![box]) { | 
 |                 input.call(pat_box).map(Pat::Box) | 
 |             } else if input.peek(Token![-]) || lookahead.peek(Lit) { | 
 |                 pat_lit_or_range(input) | 
 |             } else if lookahead.peek(Token![ref]) | 
 |                 || lookahead.peek(Token![mut]) | 
 |                 || input.peek(Token![self]) | 
 |                 || input.peek(Ident) | 
 |             { | 
 |                 input.call(pat_ident).map(Pat::Ident) | 
 |             } else if lookahead.peek(Token![&]) { | 
 |                 input.call(pat_reference).map(Pat::Reference) | 
 |             } else if lookahead.peek(token::Paren) { | 
 |                 input.call(pat_tuple).map(Pat::Tuple) | 
 |             } else if lookahead.peek(token::Bracket) { | 
 |                 input.call(pat_slice).map(Pat::Slice) | 
 |             } else if lookahead.peek(Token![..]) && !input.peek(Token![...]) { | 
 |                 pat_range_half_open(input, begin) | 
 |             } else { | 
 |                 Err(lookahead.error()) | 
 |             } | 
 |         } | 
 |     } | 
 |  | 
 |     fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> { | 
 |         let begin = input.fork(); | 
 |         let (qself, path) = path::parsing::qpath(input, true)?; | 
 |  | 
 |         if input.peek(Token![..]) { | 
 |             return pat_range(input, begin, qself, path); | 
 |         } | 
 |  | 
 |         if qself.is_some() { | 
 |             return Ok(Pat::Path(PatPath { | 
 |                 attrs: Vec::new(), | 
 |                 qself, | 
 |                 path, | 
 |             })); | 
 |         } | 
 |  | 
 |         if input.peek(Token![!]) && !input.peek(Token![!=]) { | 
 |             let mut contains_arguments = false; | 
 |             for segment in &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(Pat::Macro(PatMacro { | 
 |                     attrs: Vec::new(), | 
 |                     mac: Macro { | 
 |                         path, | 
 |                         bang_token, | 
 |                         delimiter, | 
 |                         tokens, | 
 |                     }, | 
 |                 })); | 
 |             } | 
 |         } | 
 |  | 
 |         if input.peek(token::Brace) { | 
 |             pat_struct(input, path).map(Pat::Struct) | 
 |         } else if input.peek(token::Paren) { | 
 |             pat_tuple_struct(input, path).map(Pat::TupleStruct) | 
 |         } else if input.peek(Token![..]) { | 
 |             pat_range(input, begin, qself, path) | 
 |         } else { | 
 |             Ok(Pat::Path(PatPath { | 
 |                 attrs: Vec::new(), | 
 |                 qself, | 
 |                 path, | 
 |             })) | 
 |         } | 
 |     } | 
 |  | 
 |     fn pat_wild(input: ParseStream) -> Result<PatWild> { | 
 |         Ok(PatWild { | 
 |             attrs: Vec::new(), | 
 |             underscore_token: input.parse()?, | 
 |         }) | 
 |     } | 
 |  | 
 |     fn pat_box(input: ParseStream) -> Result<PatBox> { | 
 |         Ok(PatBox { | 
 |             attrs: Vec::new(), | 
 |             box_token: input.parse()?, | 
 |             pat: input.parse()?, | 
 |         }) | 
 |     } | 
 |  | 
 |     fn pat_ident(input: ParseStream) -> Result<PatIdent> { | 
 |         Ok(PatIdent { | 
 |             attrs: Vec::new(), | 
 |             by_ref: input.parse()?, | 
 |             mutability: input.parse()?, | 
 |             ident: input.call(Ident::parse_any)?, | 
 |             subpat: { | 
 |                 if input.peek(Token![@]) { | 
 |                     let at_token: Token![@] = input.parse()?; | 
 |                     let subpat: Pat = input.parse()?; | 
 |                     Some((at_token, Box::new(subpat))) | 
 |                 } else { | 
 |                     None | 
 |                 } | 
 |             }, | 
 |         }) | 
 |     } | 
 |  | 
 |     fn pat_tuple_struct(input: ParseStream, path: Path) -> Result<PatTupleStruct> { | 
 |         Ok(PatTupleStruct { | 
 |             attrs: Vec::new(), | 
 |             path, | 
 |             pat: input.call(pat_tuple)?, | 
 |         }) | 
 |     } | 
 |  | 
 |     fn pat_struct(input: ParseStream, path: Path) -> Result<PatStruct> { | 
 |         let content; | 
 |         let brace_token = braced!(content in input); | 
 |  | 
 |         let mut fields = Punctuated::new(); | 
 |         while !content.is_empty() && !content.peek(Token![..]) { | 
 |             let value = content.call(field_pat)?; | 
 |             fields.push_value(value); | 
 |             if content.is_empty() { | 
 |                 break; | 
 |             } | 
 |             let punct: Token![,] = content.parse()?; | 
 |             fields.push_punct(punct); | 
 |         } | 
 |  | 
 |         let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) { | 
 |             Some(content.parse()?) | 
 |         } else { | 
 |             None | 
 |         }; | 
 |  | 
 |         Ok(PatStruct { | 
 |             attrs: Vec::new(), | 
 |             path, | 
 |             brace_token, | 
 |             fields, | 
 |             dot2_token, | 
 |         }) | 
 |     } | 
 |  | 
 |     impl Member { | 
 |         fn is_unnamed(&self) -> bool { | 
 |             match *self { | 
 |                 Member::Named(_) => false, | 
 |                 Member::Unnamed(_) => true, | 
 |             } | 
 |         } | 
 |     } | 
 |  | 
 |     fn field_pat(input: ParseStream) -> Result<FieldPat> { | 
 |         let attrs = input.call(Attribute::parse_outer)?; | 
 |         let boxed: Option<Token![box]> = input.parse()?; | 
 |         let by_ref: Option<Token![ref]> = input.parse()?; | 
 |         let mutability: Option<Token![mut]> = input.parse()?; | 
 |         let member: Member = input.parse()?; | 
 |  | 
 |         if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:]) | 
 |             || member.is_unnamed() | 
 |         { | 
 |             return Ok(FieldPat { | 
 |                 attrs, | 
 |                 member, | 
 |                 colon_token: input.parse()?, | 
 |                 pat: Box::new(multi_pat(input)?), | 
 |             }); | 
 |         } | 
 |  | 
 |         let ident = match member { | 
 |             Member::Named(ident) => ident, | 
 |             Member::Unnamed(_) => unreachable!(), | 
 |         }; | 
 |  | 
 |         let mut pat = Pat::Ident(PatIdent { | 
 |             attrs: Vec::new(), | 
 |             by_ref, | 
 |             mutability, | 
 |             ident: ident.clone(), | 
 |             subpat: None, | 
 |         }); | 
 |  | 
 |         if let Some(boxed) = boxed { | 
 |             pat = Pat::Box(PatBox { | 
 |                 attrs: Vec::new(), | 
 |                 box_token: boxed, | 
 |                 pat: Box::new(pat), | 
 |             }); | 
 |         } | 
 |  | 
 |         Ok(FieldPat { | 
 |             attrs, | 
 |             member: Member::Named(ident), | 
 |             colon_token: None, | 
 |             pat: Box::new(pat), | 
 |         }) | 
 |     } | 
 |  | 
 |     fn pat_range( | 
 |         input: ParseStream, | 
 |         begin: ParseBuffer, | 
 |         qself: Option<QSelf>, | 
 |         path: Path, | 
 |     ) -> Result<Pat> { | 
 |         let limits: RangeLimits = input.parse()?; | 
 |         let hi = input.call(pat_lit_expr)?; | 
 |         if let Some(hi) = hi { | 
 |             Ok(Pat::Range(PatRange { | 
 |                 attrs: Vec::new(), | 
 |                 lo: Box::new(Expr::Path(ExprPath { | 
 |                     attrs: Vec::new(), | 
 |                     qself, | 
 |                     path, | 
 |                 })), | 
 |                 limits, | 
 |                 hi, | 
 |             })) | 
 |         } else { | 
 |             Ok(Pat::Verbatim(verbatim::between(begin, input))) | 
 |         } | 
 |     } | 
 |  | 
 |     fn pat_range_half_open(input: ParseStream, begin: ParseBuffer) -> Result<Pat> { | 
 |         let limits: RangeLimits = input.parse()?; | 
 |         let hi = input.call(pat_lit_expr)?; | 
 |         if hi.is_some() { | 
 |             Ok(Pat::Verbatim(verbatim::between(begin, input))) | 
 |         } else { | 
 |             match limits { | 
 |                 RangeLimits::HalfOpen(dot2_token) => Ok(Pat::Rest(PatRest { | 
 |                     attrs: Vec::new(), | 
 |                     dot2_token, | 
 |                 })), | 
 |                 RangeLimits::Closed(_) => Err(input.error("expected range upper bound")), | 
 |             } | 
 |         } | 
 |     } | 
 |  | 
 |     fn pat_tuple(input: ParseStream) -> Result<PatTuple> { | 
 |         let content; | 
 |         let paren_token = parenthesized!(content in input); | 
 |  | 
 |         let mut elems = Punctuated::new(); | 
 |         while !content.is_empty() { | 
 |             let value = multi_pat(&content)?; | 
 |             elems.push_value(value); | 
 |             if content.is_empty() { | 
 |                 break; | 
 |             } | 
 |             let punct = content.parse()?; | 
 |             elems.push_punct(punct); | 
 |         } | 
 |  | 
 |         Ok(PatTuple { | 
 |             attrs: Vec::new(), | 
 |             paren_token, | 
 |             elems, | 
 |         }) | 
 |     } | 
 |  | 
 |     fn pat_reference(input: ParseStream) -> Result<PatReference> { | 
 |         Ok(PatReference { | 
 |             attrs: Vec::new(), | 
 |             and_token: input.parse()?, | 
 |             mutability: input.parse()?, | 
 |             pat: input.parse()?, | 
 |         }) | 
 |     } | 
 |  | 
 |     fn pat_lit_or_range(input: ParseStream) -> Result<Pat> { | 
 |         let begin = input.fork(); | 
 |         let lo = input.call(pat_lit_expr)?.unwrap(); | 
 |         if input.peek(Token![..]) { | 
 |             let limits: RangeLimits = input.parse()?; | 
 |             let hi = input.call(pat_lit_expr)?; | 
 |             if let Some(hi) = hi { | 
 |                 Ok(Pat::Range(PatRange { | 
 |                     attrs: Vec::new(), | 
 |                     lo, | 
 |                     limits, | 
 |                     hi, | 
 |                 })) | 
 |             } else { | 
 |                 Ok(Pat::Verbatim(verbatim::between(begin, input))) | 
 |             } | 
 |         } else { | 
 |             Ok(Pat::Lit(PatLit { | 
 |                 attrs: Vec::new(), | 
 |                 expr: lo, | 
 |             })) | 
 |         } | 
 |     } | 
 |  | 
 |     fn pat_lit_expr(input: ParseStream) -> Result<Option<Box<Expr>>> { | 
 |         if input.is_empty() | 
 |             || input.peek(Token![|]) | 
 |             || input.peek(Token![=>]) | 
 |             || input.peek(Token![:]) && !input.peek(Token![::]) | 
 |             || input.peek(Token![,]) | 
 |             || input.peek(Token![;]) | 
 |         { | 
 |             return Ok(None); | 
 |         } | 
 |  | 
 |         let neg: Option<Token![-]> = input.parse()?; | 
 |  | 
 |         let lookahead = input.lookahead1(); | 
 |         let expr = if lookahead.peek(Lit) { | 
 |             Expr::Lit(input.parse()?) | 
 |         } else if lookahead.peek(Ident) | 
 |             || lookahead.peek(Token![::]) | 
 |             || lookahead.peek(Token![<]) | 
 |             || lookahead.peek(Token![self]) | 
 |             || lookahead.peek(Token![Self]) | 
 |             || lookahead.peek(Token![super]) | 
 |             || lookahead.peek(Token![crate]) | 
 |         { | 
 |             Expr::Path(input.parse()?) | 
 |         } else { | 
 |             return Err(lookahead.error()); | 
 |         }; | 
 |  | 
 |         Ok(Some(Box::new(if let Some(neg) = neg { | 
 |             Expr::Unary(ExprUnary { | 
 |                 attrs: Vec::new(), | 
 |                 op: UnOp::Neg(neg), | 
 |                 expr: Box::new(expr), | 
 |             }) | 
 |         } else { | 
 |             expr | 
 |         }))) | 
 |     } | 
 |  | 
 |     fn pat_slice(input: ParseStream) -> Result<PatSlice> { | 
 |         let content; | 
 |         let bracket_token = bracketed!(content in input); | 
 |  | 
 |         let mut elems = Punctuated::new(); | 
 |         while !content.is_empty() { | 
 |             let value = multi_pat(&content)?; | 
 |             elems.push_value(value); | 
 |             if content.is_empty() { | 
 |                 break; | 
 |             } | 
 |             let punct = content.parse()?; | 
 |             elems.push_punct(punct); | 
 |         } | 
 |  | 
 |         Ok(PatSlice { | 
 |             attrs: Vec::new(), | 
 |             bracket_token, | 
 |             elems, | 
 |         }) | 
 |     } | 
 |  | 
 |     pub fn multi_pat(input: ParseStream) -> Result<Pat> { | 
 |         multi_pat_impl(input, None) | 
 |     } | 
 |  | 
 |     pub fn multi_pat_with_leading_vert(input: ParseStream) -> Result<Pat> { | 
 |         let leading_vert: Option<Token![|]> = input.parse()?; | 
 |         multi_pat_impl(input, leading_vert) | 
 |     } | 
 |  | 
 |     fn multi_pat_impl(input: ParseStream, leading_vert: Option<Token![|]>) -> Result<Pat> { | 
 |         let mut 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 = Pat::Or(PatOr { | 
 |                 attrs: Vec::new(), | 
 |                 leading_vert, | 
 |                 cases, | 
 |             }); | 
 |         } | 
 |         Ok(pat) | 
 |     } | 
 | } | 
 |  | 
 | #[cfg(feature = "printing")] | 
 | mod printing { | 
 |     use super::*; | 
 |     use crate::attr::FilterAttrs; | 
 |     use proc_macro2::TokenStream; | 
 |     use quote::{ToTokens, TokenStreamExt}; | 
 |  | 
 |     impl ToTokens for PatWild { | 
 |         fn to_tokens(&self, tokens: &mut TokenStream) { | 
 |             tokens.append_all(self.attrs.outer()); | 
 |             self.underscore_token.to_tokens(tokens); | 
 |         } | 
 |     } | 
 |  | 
 |     impl ToTokens for PatIdent { | 
 |         fn to_tokens(&self, tokens: &mut TokenStream) { | 
 |             tokens.append_all(self.attrs.outer()); | 
 |             self.by_ref.to_tokens(tokens); | 
 |             self.mutability.to_tokens(tokens); | 
 |             self.ident.to_tokens(tokens); | 
 |             if let Some((at_token, subpat)) = &self.subpat { | 
 |                 at_token.to_tokens(tokens); | 
 |                 subpat.to_tokens(tokens); | 
 |             } | 
 |         } | 
 |     } | 
 |  | 
 |     impl ToTokens for PatStruct { | 
 |         fn to_tokens(&self, tokens: &mut TokenStream) { | 
 |             tokens.append_all(self.attrs.outer()); | 
 |             self.path.to_tokens(tokens); | 
 |             self.brace_token.surround(tokens, |tokens| { | 
 |                 self.fields.to_tokens(tokens); | 
 |                 // NOTE: We need a comma before the dot2 token if it is present. | 
 |                 if !self.fields.empty_or_trailing() && self.dot2_token.is_some() { | 
 |                     <Token![,]>::default().to_tokens(tokens); | 
 |                 } | 
 |                 self.dot2_token.to_tokens(tokens); | 
 |             }); | 
 |         } | 
 |     } | 
 |  | 
 |     impl ToTokens for PatTupleStruct { | 
 |         fn to_tokens(&self, tokens: &mut TokenStream) { | 
 |             tokens.append_all(self.attrs.outer()); | 
 |             self.path.to_tokens(tokens); | 
 |             self.pat.to_tokens(tokens); | 
 |         } | 
 |     } | 
 |  | 
 |     impl ToTokens for PatType { | 
 |         fn to_tokens(&self, tokens: &mut TokenStream) { | 
 |             tokens.append_all(self.attrs.outer()); | 
 |             self.pat.to_tokens(tokens); | 
 |             self.colon_token.to_tokens(tokens); | 
 |             self.ty.to_tokens(tokens); | 
 |         } | 
 |     } | 
 |  | 
 |     impl ToTokens for PatPath { | 
 |         fn to_tokens(&self, tokens: &mut TokenStream) { | 
 |             tokens.append_all(self.attrs.outer()); | 
 |             private::print_path(tokens, &self.qself, &self.path); | 
 |         } | 
 |     } | 
 |  | 
 |     impl ToTokens for PatTuple { | 
 |         fn to_tokens(&self, tokens: &mut TokenStream) { | 
 |             tokens.append_all(self.attrs.outer()); | 
 |             self.paren_token.surround(tokens, |tokens| { | 
 |                 self.elems.to_tokens(tokens); | 
 |             }); | 
 |         } | 
 |     } | 
 |  | 
 |     impl ToTokens for PatBox { | 
 |         fn to_tokens(&self, tokens: &mut TokenStream) { | 
 |             tokens.append_all(self.attrs.outer()); | 
 |             self.box_token.to_tokens(tokens); | 
 |             self.pat.to_tokens(tokens); | 
 |         } | 
 |     } | 
 |  | 
 |     impl ToTokens for PatReference { | 
 |         fn to_tokens(&self, tokens: &mut TokenStream) { | 
 |             tokens.append_all(self.attrs.outer()); | 
 |             self.and_token.to_tokens(tokens); | 
 |             self.mutability.to_tokens(tokens); | 
 |             self.pat.to_tokens(tokens); | 
 |         } | 
 |     } | 
 |  | 
 |     impl ToTokens for PatRest { | 
 |         fn to_tokens(&self, tokens: &mut TokenStream) { | 
 |             tokens.append_all(self.attrs.outer()); | 
 |             self.dot2_token.to_tokens(tokens); | 
 |         } | 
 |     } | 
 |  | 
 |     impl ToTokens for PatLit { | 
 |         fn to_tokens(&self, tokens: &mut TokenStream) { | 
 |             tokens.append_all(self.attrs.outer()); | 
 |             self.expr.to_tokens(tokens); | 
 |         } | 
 |     } | 
 |  | 
 |     impl ToTokens for PatRange { | 
 |         fn to_tokens(&self, tokens: &mut TokenStream) { | 
 |             tokens.append_all(self.attrs.outer()); | 
 |             self.lo.to_tokens(tokens); | 
 |             match &self.limits { | 
 |                 RangeLimits::HalfOpen(t) => t.to_tokens(tokens), | 
 |                 RangeLimits::Closed(t) => t.to_tokens(tokens), | 
 |             } | 
 |             self.hi.to_tokens(tokens); | 
 |         } | 
 |     } | 
 |  | 
 |     impl ToTokens for PatSlice { | 
 |         fn to_tokens(&self, tokens: &mut TokenStream) { | 
 |             tokens.append_all(self.attrs.outer()); | 
 |             self.bracket_token.surround(tokens, |tokens| { | 
 |                 self.elems.to_tokens(tokens); | 
 |             }); | 
 |         } | 
 |     } | 
 |  | 
 |     impl ToTokens for PatMacro { | 
 |         fn to_tokens(&self, tokens: &mut TokenStream) { | 
 |             tokens.append_all(self.attrs.outer()); | 
 |             self.mac.to_tokens(tokens); | 
 |         } | 
 |     } | 
 |  | 
 |     impl ToTokens for PatOr { | 
 |         fn to_tokens(&self, tokens: &mut TokenStream) { | 
 |             tokens.append_all(self.attrs.outer()); | 
 |             self.leading_vert.to_tokens(tokens); | 
 |             self.cases.to_tokens(tokens); | 
 |         } | 
 |     } | 
 |  | 
 |     impl ToTokens for FieldPat { | 
 |         fn to_tokens(&self, tokens: &mut TokenStream) { | 
 |             tokens.append_all(self.attrs.outer()); | 
 |             if let Some(colon_token) = &self.colon_token { | 
 |                 self.member.to_tokens(tokens); | 
 |                 colon_token.to_tokens(tokens); | 
 |             } | 
 |             self.pat.to_tokens(tokens); | 
 |         } | 
 |     } | 
 | } |