summaryrefslogtreecommitdiffstats
path: root/third_party/rust/syn/src/pat.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/syn/src/pat.rs')
-rw-r--r--third_party/rust/syn/src/pat.rs927
1 files changed, 927 insertions, 0 deletions
diff --git a/third_party/rust/syn/src/pat.rs b/third_party/rust/syn/src/pat.rs
new file mode 100644
index 0000000000..b279186aa0
--- /dev/null
+++ b/third_party/rust/syn/src/pat.rs
@@ -0,0 +1,927 @@
+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]: Expr#syntax-tree-enums
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
+ #[cfg_attr(not(syn_no_non_exhaustive), non_exhaustive)]
+ 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),
+
+ // Not public API.
+ //
+ // For testing exhaustiveness in downstream code, use the following idiom:
+ //
+ // match pat {
+ // Pat::Box(pat) => {...}
+ // Pat::Ident(pat) => {...}
+ // ...
+ // Pat::Wild(pat) => {...}
+ //
+ // #[cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
+ // _ => { /* 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.
+ #[cfg(syn_no_non_exhaustive)]
+ #[doc(hidden)]
+ __NonExhaustive,
+ }
+}
+
+ast_struct! {
+ /// A box pattern: `box v`.
+ ///
+ /// *This type is available only if Syn is built with the `"full"` feature.*
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
+ 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.*
+ #[cfg_attr(doc_cfg, 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 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.*
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
+ 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.*
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
+ 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.*
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
+ 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.*
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
+ 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.*
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
+ 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.*
+ #[cfg_attr(doc_cfg, 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, ..]`
+ ///
+ /// *This type is available only if Syn is built with the `"full"` feature.*
+ #[cfg_attr(doc_cfg, 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]`.
+ ///
+ /// *This type is available only if Syn is built with the `"full"` feature.*
+ #[cfg_attr(doc_cfg, 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, .. }`.
+ ///
+ /// *This type is available only if Syn is built with the `"full"` feature.*
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
+ 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.*
+ #[cfg_attr(doc_cfg, 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)`.
+ ///
+ /// *This type is available only if Syn is built with the `"full"` feature.*
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
+ 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.*
+ #[cfg_attr(doc_cfg, 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: `_`.
+ ///
+ /// *This type is available only if Syn is built with the `"full"` feature.*
+ #[cfg_attr(doc_cfg, 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.
+ ///
+ /// *This type is available only if Syn is built with the `"full"` feature.*
+ #[cfg_attr(doc_cfg, 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 mod parsing {
+ use super::*;
+ use crate::ext::IdentExt;
+ use crate::parse::{Parse, ParseBuffer, ParseStream, Result};
+ use crate::path;
+
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
+ impl Parse for Pat {
+ fn parse(input: ParseStream) -> Result<Self> {
+ let begin = input.fork();
+ let lookahead = input.lookahead1();
+ if {
+ let ahead = input.fork();
+ ahead.parse::<Option<Ident>>()?.is_some()
+ && (ahead.peek(Token![::])
+ || ahead.peek(Token![!])
+ || ahead.peek(token::Brace)
+ || ahead.peek(token::Paren)
+ || ahead.peek(Token![..])
+ && ahead.parse::<RangeLimits>().is_ok()
+ && !(ahead.is_empty() || ahead.peek(Token![,])))
+ } || {
+ let ahead = input.fork();
+ ahead.parse::<Option<Token![self]>>()?.is_some() && ahead.peek(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) || 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_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 if lookahead.peek(Token![const]) {
+ input.call(pat_const).map(Pat::Verbatim)
+ } 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 qself.is_none() && 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) {
+ let pat = pat_struct(begin.fork(), input, path)?;
+ if qself.is_some() {
+ Ok(Pat::Verbatim(verbatim::between(begin, input)))
+ } else {
+ Ok(pat)
+ }
+ } else if input.peek(token::Paren) {
+ let pat = pat_tuple_struct(input, path)?;
+ if qself.is_some() {
+ Ok(Pat::Verbatim(verbatim::between(begin, input)))
+ } else {
+ Ok(Pat::TupleStruct(pat))
+ }
+ } 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(begin: ParseBuffer, input: ParseStream, path: Path) -> Result<Pat> {
+ let content;
+ let brace_token = braced!(content in input);
+
+ let mut fields = Punctuated::new();
+ let mut dot2_token = None;
+ while !content.is_empty() {
+ let attrs = content.call(Attribute::parse_outer)?;
+ if content.peek(Token![..]) {
+ dot2_token = Some(content.parse()?);
+ if !attrs.is_empty() {
+ return Ok(Pat::Verbatim(verbatim::between(begin, input)));
+ }
+ break;
+ }
+ let mut value = content.call(field_pat)?;
+ value.attrs = attrs;
+ fields.push_value(value);
+ if content.is_empty() {
+ break;
+ }
+ let punct: Token![,] = content.parse()?;
+ fields.push_punct(punct);
+ }
+
+ Ok(Pat::Struct(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 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: Vec::new(),
+ member,
+ colon_token: input.parse()?,
+ pat: Box::new(multi_pat_with_leading_vert(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: Vec::new(),
+ 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_with_leading_vert(&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 if let Expr::Verbatim(verbatim) = *lo {
+ Ok(Pat::Verbatim(verbatim))
+ } 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 if lookahead.peek(Token![const]) {
+ Expr::Verbatim(input.call(expr::parsing::expr_const)?)
+ } 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_with_leading_vert(&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,
+ })
+ }
+
+ fn pat_const(input: ParseStream) -> Result<TokenStream> {
+ let begin = input.fork();
+ input.parse::<Token![const]>()?;
+
+ let content;
+ braced!(content in input);
+ content.call(Attribute::parse_inner)?;
+ content.call(Block::parse_within)?;
+
+ Ok(verbatim::between(begin, input))
+ }
+
+ 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};
+
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
+ impl ToTokens for PatWild {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.underscore_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
+ 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);
+ }
+ }
+ }
+
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
+ 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);
+ });
+ }
+ }
+
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
+ 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);
+ }
+ }
+
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
+ 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);
+ }
+ }
+
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
+ impl ToTokens for PatPath {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ path::printing::print_path(tokens, &self.qself, &self.path);
+ }
+ }
+
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
+ 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);
+ });
+ }
+ }
+
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
+ 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);
+ }
+ }
+
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
+ 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);
+ }
+ }
+
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
+ impl ToTokens for PatRest {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.dot2_token.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
+ impl ToTokens for PatLit {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.expr.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
+ impl ToTokens for PatRange {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.lo.to_tokens(tokens);
+ self.limits.to_tokens(tokens);
+ self.hi.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
+ 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);
+ });
+ }
+ }
+
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
+ impl ToTokens for PatMacro {
+ fn to_tokens(&self, tokens: &mut TokenStream) {
+ tokens.append_all(self.attrs.outer());
+ self.mac.to_tokens(tokens);
+ }
+ }
+
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
+ 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);
+ }
+ }
+
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
+ 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);
+ }
+ }
+}