syn/
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, ParseStream, Result};
390    use crate::path;
391
392    impl Parse for Pat {
393        fn parse(input: ParseStream) -> Result<Self> {
394            let lookahead = input.lookahead1();
395            if lookahead.peek(Ident)
396                && ({
397                    input.peek2(Token![::])
398                        || input.peek2(Token![!])
399                        || input.peek2(token::Brace)
400                        || input.peek2(token::Paren)
401                        || input.peek2(Token![..])
402                            && !{
403                                let ahead = input.fork();
404                                ahead.parse::<Ident>()?;
405                                ahead.parse::<RangeLimits>()?;
406                                ahead.is_empty() || ahead.peek(Token![,])
407                            }
408                })
409                || input.peek(Token![self]) && input.peek2(Token![::])
410                || lookahead.peek(Token![::])
411                || lookahead.peek(Token![<])
412                || input.peek(Token![Self])
413                || input.peek(Token![super])
414                || input.peek(Token![extern])
415                || input.peek(Token![crate])
416            {
417                pat_path_or_macro_or_struct_or_range(input)
418            } else if lookahead.peek(Token![_]) {
419                input.call(pat_wild).map(Pat::Wild)
420            } else if input.peek(Token![box]) {
421                input.call(pat_box).map(Pat::Box)
422            } else if input.peek(Token![-]) || lookahead.peek(Lit) {
423                pat_lit_or_range(input)
424            } else if lookahead.peek(Token![ref])
425                || lookahead.peek(Token![mut])
426                || input.peek(Token![self])
427                || input.peek(Ident)
428            {
429                input.call(pat_ident).map(Pat::Ident)
430            } else if lookahead.peek(Token![&]) {
431                input.call(pat_reference).map(Pat::Reference)
432            } else if lookahead.peek(token::Paren) {
433                input.call(pat_tuple).map(Pat::Tuple)
434            } else if lookahead.peek(token::Bracket) {
435                input.call(pat_slice).map(Pat::Slice)
436            } else if lookahead.peek(Token![..]) && !input.peek(Token![...]) {
437                input.call(pat_rest).map(Pat::Rest)
438            } else {
439                Err(lookahead.error())
440            }
441        }
442    }
443
444    fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> {
445        let (qself, path) = path::parsing::qpath(input, true)?;
446
447        if input.peek(Token![..]) {
448            return pat_range(input, qself, path).map(Pat::Range);
449        }
450
451        if qself.is_some() {
452            return Ok(Pat::Path(PatPath {
453                attrs: Vec::new(),
454                qself,
455                path,
456            }));
457        }
458
459        if input.peek(Token![!]) && !input.peek(Token![!=]) {
460            let mut contains_arguments = false;
461            for segment in &path.segments {
462                match segment.arguments {
463                    PathArguments::None => {}
464                    PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
465                        contains_arguments = true;
466                    }
467                }
468            }
469
470            if !contains_arguments {
471                let bang_token: Token![!] = input.parse()?;
472                let (delimiter, tokens) = mac::parse_delimiter(input)?;
473                return Ok(Pat::Macro(PatMacro {
474                    attrs: Vec::new(),
475                    mac: Macro {
476                        path,
477                        bang_token,
478                        delimiter,
479                        tokens,
480                    },
481                }));
482            }
483        }
484
485        if input.peek(token::Brace) {
486            pat_struct(input, path).map(Pat::Struct)
487        } else if input.peek(token::Paren) {
488            pat_tuple_struct(input, path).map(Pat::TupleStruct)
489        } else if input.peek(Token![..]) {
490            pat_range(input, qself, path).map(Pat::Range)
491        } else {
492            Ok(Pat::Path(PatPath {
493                attrs: Vec::new(),
494                qself,
495                path,
496            }))
497        }
498    }
499
500    fn pat_wild(input: ParseStream) -> Result<PatWild> {
501        Ok(PatWild {
502            attrs: Vec::new(),
503            underscore_token: input.parse()?,
504        })
505    }
506
507    fn pat_box(input: ParseStream) -> Result<PatBox> {
508        Ok(PatBox {
509            attrs: Vec::new(),
510            box_token: input.parse()?,
511            pat: input.parse()?,
512        })
513    }
514
515    fn pat_ident(input: ParseStream) -> Result<PatIdent> {
516        Ok(PatIdent {
517            attrs: Vec::new(),
518            by_ref: input.parse()?,
519            mutability: input.parse()?,
520            ident: input.call(Ident::parse_any)?,
521            subpat: {
522                if input.peek(Token![@]) {
523                    let at_token: Token![@] = input.parse()?;
524                    let subpat: Pat = input.parse()?;
525                    Some((at_token, Box::new(subpat)))
526                } else {
527                    None
528                }
529            },
530        })
531    }
532
533    fn pat_tuple_struct(input: ParseStream, path: Path) -> Result<PatTupleStruct> {
534        Ok(PatTupleStruct {
535            attrs: Vec::new(),
536            path,
537            pat: input.call(pat_tuple)?,
538        })
539    }
540
541    fn pat_struct(input: ParseStream, path: Path) -> Result<PatStruct> {
542        let content;
543        let brace_token = braced!(content in input);
544
545        let mut fields = Punctuated::new();
546        while !content.is_empty() && !content.peek(Token![..]) {
547            let value = content.call(field_pat)?;
548            fields.push_value(value);
549            if !content.peek(Token![,]) {
550                break;
551            }
552            let punct: Token![,] = content.parse()?;
553            fields.push_punct(punct);
554        }
555
556        let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) {
557            Some(content.parse()?)
558        } else {
559            None
560        };
561
562        Ok(PatStruct {
563            attrs: Vec::new(),
564            path,
565            brace_token,
566            fields,
567            dot2_token,
568        })
569    }
570
571    impl Member {
572        fn is_unnamed(&self) -> bool {
573            match *self {
574                Member::Named(_) => false,
575                Member::Unnamed(_) => true,
576            }
577        }
578    }
579
580    fn field_pat(input: ParseStream) -> Result<FieldPat> {
581        let attrs = input.call(Attribute::parse_outer)?;
582        let boxed: Option<Token![box]> = input.parse()?;
583        let by_ref: Option<Token![ref]> = input.parse()?;
584        let mutability: Option<Token![mut]> = input.parse()?;
585        let member: Member = input.parse()?;
586
587        if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
588            || member.is_unnamed()
589        {
590            return Ok(FieldPat {
591                attrs,
592                member,
593                colon_token: input.parse()?,
594                pat: input.parse()?,
595            });
596        }
597
598        let ident = match member {
599            Member::Named(ident) => ident,
600            Member::Unnamed(_) => unreachable!(),
601        };
602
603        let mut pat = Pat::Ident(PatIdent {
604            attrs: Vec::new(),
605            by_ref,
606            mutability,
607            ident: ident.clone(),
608            subpat: None,
609        });
610
611        if let Some(boxed) = boxed {
612            pat = Pat::Box(PatBox {
613                attrs: Vec::new(),
614                box_token: boxed,
615                pat: Box::new(pat),
616            });
617        }
618
619        Ok(FieldPat {
620            attrs,
621            member: Member::Named(ident),
622            colon_token: None,
623            pat: Box::new(pat),
624        })
625    }
626
627    fn pat_range(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<PatRange> {
628        Ok(PatRange {
629            attrs: Vec::new(),
630            lo: Box::new(Expr::Path(ExprPath {
631                attrs: Vec::new(),
632                qself,
633                path,
634            })),
635            limits: input.parse()?,
636            hi: input.call(pat_lit_expr)?,
637        })
638    }
639
640    fn pat_tuple(input: ParseStream) -> Result<PatTuple> {
641        let content;
642        let paren_token = parenthesized!(content in input);
643
644        let mut elems = Punctuated::new();
645        while !content.is_empty() {
646            let value: Pat = content.parse()?;
647            elems.push_value(value);
648            if content.is_empty() {
649                break;
650            }
651            let punct = content.parse()?;
652            elems.push_punct(punct);
653        }
654
655        Ok(PatTuple {
656            attrs: Vec::new(),
657            paren_token,
658            elems,
659        })
660    }
661
662    fn pat_reference(input: ParseStream) -> Result<PatReference> {
663        Ok(PatReference {
664            attrs: Vec::new(),
665            and_token: input.parse()?,
666            mutability: input.parse()?,
667            pat: input.parse()?,
668        })
669    }
670
671    fn pat_lit_or_range(input: ParseStream) -> Result<Pat> {
672        let lo = input.call(pat_lit_expr)?;
673        if input.peek(Token![..]) {
674            Ok(Pat::Range(PatRange {
675                attrs: Vec::new(),
676                lo,
677                limits: input.parse()?,
678                hi: input.call(pat_lit_expr)?,
679            }))
680        } else {
681            Ok(Pat::Lit(PatLit {
682                attrs: Vec::new(),
683                expr: lo,
684            }))
685        }
686    }
687
688    fn pat_lit_expr(input: ParseStream) -> Result<Box<Expr>> {
689        let neg: Option<Token![-]> = input.parse()?;
690
691        let lookahead = input.lookahead1();
692        let expr = if lookahead.peek(Lit) {
693            Expr::Lit(input.parse()?)
694        } else if lookahead.peek(Ident)
695            || lookahead.peek(Token![::])
696            || lookahead.peek(Token![<])
697            || lookahead.peek(Token![self])
698            || lookahead.peek(Token![Self])
699            || lookahead.peek(Token![super])
700            || lookahead.peek(Token![extern])
701            || lookahead.peek(Token![crate])
702        {
703            Expr::Path(input.parse()?)
704        } else {
705            return Err(lookahead.error());
706        };
707
708        Ok(Box::new(if let Some(neg) = neg {
709            Expr::Unary(ExprUnary {
710                attrs: Vec::new(),
711                op: UnOp::Neg(neg),
712                expr: Box::new(expr),
713            })
714        } else {
715            expr
716        }))
717    }
718
719    fn pat_slice(input: ParseStream) -> Result<PatSlice> {
720        let content;
721        let bracket_token = bracketed!(content in input);
722
723        let mut elems = Punctuated::new();
724        while !content.is_empty() {
725            let value: Pat = content.parse()?;
726            elems.push_value(value);
727            if content.is_empty() {
728                break;
729            }
730            let punct = content.parse()?;
731            elems.push_punct(punct);
732        }
733
734        Ok(PatSlice {
735            attrs: Vec::new(),
736            bracket_token,
737            elems,
738        })
739    }
740
741    fn pat_rest(input: ParseStream) -> Result<PatRest> {
742        Ok(PatRest {
743            attrs: Vec::new(),
744            dot2_token: input.parse()?,
745        })
746    }
747}
748
749#[cfg(feature = "printing")]
750mod printing {
751    use super::*;
752
753    use proc_macro2::TokenStream;
754    use quote::{ToTokens, TokenStreamExt};
755
756    use crate::attr::FilterAttrs;
757
758    impl ToTokens for PatWild {
759        fn to_tokens(&self, tokens: &mut TokenStream) {
760            tokens.append_all(self.attrs.outer());
761            self.underscore_token.to_tokens(tokens);
762        }
763    }
764
765    impl ToTokens for PatIdent {
766        fn to_tokens(&self, tokens: &mut TokenStream) {
767            tokens.append_all(self.attrs.outer());
768            self.by_ref.to_tokens(tokens);
769            self.mutability.to_tokens(tokens);
770            self.ident.to_tokens(tokens);
771            if let Some((at_token, subpat)) = &self.subpat {
772                at_token.to_tokens(tokens);
773                subpat.to_tokens(tokens);
774            }
775        }
776    }
777
778    impl ToTokens for PatStruct {
779        fn to_tokens(&self, tokens: &mut TokenStream) {
780            tokens.append_all(self.attrs.outer());
781            self.path.to_tokens(tokens);
782            self.brace_token.surround(tokens, |tokens| {
783                self.fields.to_tokens(tokens);
784                // NOTE: We need a comma before the dot2 token if it is present.
785                if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
786                    <Token![,]>::default().to_tokens(tokens);
787                }
788                self.dot2_token.to_tokens(tokens);
789            });
790        }
791    }
792
793    impl ToTokens for PatTupleStruct {
794        fn to_tokens(&self, tokens: &mut TokenStream) {
795            tokens.append_all(self.attrs.outer());
796            self.path.to_tokens(tokens);
797            self.pat.to_tokens(tokens);
798        }
799    }
800
801    impl ToTokens for PatType {
802        fn to_tokens(&self, tokens: &mut TokenStream) {
803            tokens.append_all(self.attrs.outer());
804            self.pat.to_tokens(tokens);
805            self.colon_token.to_tokens(tokens);
806            self.ty.to_tokens(tokens);
807        }
808    }
809
810    impl ToTokens for PatPath {
811        fn to_tokens(&self, tokens: &mut TokenStream) {
812            tokens.append_all(self.attrs.outer());
813            private::print_path(tokens, &self.qself, &self.path);
814        }
815    }
816
817    impl ToTokens for PatTuple {
818        fn to_tokens(&self, tokens: &mut TokenStream) {
819            tokens.append_all(self.attrs.outer());
820            self.paren_token.surround(tokens, |tokens| {
821                self.elems.to_tokens(tokens);
822            });
823        }
824    }
825
826    impl ToTokens for PatBox {
827        fn to_tokens(&self, tokens: &mut TokenStream) {
828            tokens.append_all(self.attrs.outer());
829            self.box_token.to_tokens(tokens);
830            self.pat.to_tokens(tokens);
831        }
832    }
833
834    impl ToTokens for PatReference {
835        fn to_tokens(&self, tokens: &mut TokenStream) {
836            tokens.append_all(self.attrs.outer());
837            self.and_token.to_tokens(tokens);
838            self.mutability.to_tokens(tokens);
839            self.pat.to_tokens(tokens);
840        }
841    }
842
843    impl ToTokens for PatRest {
844        fn to_tokens(&self, tokens: &mut TokenStream) {
845            tokens.append_all(self.attrs.outer());
846            self.dot2_token.to_tokens(tokens);
847        }
848    }
849
850    impl ToTokens for PatLit {
851        fn to_tokens(&self, tokens: &mut TokenStream) {
852            tokens.append_all(self.attrs.outer());
853            self.expr.to_tokens(tokens);
854        }
855    }
856
857    impl ToTokens for PatRange {
858        fn to_tokens(&self, tokens: &mut TokenStream) {
859            tokens.append_all(self.attrs.outer());
860            self.lo.to_tokens(tokens);
861            match &self.limits {
862                RangeLimits::HalfOpen(t) => t.to_tokens(tokens),
863                RangeLimits::Closed(t) => t.to_tokens(tokens),
864            }
865            self.hi.to_tokens(tokens);
866        }
867    }
868
869    impl ToTokens for PatSlice {
870        fn to_tokens(&self, tokens: &mut TokenStream) {
871            tokens.append_all(self.attrs.outer());
872            self.bracket_token.surround(tokens, |tokens| {
873                self.elems.to_tokens(tokens);
874            });
875        }
876    }
877
878    impl ToTokens for PatMacro {
879        fn to_tokens(&self, tokens: &mut TokenStream) {
880            tokens.append_all(self.attrs.outer());
881            self.mac.to_tokens(tokens);
882        }
883    }
884
885    impl ToTokens for PatOr {
886        fn to_tokens(&self, tokens: &mut TokenStream) {
887            tokens.append_all(self.attrs.outer());
888            self.leading_vert.to_tokens(tokens);
889            self.cases.to_tokens(tokens);
890        }
891    }
892
893    impl ToTokens for FieldPat {
894        fn to_tokens(&self, tokens: &mut TokenStream) {
895            tokens.append_all(self.attrs.outer());
896            if let Some(colon_token) = &self.colon_token {
897                self.member.to_tokens(tokens);
898                colon_token.to_tokens(tokens);
899            }
900            self.pat.to_tokens(tokens);
901        }
902    }
903}