Skip to main content

syn_impersonated/
pat.rs

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