syn/
pat.rs

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