// SPDX-License-Identifier: Apache-2.0 OR MIT use crate::attr::Attribute;use crate::expr::Member;use crate::ident::Ident;use crate::path::{Path, QSelf};use crate::punctuated::Punctuated;use crate::token;use crate::ty::Type;use proc_macro2::TokenStream; pub use crate::expr::{ ExprConst as PatConst, ExprLit as PatLit, ExprMacro as PatMacro, ExprPath as PatPath, ExprRange as PatRange,}; ast_enum_of_structs! { /// A pattern in a local binding, function signature, match expression, or /// various other places. /// /// # Syntax tree enum /// /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums #[cfg_attr(docsrs, doc(cfg(feature = "full")))] #[non_exhaustive] pub enum Pat { /// A const block: `const { ... }`. Const(PatConst), /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`. Ident(PatIdent), /// A literal pattern: `0`. Lit(PatLit), /// A macro in pattern position. Macro(PatMacro), /// A pattern that matches any one of a set of cases. Or(PatOr), /// A parenthesized pattern: `(A | B)`. Paren(PatParen), /// 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), // For testing exhaustiveness in downstream code, use the following idiom: // // match pat { // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))] // // Pat::Box(pat) => {...} // Pat::Ident(pat) => {...} // ... // Pat::Wild(pat) => {...} // // _ => { /* some sane fallback */ } // } // // This way we fail your tests but don't break your library when adding // a variant. You will be notified by a test failure when a variant is // added, so that you can add code to handle it, but your library will // continue to compile and work for downstream users in the interim. }} ast_struct! { /// A 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. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 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 pattern that matches any one of a set of cases. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatOr { pub attrs: Vec<Attribute>, pub leading_vert: Option<Token![|]>, pub cases: Punctuated<Pat, Token![|]>, }} ast_struct! { /// A parenthesized pattern: `(A | B)`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatParen { pub attrs: Vec<Attribute>, pub paren_token: token::Paren, pub pat: Box<Pat>, }} ast_struct! { /// A reference pattern: `&mut var`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 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, ..]`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatRest { pub attrs: Vec<Attribute>, pub dot2_token: Token![..], }} ast_struct! { /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 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, .. }`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatStruct { pub attrs: Vec<Attribute>, pub qself: Option<QSelf>, pub path: Path, pub brace_token: token::Brace, pub fields: Punctuated<FieldPat, Token![,]>, pub rest: Option<PatRest>, }} ast_struct! { /// A tuple pattern: `(a, b)`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 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)`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatTupleStruct { pub attrs: Vec<Attribute>, pub qself: Option<QSelf>, pub path: Path, pub paren_token: token::Paren, pub elems: Punctuated<Pat, Token![,]>, }} ast_struct! { /// A type ascription pattern: `foo: f64`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 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: `_`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 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. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct FieldPat { pub attrs: Vec<Attribute>, pub member: Member, pub colon_token: Option<Token![:]>, pub pat: Box<Pat>, }} #[cfg(feature = "parsing")]pub(crate) mod parsing { use crate::attr::Attribute; use crate::error::{self, Result}; use crate::expr::{ Expr, ExprConst, ExprLit, ExprMacro, ExprPath, ExprRange, Member, RangeLimits, }; use crate::ext::IdentExt as _; use crate::ident::Ident; use crate::lit::Lit; use crate::mac::{self, Macro}; use crate::parse::{Parse, ParseBuffer, ParseStream}; use crate::pat::{ FieldPat, Pat, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice, PatStruct, PatTuple, PatTupleStruct, PatType, PatWild, }; use crate::path::{self, Path, QSelf}; use crate::punctuated::Punctuated; use crate::stmt::Block; use crate::token; use crate::verbatim; use proc_macro2::TokenStream; #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Pat { /// Parse a pattern that does _not_ involve `|` at the top level. /// /// This parser matches the behavior of the `$:pat_param` macro_rules /// matcher, and on editions prior to Rust 2021, the behavior of /// `$:pat`. /// /// In Rust syntax, some examples of where this syntax would occur are /// in the argument pattern of functions and closures. Patterns using /// `|` are not allowed to occur in these positions. /// /// ```compile_fail /// fn f(Some(_) | None: Option<T>) { /// let _ = |Some(_) | None: Option<T>| {}; /// // ^^^^^^^^^^^^^^^^^^^^^^^^^??? :( /// } /// ``` /// /// ```console /// error: top-level or-patterns are not allowed in function parameters /// --> src/main.rs:1:6 /// | /// 1 | fn f(Some(_) | None: Option<T>) { /// | ^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(Some(_) | None)` /// ``` pub fn parse_single(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![..])) || 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]) { pat_box(begin, input) } else if input.peek(Token![-]) || lookahead.peek(Lit) || lookahead.peek(Token![const]) { 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_paren_or_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) } else if lookahead.peek(Token![const]) { input.call(pat_const).map(Pat::Verbatim) } else { Err(lookahead.error()) } } /// Parse a pattern, possibly involving `|`, but not a leading `|`. pub fn parse_multi(input: ParseStream) -> Result<Self> { multi_pat_impl(input, None) } /// Parse a pattern, possibly involving `|`, possibly including a /// leading `|`. /// /// This parser matches the behavior of the Rust 2021 edition's `$:pat` /// macro_rules matcher. /// /// In Rust syntax, an example of where this syntax would occur is in /// the pattern of a `match` arm, where the language permits an optional /// leading `|`, although it is not idiomatic to write one there in /// handwritten code. /// /// ``` /// # let wat = None; /// match wat { /// | None | Some(false) => {} /// | Some(true) => {} /// } /// ``` /// /// The compiler accepts it only to facilitate some situations in /// macro-generated code where a macro author might need to write: /// /// ``` /// # macro_rules! doc { /// # ($value:expr, ($($conditions1:pat),*), ($($conditions2:pat),*), $then:expr) => { /// match $value { /// $(| $conditions1)* $(| $conditions2)* => $then /// } /// # }; /// # } /// # /// # doc!(true, (true), (false), {}); /// # doc!(true, (), (true, false), {}); /// # doc!(true, (true, false), (), {}); /// ``` /// /// Expressing the same thing correctly in the case that either one (but /// not both) of `$conditions1` and `$conditions2` might be empty, /// without leading `|`, is complex. /// /// Use [`Pat::parse_multi`] instead if you are not intending to support /// macro-generated macro input. pub fn parse_multi_with_leading_vert(input: ParseStream) -> Result<Self> { let leading_vert: Option<Token![|]> = input.parse()?; multi_pat_impl(input, leading_vert) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for PatType { fn parse(input: ParseStream) -> Result<Self> { Ok(PatType { attrs: Vec::new(), pat: Box::new(Pat::parse_single(input)?), colon_token: input.parse()?, ty: input.parse()?, }) } } fn multi_pat_impl(input: ParseStream, leading_vert: Option<Token![|]>) -> Result<Pat> { let mut pat = Pat::parse_single(input)?; 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::parse_single(input)?; cases.push_value(pat); } pat = Pat::Or(PatOr { attrs: Vec::new(), leading_vert, cases, }); } Ok(pat) } fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> { let expr_style = true; let (qself, path) = path::parsing::qpath(input, expr_style)?; if qself.is_none() && input.peek(Token![!]) && !input.peek(Token![!=]) && path.is_mod_style() { let bang_token: Token![!] = input.parse()?; let (delimiter, tokens) = mac::parse_delimiter(input)?; return Ok(Pat::Macro(ExprMacro { attrs: Vec::new(), mac: Macro { path, bang_token, delimiter, tokens, }, })); } if input.peek(token::Brace) { pat_struct(input, qself, path).map(Pat::Struct) } else if input.peek(token::Paren) { pat_tuple_struct(input, qself, path).map(Pat::TupleStruct) } else if input.peek(Token![..]) { pat_range(input, qself, path) } else { Ok(Pat::Path(ExprPath { attrs: Vec::new(), qself, path, })) } } fn pat_wild(input: ParseStream) -> Result<PatWild> { Ok(PatWild { attrs: Vec::new(), underscore_token: input.parse()?, }) } fn pat_box(begin: ParseBuffer, input: ParseStream) -> Result<Pat> { input.parse::<Token![box]>()?; Pat::parse_single(input)?; Ok(Pat::Verbatim(verbatim::between(&begin, input))) } fn pat_ident(input: ParseStream) -> Result<PatIdent> { Ok(PatIdent { attrs: Vec::new(), by_ref: input.parse()?, mutability: input.parse()?, ident: { if input.peek(Token![self]) { input.call(Ident::parse_any)? } else { input.parse()? } }, subpat: { if input.peek(Token![@]) { let at_token: Token![@] = input.parse()?; let subpat = Pat::parse_single(input)?; Some((at_token, Box::new(subpat))) } else { None } }, }) } fn pat_tuple_struct( input: ParseStream, qself: Option<QSelf>, path: Path, ) -> Result<PatTupleStruct> { let content;Lines 1–500 of 957. Load more
// SPDX-License-Identifier: Apache-2.0 OR MIT use crate::attr::Attribute; use crate::expr::Member; use crate::ident::Ident; use crate::path::{Path, QSelf}; use crate::punctuated::Punctuated; use crate::token; use crate::ty::Type; use proc_macro2::TokenStream; pub use crate::expr::{ ExprConst as PatConst, ExprLit as PatLit, ExprMacro as PatMacro, ExprPath as PatPath, ExprRange as PatRange, }; ast_enum_of_structs! { /// A pattern in a local binding, function signature, match expression, or /// various other places. /// /// # Syntax tree enum /// /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums #[cfg_attr(docsrs, doc(cfg(feature = "full")))] #[non_exhaustive] pub enum Pat { /// A const block: `const { ... }`. Const(PatConst), /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`. Ident(PatIdent), /// A literal pattern: `0`. Lit(PatLit), /// A macro in pattern position. Macro(PatMacro), /// A pattern that matches any one of a set of cases. Or(PatOr), /// A parenthesized pattern: `(A | B)`. Paren(PatParen), /// 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), // For testing exhaustiveness in downstream code, use the following idiom: // // match pat { // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))] // // Pat::Box(pat) => {...} // Pat::Ident(pat) => {...} // ... // Pat::Wild(pat) => {...} // // _ => { /* some sane fallback */ } // } // // This way we fail your tests but don't break your library when adding // a variant. You will be notified by a test failure when a variant is // added, so that you can add code to handle it, but your library will // continue to compile and work for downstream users in the interim. } } ast_struct! { /// A 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. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 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 pattern that matches any one of a set of cases. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatOr { pub attrs: Vec<Attribute>, pub leading_vert: Option<Token![|]>, pub cases: Punctuated<Pat, Token![|]>, } } ast_struct! { /// A parenthesized pattern: `(A | B)`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatParen { pub attrs: Vec<Attribute>, pub paren_token: token::Paren, pub pat: Box<Pat>, } } ast_struct! { /// A reference pattern: `&mut var`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 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, ..]`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatRest { pub attrs: Vec<Attribute>, pub dot2_token: Token![..], } } ast_struct! { /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 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, .. }`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatStruct { pub attrs: Vec<Attribute>, pub qself: Option<QSelf>, pub path: Path, pub brace_token: token::Brace, pub fields: Punctuated<FieldPat, Token![,]>, pub rest: Option<PatRest>, } } ast_struct! { /// A tuple pattern: `(a, b)`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 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)`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatTupleStruct { pub attrs: Vec<Attribute>, pub qself: Option<QSelf>, pub path: Path, pub paren_token: token::Paren, pub elems: Punctuated<Pat, Token![,]>, } } ast_struct! { /// A type ascription pattern: `foo: f64`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 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: `_`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 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. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct FieldPat { pub attrs: Vec<Attribute>, pub member: Member, pub colon_token: Option<Token![:]>, pub pat: Box<Pat>, } } #[cfg(feature = "parsing")] pub(crate) mod parsing { use crate::attr::Attribute; use crate::error::{self, Result}; use crate::expr::{ Expr, ExprConst, ExprLit, ExprMacro, ExprPath, ExprRange, Member, RangeLimits, }; use crate::ext::IdentExt as _; use crate::ident::Ident; use crate::lit::Lit; use crate::mac::{self, Macro}; use crate::parse::{Parse, ParseBuffer, ParseStream}; use crate::pat::{ FieldPat, Pat, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice, PatStruct, PatTuple, PatTupleStruct, PatType, PatWild, }; use crate::path::{self, Path, QSelf}; use crate::punctuated::Punctuated; use crate::stmt::Block; use crate::token; use crate::verbatim; use proc_macro2::TokenStream; #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Pat { /// Parse a pattern that does _not_ involve `|` at the top level. /// /// This parser matches the behavior of the `$:pat_param` macro_rules /// matcher, and on editions prior to Rust 2021, the behavior of /// `$:pat`. /// /// In Rust syntax, some examples of where this syntax would occur are /// in the argument pattern of functions and closures. Patterns using /// `|` are not allowed to occur in these positions. /// /// ```compile_fail /// fn f(Some(_) | None: Option<T>) { /// let _ = |Some(_) | None: Option<T>| {}; /// // ^^^^^^^^^^^^^^^^^^^^^^^^^??? :( /// } /// ``` /// /// ```console /// error: top-level or-patterns are not allowed in function parameters /// --> src/main.rs:1:6 /// | /// 1 | fn f(Some(_) | None: Option<T>) { /// | ^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(Some(_) | None)` /// ``` pub fn parse_single(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![..])) || 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]) { pat_box(begin, input) } else if input.peek(Token![-]) || lookahead.peek(Lit) || lookahead.peek(Token![const]) { 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_paren_or_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) } else if lookahead.peek(Token![const]) { input.call(pat_const).map(Pat::Verbatim) } else { Err(lookahead.error()) } } /// Parse a pattern, possibly involving `|`, but not a leading `|`. pub fn parse_multi(input: ParseStream) -> Result<Self> { multi_pat_impl(input, None) } /// Parse a pattern, possibly involving `|`, possibly including a /// leading `|`. /// /// This parser matches the behavior of the Rust 2021 edition's `$:pat` /// macro_rules matcher. /// /// In Rust syntax, an example of where this syntax would occur is in /// the pattern of a `match` arm, where the language permits an optional /// leading `|`, although it is not idiomatic to write one there in /// handwritten code. /// /// ``` /// # let wat = None; /// match wat { /// | None | Some(false) => {} /// | Some(true) => {} /// } /// ``` /// /// The compiler accepts it only to facilitate some situations in /// macro-generated code where a macro author might need to write: /// /// ``` /// # macro_rules! doc { /// # ($value:expr, ($($conditions1:pat),*), ($($conditions2:pat),*), $then:expr) => { /// match $value { /// $(| $conditions1)* $(| $conditions2)* => $then /// } /// # }; /// # } /// # /// # doc!(true, (true), (false), {}); /// # doc!(true, (), (true, false), {}); /// # doc!(true, (true, false), (), {}); /// ``` /// /// Expressing the same thing correctly in the case that either one (but /// not both) of `$conditions1` and `$conditions2` might be empty, /// without leading `|`, is complex. /// /// Use [`Pat::parse_multi`] instead if you are not intending to support /// macro-generated macro input. pub fn parse_multi_with_leading_vert(input: ParseStream) -> Result<Self> { let leading_vert: Option<Token![|]> = input.parse()?; multi_pat_impl(input, leading_vert) } } #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for PatType { fn parse(input: ParseStream) -> Result<Self> { Ok(PatType { attrs: Vec::new(), pat: Box::new(Pat::parse_single(input)?), colon_token: input.parse()?, ty: input.parse()?, }) } } fn multi_pat_impl(input: ParseStream, leading_vert: Option<Token![|]>) -> Result<Pat> { let mut pat = Pat::parse_single(input)?; 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::parse_single(input)?; cases.push_value(pat); } pat = Pat::Or(PatOr { attrs: Vec::new(), leading_vert, cases, }); } Ok(pat) } fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> { let expr_style = true; let (qself, path) = path::parsing::qpath(input, expr_style)?; if qself.is_none() && input.peek(Token![!]) && !input.peek(Token![!=]) && path.is_mod_style() { let bang_token: Token![!] = input.parse()?; let (delimiter, tokens) = mac::parse_delimiter(input)?; return Ok(Pat::Macro(ExprMacro { attrs: Vec::new(), mac: Macro { path, bang_token, delimiter, tokens, }, })); } if input.peek(token::Brace) { pat_struct(input, qself, path).map(Pat::Struct) } else if input.peek(token::Paren) { pat_tuple_struct(input, qself, path).map(Pat::TupleStruct) } else if input.peek(Token![..]) { pat_range(input, qself, path) } else { Ok(Pat::Path(ExprPath { attrs: Vec::new(), qself, path, })) } } fn pat_wild(input: ParseStream) -> Result<PatWild> { Ok(PatWild { attrs: Vec::new(), underscore_token: input.parse()?, }) } fn pat_box(begin: ParseBuffer, input: ParseStream) -> Result<Pat> { input.parse::<Token![box]>()?; Pat::parse_single(input)?; Ok(Pat::Verbatim(verbatim::between(&begin, input))) } fn pat_ident(input: ParseStream) -> Result<PatIdent> { Ok(PatIdent { attrs: Vec::new(), by_ref: input.parse()?, mutability: input.parse()?, ident: { if input.peek(Token![self]) { input.call(Ident::parse_any)? } else { input.parse()? } }, subpat: { if input.peek(Token![@]) { let at_token: Token![@] = input.parse()?; let subpat = Pat::parse_single(input)?; Some((at_token, Box::new(subpat))) } else { None } }, }) } fn pat_tuple_struct( input: ParseStream, qself: Option<QSelf>, path: Path, ) -> Result<PatTupleStruct> { let content;