syn/
pat.rs

1use crate::attr::Attribute;
2use crate::expr::Member;
3use crate::ident::Ident;
4use crate::path::{Path, QSelf};
5use crate::punctuated::Punctuated;
6use crate::token;
7use crate::ty::Type;
8use alloc::boxed::Box;
9use alloc::vec::Vec;
10use proc_macro2::TokenStream;
11
12pub use crate::expr::{
13    ExprConst as PatConst, ExprLit as PatLit, ExprMacro as PatMacro, ExprPath as PatPath,
14    ExprRange as PatRange,
15};
16
17#[doc =
r" A pattern in a local binding, function signature, match expression, or"]
#[doc = r" various other places."]
#[doc = r""]
#[doc = r" # Syntax tree enum"]
#[doc = r""]
#[doc = r" This type is a [syntax tree enum]."]
#[doc = r""]
#[doc = r" [syntax tree enum]: crate::expr::Expr#syntax-tree-enums"]
#[non_exhaustive]
pub enum Pat {

    #[doc = r" A const block: `const { ... }`."]
    Const(PatConst),

    #[doc =
    r" A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`."]
    Ident(PatIdent),

    #[doc = r" A literal pattern: `0`."]
    Lit(PatLit),

    #[doc = r" A macro in pattern position."]
    Macro(PatMacro),

    #[doc = r" A pattern that matches any one of a set of cases."]
    Or(PatOr),

    #[doc = r" A parenthesized pattern: `(A | B)`."]
    Paren(PatParen),

    #[doc = r" A path pattern like `Color::Red`, optionally qualified with a"]
    #[doc = r" self-type."]
    #[doc = r""]
    #[doc =
    r" Unqualified path patterns can legally refer to variants, structs,"]
    #[doc =
    r" constants or associated constants. Qualified path patterns like"]
    #[doc =
    r" `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to"]
    #[doc = r" associated constants."]
    Path(PatPath),

    #[doc = r" A range pattern: `1..=2`."]
    Range(PatRange),

    #[doc = r" A reference pattern: `&mut var`."]
    Reference(PatReference),

    #[doc = r" The dots in a tuple or slice pattern: `[0, 1, ..]`."]
    Rest(PatRest),

    #[doc =
    r" A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`."]
    Slice(PatSlice),

    #[doc = r" A struct or struct variant pattern: `Variant { x, y, .. }`."]
    Struct(PatStruct),

    #[doc = r" A tuple pattern: `(a, b)`."]
    Tuple(PatTuple),

    #[doc =
    r" A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`."]
    TupleStruct(PatTupleStruct),

    #[doc = r" A type ascription pattern: `foo: f64`."]
    Type(PatType),

    #[doc = r" Tokens in pattern position not interpreted by Syn."]
    Verbatim(TokenStream),

    #[doc = r" A pattern that matches any value: `_`."]
    Wild(PatWild),
}
impl From<PatConst> for Pat {
    fn from(e: PatConst) -> Pat { Pat::Const(e) }
}
impl From<PatIdent> for Pat {
    fn from(e: PatIdent) -> Pat { Pat::Ident(e) }
}
impl From<PatLit> for Pat {
    fn from(e: PatLit) -> Pat { Pat::Lit(e) }
}
impl From<PatMacro> for Pat {
    fn from(e: PatMacro) -> Pat { Pat::Macro(e) }
}
impl From<PatOr> for Pat {
    fn from(e: PatOr) -> Pat { Pat::Or(e) }
}
impl From<PatParen> for Pat {
    fn from(e: PatParen) -> Pat { Pat::Paren(e) }
}
impl From<PatPath> for Pat {
    fn from(e: PatPath) -> Pat { Pat::Path(e) }
}
impl From<PatRange> for Pat {
    fn from(e: PatRange) -> Pat { Pat::Range(e) }
}
impl From<PatReference> for Pat {
    fn from(e: PatReference) -> Pat { Pat::Reference(e) }
}
impl From<PatRest> for Pat {
    fn from(e: PatRest) -> Pat { Pat::Rest(e) }
}
impl From<PatSlice> for Pat {
    fn from(e: PatSlice) -> Pat { Pat::Slice(e) }
}
impl From<PatStruct> for Pat {
    fn from(e: PatStruct) -> Pat { Pat::Struct(e) }
}
impl From<PatTuple> for Pat {
    fn from(e: PatTuple) -> Pat { Pat::Tuple(e) }
}
impl From<PatTupleStruct> for Pat {
    fn from(e: PatTupleStruct) -> Pat { Pat::TupleStruct(e) }
}
impl From<PatType> for Pat {
    fn from(e: PatType) -> Pat { Pat::Type(e) }
}
impl From<PatWild> for Pat {
    fn from(e: PatWild) -> Pat { Pat::Wild(e) }
}
impl ::quote::ToTokens for Pat {
    fn to_tokens(&self, tokens: &mut ::proc_macro2::TokenStream) {
        match self {
            Pat::Const(_e) => _e.to_tokens(tokens),
            Pat::Ident(_e) => _e.to_tokens(tokens),
            Pat::Lit(_e) => _e.to_tokens(tokens),
            Pat::Macro(_e) => _e.to_tokens(tokens),
            Pat::Or(_e) => _e.to_tokens(tokens),
            Pat::Paren(_e) => _e.to_tokens(tokens),
            Pat::Path(_e) => _e.to_tokens(tokens),
            Pat::Range(_e) => _e.to_tokens(tokens),
            Pat::Reference(_e) => _e.to_tokens(tokens),
            Pat::Rest(_e) => _e.to_tokens(tokens),
            Pat::Slice(_e) => _e.to_tokens(tokens),
            Pat::Struct(_e) => _e.to_tokens(tokens),
            Pat::Tuple(_e) => _e.to_tokens(tokens),
            Pat::TupleStruct(_e) => _e.to_tokens(tokens),
            Pat::Type(_e) => _e.to_tokens(tokens),
            Pat::Verbatim(_e) => _e.to_tokens(tokens),
            Pat::Wild(_e) => _e.to_tokens(tokens),
        }
    }
}ast_enum_of_structs! {
18    /// A pattern in a local binding, function signature, match expression, or
19    /// various other places.
20    ///
21    /// # Syntax tree enum
22    ///
23    /// This type is a [syntax tree enum].
24    ///
25    /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
26    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
27    #[non_exhaustive]
28    pub enum Pat {
29        /// A const block: `const { ... }`.
30        Const(PatConst),
31
32        /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
33        Ident(PatIdent),
34
35        /// A literal pattern: `0`.
36        Lit(PatLit),
37
38        /// A macro in pattern position.
39        Macro(PatMacro),
40
41        /// A pattern that matches any one of a set of cases.
42        Or(PatOr),
43
44        /// A parenthesized pattern: `(A | B)`.
45        Paren(PatParen),
46
47        /// A path pattern like `Color::Red`, optionally qualified with a
48        /// self-type.
49        ///
50        /// Unqualified path patterns can legally refer to variants, structs,
51        /// constants or associated constants. Qualified path patterns like
52        /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
53        /// associated constants.
54        Path(PatPath),
55
56        /// A range pattern: `1..=2`.
57        Range(PatRange),
58
59        /// A reference pattern: `&mut var`.
60        Reference(PatReference),
61
62        /// The dots in a tuple or slice pattern: `[0, 1, ..]`.
63        Rest(PatRest),
64
65        /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`.
66        Slice(PatSlice),
67
68        /// A struct or struct variant pattern: `Variant { x, y, .. }`.
69        Struct(PatStruct),
70
71        /// A tuple pattern: `(a, b)`.
72        Tuple(PatTuple),
73
74        /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
75        TupleStruct(PatTupleStruct),
76
77        /// A type ascription pattern: `foo: f64`.
78        Type(PatType),
79
80        /// Tokens in pattern position not interpreted by Syn.
81        Verbatim(TokenStream),
82
83        /// A pattern that matches any value: `_`.
84        Wild(PatWild),
85
86        // For testing exhaustiveness in downstream code, use the following idiom:
87        //
88        //     match pat {
89        //         #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
90        //
91        //         Pat::Box(pat) => {...}
92        //         Pat::Ident(pat) => {...}
93        //         ...
94        //         Pat::Wild(pat) => {...}
95        //
96        //         _ => { /* some sane fallback */ }
97        //     }
98        //
99        // This way we fail your tests but don't break your library when adding
100        // a variant. You will be notified by a test failure when a variant is
101        // added, so that you can add code to handle it, but your library will
102        // continue to compile and work for downstream users in the interim.
103    }
104}
105
106#[doc =
r" A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`."]
#[doc = r""]
#[doc =
r" It may also be a unit struct or struct variant (e.g. `None`), or a"]
#[doc = r" constant; these cannot be distinguished syntactically."]
pub struct PatIdent {
    pub attrs: Vec<Attribute>,
    pub by_ref: Option<crate::token::Ref>,
    pub mutability: Option<crate::token::Mut>,
    pub ident: Ident,
    pub subpat: Option<(crate::token::At, Box<Pat>)>,
}ast_struct! {
107    /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
108    ///
109    /// It may also be a unit struct or struct variant (e.g. `None`), or a
110    /// constant; these cannot be distinguished syntactically.
111    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
112    pub struct PatIdent {
113        pub attrs: Vec<Attribute>,
114        pub by_ref: Option<Token![ref]>,
115        pub mutability: Option<Token![mut]>,
116        pub ident: Ident,
117        pub subpat: Option<(Token![@], Box<Pat>)>,
118    }
119}
120
121#[doc = r" A pattern that matches any one of a set of cases."]
pub struct PatOr {
    pub attrs: Vec<Attribute>,
    pub leading_vert: Option<crate::token::Or>,
    pub cases: Punctuated<Pat, crate::token::Or>,
}ast_struct! {
122    /// A pattern that matches any one of a set of cases.
123    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
124    pub struct PatOr {
125        pub attrs: Vec<Attribute>,
126        pub leading_vert: Option<Token![|]>,
127        pub cases: Punctuated<Pat, Token![|]>,
128    }
129}
130
131#[doc = r" A parenthesized pattern: `(A | B)`."]
pub struct PatParen {
    pub attrs: Vec<Attribute>,
    pub paren_token: token::Paren,
    pub pat: Box<Pat>,
}ast_struct! {
132    /// A parenthesized pattern: `(A | B)`.
133    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
134    pub struct PatParen {
135        pub attrs: Vec<Attribute>,
136        pub paren_token: token::Paren,
137        pub pat: Box<Pat>,
138    }
139}
140
141#[doc = r" A reference pattern: `&mut var`."]
pub struct PatReference {
    pub attrs: Vec<Attribute>,
    pub and_token: crate::token::And,
    pub mutability: Option<crate::token::Mut>,
    pub pat: Box<Pat>,
}ast_struct! {
142    /// A reference pattern: `&mut var`.
143    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
144    pub struct PatReference {
145        pub attrs: Vec<Attribute>,
146        pub and_token: Token![&],
147        pub mutability: Option<Token![mut]>,
148        pub pat: Box<Pat>,
149    }
150}
151
152#[doc = r" The dots in a tuple or slice pattern: `[0, 1, ..]`."]
pub struct PatRest {
    pub attrs: Vec<Attribute>,
    pub dot2_token: crate::token::DotDot,
}ast_struct! {
153    /// The dots in a tuple or slice pattern: `[0, 1, ..]`.
154    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
155    pub struct PatRest {
156        pub attrs: Vec<Attribute>,
157        pub dot2_token: Token![..],
158    }
159}
160
161#[doc = r" A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`."]
pub struct PatSlice {
    pub attrs: Vec<Attribute>,
    pub bracket_token: token::Bracket,
    pub elems: Punctuated<Pat, crate::token::Comma>,
}ast_struct! {
162    /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`.
163    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
164    pub struct PatSlice {
165        pub attrs: Vec<Attribute>,
166        pub bracket_token: token::Bracket,
167        pub elems: Punctuated<Pat, Token![,]>,
168    }
169}
170
171#[doc = r" A struct or struct variant pattern: `Variant { x, y, .. }`."]
pub struct PatStruct {
    pub attrs: Vec<Attribute>,
    pub qself: Option<QSelf>,
    pub path: Path,
    pub brace_token: token::Brace,
    pub fields: Punctuated<FieldPat, crate::token::Comma>,
    pub rest: Option<PatRest>,
}ast_struct! {
172    /// A struct or struct variant pattern: `Variant { x, y, .. }`.
173    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
174    pub struct PatStruct {
175        pub attrs: Vec<Attribute>,
176        pub qself: Option<QSelf>,
177        pub path: Path,
178        pub brace_token: token::Brace,
179        pub fields: Punctuated<FieldPat, Token![,]>,
180        pub rest: Option<PatRest>,
181    }
182}
183
184#[doc = r" A tuple pattern: `(a, b)`."]
pub struct PatTuple {
    pub attrs: Vec<Attribute>,
    pub paren_token: token::Paren,
    pub elems: Punctuated<Pat, crate::token::Comma>,
}ast_struct! {
185    /// A tuple pattern: `(a, b)`.
186    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
187    pub struct PatTuple {
188        pub attrs: Vec<Attribute>,
189        pub paren_token: token::Paren,
190        pub elems: Punctuated<Pat, Token![,]>,
191    }
192}
193
194#[doc = r" A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`."]
pub struct PatTupleStruct {
    pub attrs: Vec<Attribute>,
    pub qself: Option<QSelf>,
    pub path: Path,
    pub paren_token: token::Paren,
    pub elems: Punctuated<Pat, crate::token::Comma>,
}ast_struct! {
195    /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
196    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
197    pub struct PatTupleStruct {
198        pub attrs: Vec<Attribute>,
199        pub qself: Option<QSelf>,
200        pub path: Path,
201        pub paren_token: token::Paren,
202        pub elems: Punctuated<Pat, Token![,]>,
203    }
204}
205
206#[doc = r" A type ascription pattern: `foo: f64`."]
pub struct PatType {
    pub attrs: Vec<Attribute>,
    pub pat: Box<Pat>,
    pub colon_token: crate::token::Colon,
    pub ty: Box<Type>,
}ast_struct! {
207    /// A type ascription pattern: `foo: f64`.
208    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
209    pub struct PatType {
210        pub attrs: Vec<Attribute>,
211        pub pat: Box<Pat>,
212        pub colon_token: Token![:],
213        pub ty: Box<Type>,
214    }
215}
216
217#[doc = r" A pattern that matches any value: `_`."]
pub struct PatWild {
    pub attrs: Vec<Attribute>,
    pub underscore_token: crate::token::Underscore,
}ast_struct! {
218    /// A pattern that matches any value: `_`.
219    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
220    pub struct PatWild {
221        pub attrs: Vec<Attribute>,
222        pub underscore_token: Token![_],
223    }
224}
225
226#[doc = r" A single field in a struct pattern."]
#[doc = r""]
#[doc =
r" Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated"]
#[doc =
r" the same as `x: x, y: ref y, z: ref mut z` but there is no colon token."]
pub struct FieldPat {
    pub attrs: Vec<Attribute>,
    pub member: Member,
    pub colon_token: Option<crate::token::Colon>,
    pub pat: Box<Pat>,
}ast_struct! {
227    /// A single field in a struct pattern.
228    ///
229    /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
230    /// the same as `x: x, y: ref y, z: ref mut z` but there is no colon token.
231    #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
232    pub struct FieldPat {
233        pub attrs: Vec<Attribute>,
234        pub member: Member,
235        pub colon_token: Option<Token![:]>,
236        pub pat: Box<Pat>,
237    }
238}
239
240#[cfg(feature = "parsing")]
241pub(crate) mod parsing {
242    use crate::attr::Attribute;
243    use crate::error::{self, Result};
244    use crate::expr::{
245        Expr, ExprConst, ExprLit, ExprMacro, ExprPath, ExprRange, Member, RangeLimits,
246    };
247    use crate::ext::IdentExt as _;
248    use crate::ident::Ident;
249    use crate::lit::Lit;
250    use crate::mac::{self, Macro};
251    use crate::parse::{Parse, ParseBuffer, ParseStream};
252    use crate::pat::{
253        FieldPat, Pat, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice, PatStruct,
254        PatTuple, PatTupleStruct, PatType, PatWild,
255    };
256    use crate::path::{self, Path, QSelf};
257    use crate::punctuated::Punctuated;
258    use crate::stmt::Block;
259    use crate::token;
260    use crate::verbatim;
261    use alloc::boxed::Box;
262    use alloc::vec::Vec;
263    use proc_macro2::TokenStream;
264
265    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
266    impl Pat {
267        /// Parse a pattern that does _not_ involve `|` at the top level.
268        ///
269        /// This parser matches the behavior of the `$:pat_param` macro_rules
270        /// matcher, and on editions prior to Rust 2021, the behavior of
271        /// `$:pat`.
272        ///
273        /// In Rust syntax, some examples of where this syntax would occur are
274        /// in the argument pattern of functions and closures. Patterns using
275        /// `|` are not allowed to occur in these positions.
276        ///
277        /// ```compile_fail
278        /// fn f(Some(_) | None: Option<T>) {
279        ///     let _ = |Some(_) | None: Option<T>| {};
280        ///     //       ^^^^^^^^^^^^^^^^^^^^^^^^^??? :(
281        /// }
282        /// ```
283        ///
284        /// ```console
285        /// error: top-level or-patterns are not allowed in function parameters
286        ///  --> src/main.rs:1:6
287        ///   |
288        /// 1 | fn f(Some(_) | None: Option<T>) {
289        ///   |      ^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(Some(_) | None)`
290        /// ```
291        pub fn parse_single(input: ParseStream) -> Result<Self> {
292            let begin = input.fork();
293            let lookahead = input.lookahead1();
294            if lookahead.peek(Ident)
295                && (input.peek2(crate::token::PathSepToken![::])
296                    || input.peek2(crate::token::NotToken![!])
297                    || input.peek2(token::Brace)
298                    || input.peek2(token::Paren)
299                    || input.peek2(crate::token::DotDotToken![..]))
300                || input.peek(crate::token::SelfValueToken![self]) && input.peek2(crate::token::PathSepToken![::])
301                || lookahead.peek(crate::token::PathSepToken![::])
302                || lookahead.peek(crate::token::LtToken![<])
303                || input.peek(crate::token::SelfTypeToken![Self])
304                || input.peek(crate::token::SuperToken![super])
305                || input.peek(crate::token::CrateToken![crate])
306            {
307                pat_path_or_macro_or_struct_or_range(input)
308            } else if lookahead.peek(crate::token::UnderscoreToken![_]) {
309                input.call(pat_wild).map(Pat::Wild)
310            } else if input.peek(crate::token::BoxToken![box]) {
311                pat_box(begin, input)
312            } else if input.peek(crate::token::MinusToken![-]) || lookahead.peek(Lit) || lookahead.peek(crate::token::ConstToken![const])
313            {
314                pat_lit_or_range(input)
315            } else if lookahead.peek(crate::token::RefToken![ref])
316                || lookahead.peek(crate::token::MutToken![mut])
317                || input.peek(crate::token::SelfValueToken![self])
318                || input.peek(Ident)
319            {
320                input.call(pat_ident).map(Pat::Ident)
321            } else if lookahead.peek(crate::token::AndToken![&]) {
322                input.call(pat_reference).map(Pat::Reference)
323            } else if lookahead.peek(token::Paren) {
324                input.call(pat_paren_or_tuple)
325            } else if lookahead.peek(token::Bracket) {
326                input.call(pat_slice).map(Pat::Slice)
327            } else if lookahead.peek(crate::token::DotDotToken![..]) && !input.peek(crate::token::DotDotDotToken![...]) {
328                pat_range_half_open(input)
329            } else if lookahead.peek(crate::token::ConstToken![const]) {
330                input.call(pat_const).map(Pat::Verbatim)
331            } else {
332                Err(lookahead.error())
333            }
334        }
335
336        /// Parse a pattern, possibly involving `|`, but not a leading `|`.
337        pub fn parse_multi(input: ParseStream) -> Result<Self> {
338            multi_pat_impl(input, None)
339        }
340
341        /// Parse a pattern, possibly involving `|`, possibly including a
342        /// leading `|`.
343        ///
344        /// This parser matches the behavior of the Rust 2021 edition's `$:pat`
345        /// macro_rules matcher.
346        ///
347        /// In Rust syntax, an example of where this syntax would occur is in
348        /// the pattern of a `match` arm, where the language permits an optional
349        /// leading `|`, although it is not idiomatic to write one there in
350        /// handwritten code.
351        ///
352        /// ```
353        /// # let wat = None;
354        /// match wat {
355        ///     | None | Some(false) => {}
356        ///     | Some(true) => {}
357        /// }
358        /// ```
359        ///
360        /// The compiler accepts it only to facilitate some situations in
361        /// macro-generated code where a macro author might need to write:
362        ///
363        /// ```
364        /// # macro_rules! doc {
365        /// #     ($value:expr, ($($conditions1:pat),*), ($($conditions2:pat),*), $then:expr) => {
366        /// match $value {
367        ///     $(| $conditions1)* $(| $conditions2)* => $then
368        /// }
369        /// #     };
370        /// # }
371        /// #
372        /// # doc!(true, (true), (false), {});
373        /// # doc!(true, (), (true, false), {});
374        /// # doc!(true, (true, false), (), {});
375        /// ```
376        ///
377        /// Expressing the same thing correctly in the case that either one (but
378        /// not both) of `$conditions1` and `$conditions2` might be empty,
379        /// without leading `|`, is complex.
380        ///
381        /// Use [`Pat::parse_multi`] instead if you are not intending to support
382        /// macro-generated macro input.
383        pub fn parse_multi_with_leading_vert(input: ParseStream) -> Result<Self> {
384            let leading_vert: Option<crate::token::OrToken![|]> = input.parse()?;
385            multi_pat_impl(input, leading_vert)
386        }
387    }
388
389    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
390    impl Parse for PatType {
391        fn parse(input: ParseStream) -> Result<Self> {
392            Ok(PatType {
393                attrs: Vec::new(),
394                pat: Box::new(Pat::parse_single(input)?),
395                colon_token: input.parse()?,
396                ty: input.parse()?,
397            })
398        }
399    }
400
401    fn multi_pat_impl(input: ParseStream, leading_vert: Option<crate::token::OrToken![|]>) -> Result<Pat> {
402        let mut pat = Pat::parse_single(input)?;
403        if leading_vert.is_some()
404            || input.peek(crate::token::OrToken![|]) && !input.peek(crate::token::OrOrToken![||]) && !input.peek(crate::token::OrEqToken![|=])
405        {
406            let mut cases = Punctuated::new();
407            cases.push_value(pat);
408            while input.peek(crate::token::OrToken![|]) && !input.peek(crate::token::OrOrToken![||]) && !input.peek(crate::token::OrEqToken![|=]) {
409                let punct = input.parse()?;
410                cases.push_punct(punct);
411                let pat = Pat::parse_single(input)?;
412                cases.push_value(pat);
413            }
414            pat = Pat::Or(PatOr {
415                attrs: Vec::new(),
416                leading_vert,
417                cases,
418            });
419        }
420        Ok(pat)
421    }
422
423    fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> {
424        let expr_style = true;
425        let (qself, path) = path::parsing::qpath(input, expr_style)?;
426
427        if qself.is_none()
428            && input.peek(crate::token::NotToken![!])
429            && !input.peek(crate::token::NeToken![!=])
430            && path.is_mod_style()
431        {
432            let bang_token: crate::token::NotToken![!] = input.parse()?;
433            let (delimiter, tokens) = mac::parse_delimiter(input)?;
434            return Ok(Pat::Macro(ExprMacro {
435                attrs: Vec::new(),
436                mac: Macro {
437                    path,
438                    bang_token,
439                    delimiter,
440                    tokens,
441                },
442            }));
443        }
444
445        if input.peek(token::Brace) {
446            pat_struct(input, qself, path).map(Pat::Struct)
447        } else if input.peek(token::Paren) {
448            pat_tuple_struct(input, qself, path).map(Pat::TupleStruct)
449        } else if input.peek(crate::token::DotDotToken![..]) {
450            pat_range(input, qself, path)
451        } else {
452            Ok(Pat::Path(ExprPath {
453                attrs: Vec::new(),
454                qself,
455                path,
456            }))
457        }
458    }
459
460    fn pat_wild(input: ParseStream) -> Result<PatWild> {
461        Ok(PatWild {
462            attrs: Vec::new(),
463            underscore_token: input.parse()?,
464        })
465    }
466
467    fn pat_box(begin: ParseBuffer, input: ParseStream) -> Result<Pat> {
468        input.parse::<crate::token::BoxToken![box]>()?;
469        Pat::parse_single(input)?;
470        Ok(Pat::Verbatim(verbatim::between(&begin, input)))
471    }
472
473    fn pat_ident(input: ParseStream) -> Result<PatIdent> {
474        Ok(PatIdent {
475            attrs: Vec::new(),
476            by_ref: input.parse()?,
477            mutability: input.parse()?,
478            ident: {
479                if input.peek(crate::token::SelfValueToken![self]) {
480                    input.call(Ident::parse_any)?
481                } else {
482                    input.parse()?
483                }
484            },
485            subpat: {
486                if input.peek(crate::token::AtToken![@]) {
487                    let at_token: crate::token::AtToken![@] = input.parse()?;
488                    let subpat = Pat::parse_single(input)?;
489                    Some((at_token, Box::new(subpat)))
490                } else {
491                    None
492                }
493            },
494        })
495    }
496
497    fn pat_tuple_struct(
498        input: ParseStream,
499        qself: Option<QSelf>,
500        path: Path,
501    ) -> Result<PatTupleStruct> {
502        let content;
503        let paren_token = match crate::__private::parse_parens(&input) {
    crate::__private::Ok(parens) => {
        content = parens.content;
        _ = content;
        parens.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
}parenthesized!(content in input);
504
505        let mut elems = Punctuated::new();
506        while !content.is_empty() {
507            let value = Pat::parse_multi_with_leading_vert(&content)?;
508            elems.push_value(value);
509            if content.is_empty() {
510                break;
511            }
512            let punct = content.parse()?;
513            elems.push_punct(punct);
514        }
515
516        Ok(PatTupleStruct {
517            attrs: Vec::new(),
518            qself,
519            path,
520            paren_token,
521            elems,
522        })
523    }
524
525    fn pat_struct(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<PatStruct> {
526        let content;
527        let brace_token = match crate::__private::parse_braces(&input) {
    crate::__private::Ok(braces) => {
        content = braces.content;
        _ = content;
        braces.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
}braced!(content in input);
528
529        let mut fields = Punctuated::new();
530        let mut rest = None;
531        while !content.is_empty() {
532            let attrs = content.call(Attribute::parse_outer)?;
533            if content.peek(crate::token::DotDotToken![..]) {
534                rest = Some(PatRest {
535                    attrs,
536                    dot2_token: content.parse()?,
537                });
538                break;
539            }
540            let mut value = content.call(field_pat)?;
541            value.attrs = attrs;
542            fields.push_value(value);
543            if content.is_empty() {
544                break;
545            }
546            let punct: crate::token::CommaToken![,] = content.parse()?;
547            fields.push_punct(punct);
548        }
549
550        Ok(PatStruct {
551            attrs: Vec::new(),
552            qself,
553            path,
554            brace_token,
555            fields,
556            rest,
557        })
558    }
559
560    fn field_pat(input: ParseStream) -> Result<FieldPat> {
561        let begin = input.fork();
562        let boxed: Option<crate::token::BoxToken![box]> = input.parse()?;
563        let by_ref: Option<crate::token::RefToken![ref]> = input.parse()?;
564        let mutability: Option<crate::token::MutToken![mut]> = input.parse()?;
565
566        let member = if boxed.is_some() || by_ref.is_some() || mutability.is_some() {
567            input.parse().map(Member::Named)
568        } else {
569            input.parse()
570        }?;
571
572        if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(crate::token::ColonToken![:])
573            || !member.is_named()
574        {
575            return Ok(FieldPat {
576                attrs: Vec::new(),
577                member,
578                colon_token: Some(input.parse()?),
579                pat: Box::new(Pat::parse_multi_with_leading_vert(input)?),
580            });
581        }
582
583        let ident = match member {
584            Member::Named(ident) => ident,
585            Member::Unnamed(_) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
586        };
587
588        let pat = if boxed.is_some() {
589            Pat::Verbatim(verbatim::between(&begin, input))
590        } else {
591            Pat::Ident(PatIdent {
592                attrs: Vec::new(),
593                by_ref,
594                mutability,
595                ident: ident.clone(),
596                subpat: None,
597            })
598        };
599
600        Ok(FieldPat {
601            attrs: Vec::new(),
602            member: Member::Named(ident),
603            colon_token: None,
604            pat: Box::new(pat),
605        })
606    }
607
608    fn pat_range(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<Pat> {
609        let limits = RangeLimits::parse_obsolete(input)?;
610        let end = input.call(pat_range_bound)?;
611        if let (RangeLimits::Closed(_), None) = (&limits, &end) {
612            return Err(input.error("expected range upper bound"));
613        }
614        Ok(Pat::Range(ExprRange {
615            attrs: Vec::new(),
616            start: Some(Box::new(Expr::Path(ExprPath {
617                attrs: Vec::new(),
618                qself,
619                path,
620            }))),
621            limits,
622            end: end.map(PatRangeBound::into_expr),
623        }))
624    }
625
626    fn pat_range_half_open(input: ParseStream) -> Result<Pat> {
627        let limits: RangeLimits = input.parse()?;
628        let end = input.call(pat_range_bound)?;
629        if end.is_some() {
630            Ok(Pat::Range(ExprRange {
631                attrs: Vec::new(),
632                start: None,
633                limits,
634                end: end.map(PatRangeBound::into_expr),
635            }))
636        } else {
637            match limits {
638                RangeLimits::HalfOpen(dot2_token) => Ok(Pat::Rest(PatRest {
639                    attrs: Vec::new(),
640                    dot2_token,
641                })),
642                RangeLimits::Closed(_) => Err(input.error("expected range upper bound")),
643            }
644        }
645    }
646
647    fn pat_paren_or_tuple(input: ParseStream) -> Result<Pat> {
648        let content;
649        let paren_token = match crate::__private::parse_parens(&input) {
    crate::__private::Ok(parens) => {
        content = parens.content;
        _ = content;
        parens.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
}parenthesized!(content in input);
650
651        let mut elems = Punctuated::new();
652        while !content.is_empty() {
653            let value = Pat::parse_multi_with_leading_vert(&content)?;
654            if content.is_empty() {
655                if elems.is_empty() && !#[allow(non_exhaustive_omitted_patterns)] match value {
    Pat::Rest(_) => true,
    _ => false,
}matches!(value, Pat::Rest(_)) {
656                    return Ok(Pat::Paren(PatParen {
657                        attrs: Vec::new(),
658                        paren_token,
659                        pat: Box::new(value),
660                    }));
661                }
662                elems.push_value(value);
663                break;
664            }
665            elems.push_value(value);
666            let punct = content.parse()?;
667            elems.push_punct(punct);
668        }
669
670        Ok(Pat::Tuple(PatTuple {
671            attrs: Vec::new(),
672            paren_token,
673            elems,
674        }))
675    }
676
677    fn pat_reference(input: ParseStream) -> Result<PatReference> {
678        Ok(PatReference {
679            attrs: Vec::new(),
680            and_token: input.parse()?,
681            mutability: input.parse()?,
682            pat: Box::new(Pat::parse_single(input)?),
683        })
684    }
685
686    fn pat_lit_or_range(input: ParseStream) -> Result<Pat> {
687        let start = input.call(pat_range_bound)?.unwrap();
688        if input.peek(crate::token::DotDotToken![..]) {
689            let limits = RangeLimits::parse_obsolete(input)?;
690            let end = input.call(pat_range_bound)?;
691            if let (RangeLimits::Closed(_), None) = (&limits, &end) {
692                return Err(input.error("expected range upper bound"));
693            }
694            Ok(Pat::Range(ExprRange {
695                attrs: Vec::new(),
696                start: Some(start.into_expr()),
697                limits,
698                end: end.map(PatRangeBound::into_expr),
699            }))
700        } else {
701            Ok(start.into_pat())
702        }
703    }
704
705    // Patterns that can appear on either side of a range pattern.
706    enum PatRangeBound {
707        Const(ExprConst),
708        Lit(ExprLit),
709        Path(ExprPath),
710    }
711
712    impl PatRangeBound {
713        fn into_expr(self) -> Box<Expr> {
714            Box::new(match self {
715                PatRangeBound::Const(pat) => Expr::Const(pat),
716                PatRangeBound::Lit(pat) => Expr::Lit(pat),
717                PatRangeBound::Path(pat) => Expr::Path(pat),
718            })
719        }
720
721        fn into_pat(self) -> Pat {
722            match self {
723                PatRangeBound::Const(pat) => Pat::Const(pat),
724                PatRangeBound::Lit(pat) => Pat::Lit(pat),
725                PatRangeBound::Path(pat) => Pat::Path(pat),
726            }
727        }
728    }
729
730    fn pat_range_bound(input: ParseStream) -> Result<Option<PatRangeBound>> {
731        if input.is_empty()
732            || input.peek(crate::token::OrToken![|])
733            || input.peek(crate::token::EqToken![=])
734            || input.peek(crate::token::ColonToken![:]) && !input.peek(crate::token::PathSepToken![::])
735            || input.peek(crate::token::CommaToken![,])
736            || input.peek(crate::token::SemiToken![;])
737            || input.peek(crate::token::IfToken![if])
738        {
739            return Ok(None);
740        }
741
742        let lookahead = input.lookahead1();
743        let expr = if lookahead.peek(Lit) {
744            PatRangeBound::Lit(input.parse()?)
745        } else if lookahead.peek(Ident)
746            || lookahead.peek(crate::token::PathSepToken![::])
747            || lookahead.peek(crate::token::LtToken![<])
748            || lookahead.peek(crate::token::SelfValueToken![self])
749            || lookahead.peek(crate::token::SelfTypeToken![Self])
750            || lookahead.peek(crate::token::SuperToken![super])
751            || lookahead.peek(crate::token::CrateToken![crate])
752        {
753            PatRangeBound::Path(input.parse()?)
754        } else if lookahead.peek(crate::token::ConstToken![const]) {
755            PatRangeBound::Const(input.parse()?)
756        } else {
757            return Err(lookahead.error());
758        };
759
760        Ok(Some(expr))
761    }
762
763    fn pat_slice(input: ParseStream) -> Result<PatSlice> {
764        let content;
765        let bracket_token = match crate::__private::parse_brackets(&input) {
    crate::__private::Ok(brackets) => {
        content = brackets.content;
        _ = content;
        brackets.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
}bracketed!(content in input);
766
767        let mut elems = Punctuated::new();
768        while !content.is_empty() {
769            let value = Pat::parse_multi_with_leading_vert(&content)?;
770            match value {
771                Pat::Range(pat) if pat.start.is_none() || pat.end.is_none() => {
772                    let (start, end) = match pat.limits {
773                        RangeLimits::HalfOpen(dot_dot) => (dot_dot.spans[0], dot_dot.spans[1]),
774                        RangeLimits::Closed(dot_dot_eq) => {
775                            (dot_dot_eq.spans[0], dot_dot_eq.spans[2])
776                        }
777                    };
778                    let msg = "range pattern is not allowed unparenthesized inside slice pattern";
779                    return Err(error::new2(start, end, msg));
780                }
781                _ => {}
782            }
783            elems.push_value(value);
784            if content.is_empty() {
785                break;
786            }
787            let punct = content.parse()?;
788            elems.push_punct(punct);
789        }
790
791        Ok(PatSlice {
792            attrs: Vec::new(),
793            bracket_token,
794            elems,
795        })
796    }
797
798    fn pat_const(input: ParseStream) -> Result<TokenStream> {
799        let begin = input.fork();
800        input.parse::<crate::token::ConstToken![const]>()?;
801
802        let content;
803        match crate::__private::parse_braces(&input) {
    crate::__private::Ok(braces) => {
        content = braces.content;
        _ = content;
        braces.token
    }
    crate::__private::Err(error) => { return crate::__private::Err(error); }
};braced!(content in input);
804        content.call(Attribute::parse_inner)?;
805        content.call(Block::parse_within)?;
806
807        Ok(verbatim::between(&begin, input))
808    }
809}
810
811#[cfg(feature = "printing")]
812mod printing {
813    use crate::attr::FilterAttrs;
814    use crate::pat::{
815        FieldPat, Pat, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice, PatStruct,
816        PatTuple, PatTupleStruct, PatType, PatWild,
817    };
818    use crate::path;
819    use crate::path::printing::PathStyle;
820    use proc_macro2::TokenStream;
821    use quote::{ToTokens, TokenStreamExt as _};
822
823    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
824    impl ToTokens for PatIdent {
825        fn to_tokens(&self, tokens: &mut TokenStream) {
826            tokens.append_all(self.attrs.outer());
827            self.by_ref.to_tokens(tokens);
828            self.mutability.to_tokens(tokens);
829            self.ident.to_tokens(tokens);
830            if let Some((at_token, subpat)) = &self.subpat {
831                at_token.to_tokens(tokens);
832                subpat.to_tokens(tokens);
833            }
834        }
835    }
836
837    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
838    impl ToTokens for PatOr {
839        fn to_tokens(&self, tokens: &mut TokenStream) {
840            tokens.append_all(self.attrs.outer());
841            self.leading_vert.to_tokens(tokens);
842            self.cases.to_tokens(tokens);
843        }
844    }
845
846    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
847    impl ToTokens for PatParen {
848        fn to_tokens(&self, tokens: &mut TokenStream) {
849            tokens.append_all(self.attrs.outer());
850            self.paren_token.surround(tokens, |tokens| {
851                self.pat.to_tokens(tokens);
852            });
853        }
854    }
855
856    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
857    impl ToTokens for PatReference {
858        fn to_tokens(&self, tokens: &mut TokenStream) {
859            tokens.append_all(self.attrs.outer());
860            self.and_token.to_tokens(tokens);
861            self.mutability.to_tokens(tokens);
862            self.pat.to_tokens(tokens);
863        }
864    }
865
866    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
867    impl ToTokens for PatRest {
868        fn to_tokens(&self, tokens: &mut TokenStream) {
869            tokens.append_all(self.attrs.outer());
870            self.dot2_token.to_tokens(tokens);
871        }
872    }
873
874    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
875    impl ToTokens for PatSlice {
876        fn to_tokens(&self, tokens: &mut TokenStream) {
877            tokens.append_all(self.attrs.outer());
878            self.bracket_token.surround(tokens, |tokens| {
879                self.elems.to_tokens(tokens);
880            });
881        }
882    }
883
884    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
885    impl ToTokens for PatStruct {
886        fn to_tokens(&self, tokens: &mut TokenStream) {
887            tokens.append_all(self.attrs.outer());
888            path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
889            self.brace_token.surround(tokens, |tokens| {
890                self.fields.to_tokens(tokens);
891                // NOTE: We need a comma before the dot2 token if it is present.
892                if !self.fields.empty_or_trailing() && self.rest.is_some() {
893                    <crate::token::CommaToken![,]>::default().to_tokens(tokens);
894                }
895                self.rest.to_tokens(tokens);
896            });
897        }
898    }
899
900    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
901    impl ToTokens for PatTuple {
902        fn to_tokens(&self, tokens: &mut TokenStream) {
903            tokens.append_all(self.attrs.outer());
904            self.paren_token.surround(tokens, |tokens| {
905                self.elems.to_tokens(tokens);
906                // If there is only one element, a trailing comma is needed to
907                // distinguish PatTuple from PatParen, unless this is `(..)`
908                // which is a tuple pattern even without comma.
909                if self.elems.len() == 1
910                    && !self.elems.trailing_punct()
911                    && !#[allow(non_exhaustive_omitted_patterns)] match self.elems[0] {
    Pat::Rest { .. } => true,
    _ => false,
}matches!(self.elems[0], Pat::Rest { .. })
912                {
913                    <crate::token::CommaToken![,]>::default().to_tokens(tokens);
914                }
915            });
916        }
917    }
918
919    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
920    impl ToTokens for PatTupleStruct {
921        fn to_tokens(&self, tokens: &mut TokenStream) {
922            tokens.append_all(self.attrs.outer());
923            path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
924            self.paren_token.surround(tokens, |tokens| {
925                self.elems.to_tokens(tokens);
926            });
927        }
928    }
929
930    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
931    impl ToTokens for PatType {
932        fn to_tokens(&self, tokens: &mut TokenStream) {
933            tokens.append_all(self.attrs.outer());
934            self.pat.to_tokens(tokens);
935            self.colon_token.to_tokens(tokens);
936            self.ty.to_tokens(tokens);
937        }
938    }
939
940    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
941    impl ToTokens for PatWild {
942        fn to_tokens(&self, tokens: &mut TokenStream) {
943            tokens.append_all(self.attrs.outer());
944            self.underscore_token.to_tokens(tokens);
945        }
946    }
947
948    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
949    impl ToTokens for FieldPat {
950        fn to_tokens(&self, tokens: &mut TokenStream) {
951            tokens.append_all(self.attrs.outer());
952            if let Some(colon_token) = &self.colon_token {
953                self.member.to_tokens(tokens);
954                colon_token.to_tokens(tokens);
955            }
956            self.pat.to_tokens(tokens);
957        }
958    }
959}