Skip to main content

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::buffer::Cursor;
244    use crate::error::{self, Result};
245    use crate::expr::{
246        Expr, ExprConst, ExprLit, ExprMacro, ExprPath, ExprRange, Member, RangeLimits,
247    };
248    use crate::ext::IdentExt as _;
249    use crate::ident::Ident;
250    use crate::lit::Lit;
251    use crate::mac::{self, Macro};
252    use crate::parse::{Parse, ParseStream};
253    use crate::pat::{
254        FieldPat, Pat, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice, PatStruct,
255        PatTuple, PatTupleStruct, PatType, PatWild,
256    };
257    use crate::path::{self, Path, QSelf};
258    use crate::punctuated::Punctuated;
259    use crate::stmt::Block;
260    use crate::token;
261    use crate::verbatim;
262    use alloc::boxed::Box;
263    use alloc::vec::Vec;
264    use proc_macro2::TokenStream;
265
266    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
267    impl Pat {
268        /// Parse a pattern that does _not_ involve `|` at the top level.
269        ///
270        /// This parser matches the behavior of the `$:pat_param` macro_rules
271        /// matcher, and on editions prior to Rust 2021, the behavior of
272        /// `$:pat`.
273        ///
274        /// In Rust syntax, some examples of where this syntax would occur are
275        /// in the argument pattern of functions and closures. Patterns using
276        /// `|` are not allowed to occur in these positions.
277        ///
278        /// ```compile_fail
279        /// fn f(Some(_) | None: Option<T>) {
280        ///     let _ = |Some(_) | None: Option<T>| {};
281        ///     //       ^^^^^^^^^^^^^^^^^^^^^^^^^??? :(
282        /// }
283        /// ```
284        ///
285        /// ```console
286        /// error: top-level or-patterns are not allowed in function parameters
287        ///  --> src/main.rs:1:6
288        ///   |
289        /// 1 | fn f(Some(_) | None: Option<T>) {
290        ///   |      ^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(Some(_) | None)`
291        /// ```
292        pub fn parse_single(input: ParseStream) -> Result<Self> {
293            let begin = input.cursor();
294            let lookahead = input.lookahead1();
295            if lookahead.peek(Ident)
296                && (input.peek2(crate::token::PathSepToken![::])
297                    || input.peek2(crate::token::NotToken![!])
298                    || input.peek2(token::Brace)
299                    || input.peek2(token::Paren)
300                    || input.peek2(crate::token::DotDotToken![..]))
301                || input.peek(crate::token::SelfValueToken![self]) && input.peek2(crate::token::PathSepToken![::])
302                || lookahead.peek(crate::token::PathSepToken![::])
303                || lookahead.peek(crate::token::LtToken![<])
304                || input.peek(crate::token::SelfTypeToken![Self])
305                || input.peek(crate::token::SuperToken![super])
306                || input.peek(crate::token::CrateToken![crate])
307            {
308                pat_path_or_macro_or_struct_or_range(input)
309            } else if lookahead.peek(crate::token::UnderscoreToken![_]) {
310                input.call(pat_wild).map(Pat::Wild)
311            } else if input.peek(crate::token::BoxToken![box]) {
312                pat_box(begin, input)
313            } else if input.peek(crate::token::MinusToken![-]) || lookahead.peek(Lit) || lookahead.peek(crate::token::ConstToken![const])
314            {
315                pat_lit_or_range(input)
316            } else if lookahead.peek(crate::token::RefToken![ref])
317                || lookahead.peek(crate::token::MutToken![mut])
318                || input.peek(crate::token::SelfValueToken![self])
319                || input.peek(Ident)
320            {
321                input.call(pat_ident).map(Pat::Ident)
322            } else if lookahead.peek(crate::token::AndToken![&]) {
323                input.call(pat_reference).map(Pat::Reference)
324            } else if lookahead.peek(token::Paren) {
325                input.call(pat_paren_or_tuple)
326            } else if lookahead.peek(token::Bracket) {
327                input.call(pat_slice).map(Pat::Slice)
328            } else if lookahead.peek(crate::token::DotDotToken![..]) && !input.peek(crate::token::DotDotDotToken![...]) {
329                pat_range_half_open(input)
330            } else if lookahead.peek(crate::token::ConstToken![const]) {
331                input.call(pat_const).map(Pat::Verbatim)
332            } else {
333                Err(lookahead.error())
334            }
335        }
336
337        /// Parse a pattern, possibly involving `|`, but not a leading `|`.
338        pub fn parse_multi(input: ParseStream) -> Result<Self> {
339            multi_pat_impl(input, None)
340        }
341
342        /// Parse a pattern, possibly involving `|`, possibly including a
343        /// leading `|`.
344        ///
345        /// This parser matches the behavior of the Rust 2021 edition's `$:pat`
346        /// macro_rules matcher.
347        ///
348        /// In Rust syntax, an example of where this syntax would occur is in
349        /// the pattern of a `match` arm, where the language permits an optional
350        /// leading `|`, although it is not idiomatic to write one there in
351        /// handwritten code.
352        ///
353        /// ```
354        /// # let wat = None;
355        /// match wat {
356        ///     | None | Some(false) => {}
357        ///     | Some(true) => {}
358        /// }
359        /// ```
360        ///
361        /// The compiler accepts it only to facilitate some situations in
362        /// macro-generated code where a macro author might need to write:
363        ///
364        /// ```
365        /// # macro_rules! doc {
366        /// #     ($value:expr, ($($conditions1:pat),*), ($($conditions2:pat),*), $then:expr) => {
367        /// match $value {
368        ///     $(| $conditions1)* $(| $conditions2)* => $then
369        /// }
370        /// #     };
371        /// # }
372        /// #
373        /// # doc!(true, (true), (false), {});
374        /// # doc!(true, (), (true, false), {});
375        /// # doc!(true, (true, false), (), {});
376        /// ```
377        ///
378        /// Expressing the same thing correctly in the case that either one (but
379        /// not both) of `$conditions1` and `$conditions2` might be empty,
380        /// without leading `|`, is complex.
381        ///
382        /// Use [`Pat::parse_multi`] instead if you are not intending to support
383        /// macro-generated macro input.
384        pub fn parse_multi_with_leading_vert(input: ParseStream) -> Result<Self> {
385            let leading_vert: Option<crate::token::OrToken![|]> = input.parse()?;
386            multi_pat_impl(input, leading_vert)
387        }
388    }
389
390    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
391    impl Parse for PatType {
392        fn parse(input: ParseStream) -> Result<Self> {
393            Ok(PatType {
394                attrs: Vec::new(),
395                pat: Box::new(Pat::parse_single(input)?),
396                colon_token: input.parse()?,
397                ty: input.parse()?,
398            })
399        }
400    }
401
402    fn multi_pat_impl(input: ParseStream, leading_vert: Option<crate::token::OrToken![|]>) -> Result<Pat> {
403        let mut pat = Pat::parse_single(input)?;
404        if leading_vert.is_some()
405            || input.peek(crate::token::OrToken![|]) && !input.peek(crate::token::OrOrToken![||]) && !input.peek(crate::token::OrEqToken![|=])
406        {
407            let mut cases = Punctuated::new();
408            cases.push_value(pat);
409            while input.peek(crate::token::OrToken![|]) && !input.peek(crate::token::OrOrToken![||]) && !input.peek(crate::token::OrEqToken![|=]) {
410                let punct = input.parse()?;
411                cases.push_punct(punct);
412                let pat = Pat::parse_single(input)?;
413                cases.push_value(pat);
414            }
415            pat = Pat::Or(PatOr {
416                attrs: Vec::new(),
417                leading_vert,
418                cases,
419            });
420        }
421        Ok(pat)
422    }
423
424    fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> {
425        let expr_style = true;
426        let (qself, path) = path::parsing::qpath(input, expr_style)?;
427
428        if qself.is_none()
429            && input.peek(crate::token::NotToken![!])
430            && !input.peek(crate::token::NeToken![!=])
431            && path.is_mod_style()
432        {
433            let bang_token: crate::token::NotToken![!] = input.parse()?;
434            let (delimiter, tokens) = mac::parse_delimiter(input)?;
435            return Ok(Pat::Macro(ExprMacro {
436                attrs: Vec::new(),
437                mac: Macro {
438                    path,
439                    bang_token,
440                    delimiter,
441                    tokens,
442                },
443            }));
444        }
445
446        if input.peek(token::Brace) {
447            pat_struct(input, qself, path).map(Pat::Struct)
448        } else if input.peek(token::Paren) {
449            pat_tuple_struct(input, qself, path).map(Pat::TupleStruct)
450        } else if input.peek(crate::token::DotDotToken![..]) {
451            pat_range(input, qself, path)
452        } else {
453            Ok(Pat::Path(ExprPath {
454                attrs: Vec::new(),
455                qself,
456                path,
457            }))
458        }
459    }
460
461    fn pat_wild(input: ParseStream) -> Result<PatWild> {
462        Ok(PatWild {
463            attrs: Vec::new(),
464            underscore_token: input.parse()?,
465        })
466    }
467
468    fn pat_box(begin: Cursor, input: ParseStream) -> Result<Pat> {
469        input.parse::<crate::token::BoxToken![box]>()?;
470        Pat::parse_single(input)?;
471        Ok(Pat::Verbatim(verbatim::between(begin, input.cursor())))
472    }
473
474    fn pat_ident(input: ParseStream) -> Result<PatIdent> {
475        Ok(PatIdent {
476            attrs: Vec::new(),
477            by_ref: input.parse()?,
478            mutability: input.parse()?,
479            ident: {
480                if input.peek(crate::token::SelfValueToken![self]) {
481                    input.call(Ident::parse_any)?
482                } else {
483                    input.parse()?
484                }
485            },
486            subpat: {
487                if input.peek(crate::token::AtToken![@]) {
488                    let at_token: crate::token::AtToken![@] = input.parse()?;
489                    let subpat = Pat::parse_single(input)?;
490                    Some((at_token, Box::new(subpat)))
491                } else {
492                    None
493                }
494            },
495        })
496    }
497
498    fn pat_tuple_struct(
499        input: ParseStream,
500        qself: Option<QSelf>,
501        path: Path,
502    ) -> Result<PatTupleStruct> {
503        let content;
504        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);
505
506        let mut elems = Punctuated::new();
507        while !content.is_empty() {
508            let value = Pat::parse_multi_with_leading_vert(&content)?;
509            elems.push_value(value);
510            if content.is_empty() {
511                break;
512            }
513            let punct = content.parse()?;
514            elems.push_punct(punct);
515        }
516
517        Ok(PatTupleStruct {
518            attrs: Vec::new(),
519            qself,
520            path,
521            paren_token,
522            elems,
523        })
524    }
525
526    fn pat_struct(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<PatStruct> {
527        let content;
528        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);
529
530        let mut fields = Punctuated::new();
531        let mut rest = None;
532        while !content.is_empty() {
533            let attrs = content.call(Attribute::parse_outer)?;
534            if content.peek(crate::token::DotDotToken![..]) {
535                rest = Some(PatRest {
536                    attrs,
537                    dot2_token: content.parse()?,
538                });
539                break;
540            }
541            let mut value = content.call(field_pat)?;
542            value.attrs = attrs;
543            fields.push_value(value);
544            if content.is_empty() {
545                break;
546            }
547            let punct: crate::token::CommaToken![,] = content.parse()?;
548            fields.push_punct(punct);
549        }
550
551        Ok(PatStruct {
552            attrs: Vec::new(),
553            qself,
554            path,
555            brace_token,
556            fields,
557            rest,
558        })
559    }
560
561    fn field_pat(input: ParseStream) -> Result<FieldPat> {
562        let begin = input.cursor();
563        let boxed: Option<crate::token::BoxToken![box]> = input.parse()?;
564        let by_ref: Option<crate::token::RefToken![ref]> = input.parse()?;
565        let mutability: Option<crate::token::MutToken![mut]> = input.parse()?;
566
567        let member = if boxed.is_some() || by_ref.is_some() || mutability.is_some() {
568            input.parse().map(Member::Named)
569        } else {
570            input.parse()
571        }?;
572
573        if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(crate::token::ColonToken![:])
574            || !member.is_named()
575        {
576            return Ok(FieldPat {
577                attrs: Vec::new(),
578                member,
579                colon_token: Some(input.parse()?),
580                pat: Box::new(Pat::parse_multi_with_leading_vert(input)?),
581            });
582        }
583
584        let ident = match member {
585            Member::Named(ident) => ident,
586            Member::Unnamed(_) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
587        };
588
589        let pat = if boxed.is_some() {
590            Pat::Verbatim(verbatim::between(begin, input.cursor()))
591        } else {
592            Pat::Ident(PatIdent {
593                attrs: Vec::new(),
594                by_ref,
595                mutability,
596                ident: ident.clone(),
597                subpat: None,
598            })
599        };
600
601        Ok(FieldPat {
602            attrs: Vec::new(),
603            member: Member::Named(ident),
604            colon_token: None,
605            pat: Box::new(pat),
606        })
607    }
608
609    fn pat_range(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<Pat> {
610        let limits = RangeLimits::parse_obsolete(input)?;
611        let end = input.call(pat_range_bound)?;
612        if let (RangeLimits::Closed(_), None) = (&limits, &end) {
613            return Err(input.error("expected range upper bound"));
614        }
615        Ok(Pat::Range(ExprRange {
616            attrs: Vec::new(),
617            start: Some(Box::new(Expr::Path(ExprPath {
618                attrs: Vec::new(),
619                qself,
620                path,
621            }))),
622            limits,
623            end: end.map(PatRangeBound::into_expr),
624        }))
625    }
626
627    fn pat_range_half_open(input: ParseStream) -> Result<Pat> {
628        let limits: RangeLimits = input.parse()?;
629        let end = input.call(pat_range_bound)?;
630        if end.is_some() {
631            Ok(Pat::Range(ExprRange {
632                attrs: Vec::new(),
633                start: None,
634                limits,
635                end: end.map(PatRangeBound::into_expr),
636            }))
637        } else {
638            match limits {
639                RangeLimits::HalfOpen(dot2_token) => Ok(Pat::Rest(PatRest {
640                    attrs: Vec::new(),
641                    dot2_token,
642                })),
643                RangeLimits::Closed(_) => Err(input.error("expected range upper bound")),
644            }
645        }
646    }
647
648    fn pat_paren_or_tuple(input: ParseStream) -> Result<Pat> {
649        let content;
650        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);
651
652        let mut elems = Punctuated::new();
653        while !content.is_empty() {
654            let value = Pat::parse_multi_with_leading_vert(&content)?;
655            if content.is_empty() {
656                if elems.is_empty() && !#[allow(non_exhaustive_omitted_patterns)] match value {
    Pat::Rest(_) => true,
    _ => false,
}matches!(value, Pat::Rest(_)) {
657                    return Ok(Pat::Paren(PatParen {
658                        attrs: Vec::new(),
659                        paren_token,
660                        pat: Box::new(value),
661                    }));
662                }
663                elems.push_value(value);
664                break;
665            }
666            elems.push_value(value);
667            let punct = content.parse()?;
668            elems.push_punct(punct);
669        }
670
671        Ok(Pat::Tuple(PatTuple {
672            attrs: Vec::new(),
673            paren_token,
674            elems,
675        }))
676    }
677
678    fn pat_reference(input: ParseStream) -> Result<PatReference> {
679        Ok(PatReference {
680            attrs: Vec::new(),
681            and_token: input.parse()?,
682            mutability: input.parse()?,
683            pat: Box::new(Pat::parse_single(input)?),
684        })
685    }
686
687    fn pat_lit_or_range(input: ParseStream) -> Result<Pat> {
688        let start = input.call(pat_range_bound)?.unwrap();
689        if input.peek(crate::token::DotDotToken![..]) {
690            let limits = RangeLimits::parse_obsolete(input)?;
691            let end = input.call(pat_range_bound)?;
692            if let (RangeLimits::Closed(_), None) = (&limits, &end) {
693                return Err(input.error("expected range upper bound"));
694            }
695            Ok(Pat::Range(ExprRange {
696                attrs: Vec::new(),
697                start: Some(start.into_expr()),
698                limits,
699                end: end.map(PatRangeBound::into_expr),
700            }))
701        } else {
702            Ok(start.into_pat())
703        }
704    }
705
706    // Patterns that can appear on either side of a range pattern.
707    enum PatRangeBound {
708        Const(ExprConst),
709        Lit(ExprLit),
710        Path(ExprPath),
711    }
712
713    impl PatRangeBound {
714        fn into_expr(self) -> Box<Expr> {
715            Box::new(match self {
716                PatRangeBound::Const(pat) => Expr::Const(pat),
717                PatRangeBound::Lit(pat) => Expr::Lit(pat),
718                PatRangeBound::Path(pat) => Expr::Path(pat),
719            })
720        }
721
722        fn into_pat(self) -> Pat {
723            match self {
724                PatRangeBound::Const(pat) => Pat::Const(pat),
725                PatRangeBound::Lit(pat) => Pat::Lit(pat),
726                PatRangeBound::Path(pat) => Pat::Path(pat),
727            }
728        }
729    }
730
731    fn pat_range_bound(input: ParseStream) -> Result<Option<PatRangeBound>> {
732        if input.is_empty()
733            || input.peek(crate::token::OrToken![|])
734            || input.peek(crate::token::EqToken![=])
735            || input.peek(crate::token::ColonToken![:]) && !input.peek(crate::token::PathSepToken![::])
736            || input.peek(crate::token::CommaToken![,])
737            || input.peek(crate::token::SemiToken![;])
738            || input.peek(crate::token::IfToken![if])
739        {
740            return Ok(None);
741        }
742
743        let lookahead = input.lookahead1();
744        let expr = if lookahead.peek(Lit) {
745            PatRangeBound::Lit(input.parse()?)
746        } else if lookahead.peek(Ident)
747            || lookahead.peek(crate::token::PathSepToken![::])
748            || lookahead.peek(crate::token::LtToken![<])
749            || lookahead.peek(crate::token::SelfValueToken![self])
750            || lookahead.peek(crate::token::SelfTypeToken![Self])
751            || lookahead.peek(crate::token::SuperToken![super])
752            || lookahead.peek(crate::token::CrateToken![crate])
753        {
754            PatRangeBound::Path(input.parse()?)
755        } else if lookahead.peek(crate::token::ConstToken![const]) {
756            PatRangeBound::Const(input.parse()?)
757        } else {
758            return Err(lookahead.error());
759        };
760
761        Ok(Some(expr))
762    }
763
764    fn pat_slice(input: ParseStream) -> Result<PatSlice> {
765        let content;
766        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);
767
768        let mut elems = Punctuated::new();
769        while !content.is_empty() {
770            let value = Pat::parse_multi_with_leading_vert(&content)?;
771            match value {
772                Pat::Range(pat) if pat.start.is_none() || pat.end.is_none() => {
773                    let (start, end) = match pat.limits {
774                        RangeLimits::HalfOpen(dot_dot) => (dot_dot.spans[0], dot_dot.spans[1]),
775                        RangeLimits::Closed(dot_dot_eq) => {
776                            (dot_dot_eq.spans[0], dot_dot_eq.spans[2])
777                        }
778                    };
779                    let msg = "range pattern is not allowed unparenthesized inside slice pattern";
780                    return Err(error::new2(start, end, msg));
781                }
782                _ => {}
783            }
784            elems.push_value(value);
785            if content.is_empty() {
786                break;
787            }
788            let punct = content.parse()?;
789            elems.push_punct(punct);
790        }
791
792        Ok(PatSlice {
793            attrs: Vec::new(),
794            bracket_token,
795            elems,
796        })
797    }
798
799    fn pat_const(input: ParseStream) -> Result<TokenStream> {
800        let begin = input.cursor();
801        input.parse::<crate::token::ConstToken![const]>()?;
802
803        let content;
804        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);
805        content.call(Attribute::parse_inner)?;
806        content.call(Block::parse_within)?;
807
808        Ok(verbatim::between(begin, input.cursor()))
809    }
810}
811
812#[cfg(feature = "printing")]
813mod printing {
814    use crate::attr::FilterAttrs;
815    use crate::pat::{
816        FieldPat, Pat, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice, PatStruct,
817        PatTuple, PatTupleStruct, PatType, PatWild,
818    };
819    use crate::path;
820    use crate::path::printing::PathStyle;
821    use proc_macro2::TokenStream;
822    use quote::{ToTokens, TokenStreamExt as _};
823
824    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
825    impl ToTokens for PatIdent {
826        fn to_tokens(&self, tokens: &mut TokenStream) {
827            tokens.append_all(self.attrs.outer());
828            self.by_ref.to_tokens(tokens);
829            self.mutability.to_tokens(tokens);
830            self.ident.to_tokens(tokens);
831            if let Some((at_token, subpat)) = &self.subpat {
832                at_token.to_tokens(tokens);
833                subpat.to_tokens(tokens);
834            }
835        }
836    }
837
838    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
839    impl ToTokens for PatOr {
840        fn to_tokens(&self, tokens: &mut TokenStream) {
841            tokens.append_all(self.attrs.outer());
842            self.leading_vert.to_tokens(tokens);
843            self.cases.to_tokens(tokens);
844        }
845    }
846
847    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
848    impl ToTokens for PatParen {
849        fn to_tokens(&self, tokens: &mut TokenStream) {
850            tokens.append_all(self.attrs.outer());
851            self.paren_token.surround(tokens, |tokens| {
852                self.pat.to_tokens(tokens);
853            });
854        }
855    }
856
857    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
858    impl ToTokens for PatReference {
859        fn to_tokens(&self, tokens: &mut TokenStream) {
860            tokens.append_all(self.attrs.outer());
861            self.and_token.to_tokens(tokens);
862            self.mutability.to_tokens(tokens);
863            self.pat.to_tokens(tokens);
864        }
865    }
866
867    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
868    impl ToTokens for PatRest {
869        fn to_tokens(&self, tokens: &mut TokenStream) {
870            tokens.append_all(self.attrs.outer());
871            self.dot2_token.to_tokens(tokens);
872        }
873    }
874
875    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
876    impl ToTokens for PatSlice {
877        fn to_tokens(&self, tokens: &mut TokenStream) {
878            tokens.append_all(self.attrs.outer());
879            self.bracket_token.surround(tokens, |tokens| {
880                self.elems.to_tokens(tokens);
881            });
882        }
883    }
884
885    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
886    impl ToTokens for PatStruct {
887        fn to_tokens(&self, tokens: &mut TokenStream) {
888            tokens.append_all(self.attrs.outer());
889            path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
890            self.brace_token.surround(tokens, |tokens| {
891                self.fields.to_tokens(tokens);
892                // NOTE: We need a comma before the dot2 token if it is present.
893                if !self.fields.empty_or_trailing() && self.rest.is_some() {
894                    <crate::token::CommaToken![,]>::default().to_tokens(tokens);
895                }
896                self.rest.to_tokens(tokens);
897            });
898        }
899    }
900
901    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
902    impl ToTokens for PatTuple {
903        fn to_tokens(&self, tokens: &mut TokenStream) {
904            tokens.append_all(self.attrs.outer());
905            self.paren_token.surround(tokens, |tokens| {
906                self.elems.to_tokens(tokens);
907                // If there is only one element, a trailing comma is needed to
908                // distinguish PatTuple from PatParen, unless this is `(..)`
909                // which is a tuple pattern even without comma.
910                if self.elems.len() == 1
911                    && !self.elems.trailing_punct()
912                    && !#[allow(non_exhaustive_omitted_patterns)] match self.elems[0] {
    Pat::Rest { .. } => true,
    _ => false,
}matches!(self.elems[0], Pat::Rest { .. })
913                {
914                    <crate::token::CommaToken![,]>::default().to_tokens(tokens);
915                }
916            });
917        }
918    }
919
920    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
921    impl ToTokens for PatTupleStruct {
922        fn to_tokens(&self, tokens: &mut TokenStream) {
923            tokens.append_all(self.attrs.outer());
924            path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
925            self.paren_token.surround(tokens, |tokens| {
926                self.elems.to_tokens(tokens);
927            });
928        }
929    }
930
931    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
932    impl ToTokens for PatType {
933        fn to_tokens(&self, tokens: &mut TokenStream) {
934            tokens.append_all(self.attrs.outer());
935            self.pat.to_tokens(tokens);
936            self.colon_token.to_tokens(tokens);
937            self.ty.to_tokens(tokens);
938        }
939    }
940
941    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
942    impl ToTokens for PatWild {
943        fn to_tokens(&self, tokens: &mut TokenStream) {
944            tokens.append_all(self.attrs.outer());
945            self.underscore_token.to_tokens(tokens);
946        }
947    }
948
949    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
950    impl ToTokens for FieldPat {
951        fn to_tokens(&self, tokens: &mut TokenStream) {
952            tokens.append_all(self.attrs.outer());
953            if let Some(colon_token) = &self.colon_token {
954                self.member.to_tokens(tokens);
955                colon_token.to_tokens(tokens);
956            }
957            self.pat.to_tokens(tokens);
958        }
959    }
960}