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 pub enum Pat #manual_extra_traits {
24 Box(PatBox),
26
27 Ident(PatIdent),
29
30 Lit(PatLit),
35
36 Macro(PatMacro),
38
39 Or(PatOr),
41
42 Path(PatPath),
50
51 Range(PatRange),
53
54 Reference(PatReference),
56
57 Rest(PatRest),
59
60 Slice(PatSlice),
62
63 Struct(PatStruct),
65
66 Tuple(PatTuple),
68
69 TupleStruct(PatTupleStruct),
71
72 Type(PatType),
74
75 Verbatim(TokenStream),
77
78 Wild(PatWild),
80
81 #[doc(hidden)]
82 __Nonexhaustive,
83 }
84}
85
86ast_struct! {
87 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 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 pub struct PatLit {
118 pub attrs: Vec<Attribute>,
119 pub expr: Box<Expr>,
120 }
121}
122
123ast_struct! {
124 pub struct PatMacro {
128 pub attrs: Vec<Attribute>,
129 pub mac: Macro,
130 }
131}
132
133ast_struct! {
134 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 pub struct PatPath {
155 pub attrs: Vec<Attribute>,
156 pub qself: Option<QSelf>,
157 pub path: Path,
158 }
159}
160
161ast_struct! {
162 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 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 pub struct PatRest {
190 pub attrs: Vec<Attribute>,
191 pub dot2_token: Token![..],
192 }
193}
194
195ast_struct! {
196 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 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 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 pub struct PatTupleStruct {
235 pub attrs: Vec<Attribute>,
236 pub path: Path,
237 pub pat: PatTuple,
238 }
239}
240
241ast_struct! {
242 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 pub struct PatWild {
258 pub attrs: Vec<Attribute>,
259 pub underscore_token: Token![_],
260 }
261}
262
263ast_struct! {
264 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 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}