1 use super::*;
2 use crate::punctuated::Punctuated;
3 use proc_macro2::TokenStream;
4 
5 ast_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     pub enum Pat {
18         /// A box pattern: `box v`.
19         Box(PatBox),
20 
21         /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
22         Ident(PatIdent),
23 
24         /// A literal pattern: `0`.
25         ///
26         /// This holds an `Expr` rather than a `Lit` because negative numbers
27         /// are represented as an `Expr::Unary`.
28         Lit(PatLit),
29 
30         /// A macro in pattern position.
31         Macro(PatMacro),
32 
33         /// A pattern that matches any one of a set of cases.
34         Or(PatOr),
35 
36         /// A path pattern like `Color::Red`, optionally qualified with a
37         /// self-type.
38         ///
39         /// Unqualified path patterns can legally refer to variants, structs,
40         /// constants or associated constants. Qualified path patterns like
41         /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
42         /// associated constants.
43         Path(PatPath),
44 
45         /// A range pattern: `1..=2`.
46         Range(PatRange),
47 
48         /// A reference pattern: `&mut var`.
49         Reference(PatReference),
50 
51         /// The dots in a tuple or slice pattern: `[0, 1, ..]`
52         Rest(PatRest),
53 
54         /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`.
55         Slice(PatSlice),
56 
57         /// A struct or struct variant pattern: `Variant { x, y, .. }`.
58         Struct(PatStruct),
59 
60         /// A tuple pattern: `(a, b)`.
61         Tuple(PatTuple),
62 
63         /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
64         TupleStruct(PatTupleStruct),
65 
66         /// A type ascription pattern: `foo: f64`.
67         Type(PatType),
68 
69         /// Tokens in pattern position not interpreted by Syn.
70         Verbatim(TokenStream),
71 
72         /// A pattern that matches any value: `_`.
73         Wild(PatWild),
74 
75         // The following is the only supported idiom for exhaustive matching of
76         // this enum.
77         //
78         //     match expr {
79         //         Pat::Box(e) => {...}
80         //         Pat::Ident(e) => {...}
81         //         ...
82         //         Pat::Wild(e) => {...}
83         //
84         //         #[cfg(test)]
85         //         Pat::__TestExhaustive(_) => unimplemented!(),
86         //         #[cfg(not(test))]
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         //
95         // Once `deny(reachable)` is available in rustc, Pat will be
96         // reimplemented as a non_exhaustive enum.
97         // https://github.com/rust-lang/rust/issues/44109#issuecomment-521781237
98         #[doc(hidden)]
99         __TestExhaustive(crate::private),
100     }
101 }
102 
103 ast_struct! {
104     /// A box pattern: `box v`.
105     ///
106     /// *This type is available only if Syn is built with the `"full"` feature.*
107     #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
108     pub struct PatBox {
109         pub attrs: Vec<Attribute>,
110         pub box_token: Token![box],
111         pub pat: Box<Pat>,
112     }
113 }
114 
115 ast_struct! {
116     /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
117     ///
118     /// It may also be a unit struct or struct variant (e.g. `None`), or a
119     /// constant; these cannot be distinguished syntactically.
120     ///
121     /// *This type is available only if Syn is built with the `"full"` feature.*
122     #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
123     pub struct PatIdent {
124         pub attrs: Vec<Attribute>,
125         pub by_ref: Option<Token![ref]>,
126         pub mutability: Option<Token![mut]>,
127         pub ident: Ident,
128         pub subpat: Option<(Token![@], Box<Pat>)>,
129     }
130 }
131 
132 ast_struct! {
133     /// A literal pattern: `0`.
134     ///
135     /// This holds an `Expr` rather than a `Lit` because negative numbers
136     /// are represented as an `Expr::Unary`.
137     ///
138     /// *This type is available only if Syn is built with the `"full"` feature.*
139     #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
140     pub struct PatLit {
141         pub attrs: Vec<Attribute>,
142         pub expr: Box<Expr>,
143     }
144 }
145 
146 ast_struct! {
147     /// A macro in pattern position.
148     ///
149     /// *This type is available only if Syn is built with the `"full"` feature.*
150     #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
151     pub struct PatMacro {
152         pub attrs: Vec<Attribute>,
153         pub mac: Macro,
154     }
155 }
156 
157 ast_struct! {
158     /// A pattern that matches any one of a set of cases.
159     ///
160     /// *This type is available only if Syn is built with the `"full"` feature.*
161     #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
162     pub struct PatOr {
163         pub attrs: Vec<Attribute>,
164         pub leading_vert: Option<Token![|]>,
165         pub cases: Punctuated<Pat, Token![|]>,
166     }
167 }
168 
169 ast_struct! {
170     /// A path pattern like `Color::Red`, optionally qualified with a
171     /// self-type.
172     ///
173     /// Unqualified path patterns can legally refer to variants, structs,
174     /// constants or associated constants. Qualified path patterns like
175     /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
176     /// associated constants.
177     ///
178     /// *This type is available only if Syn is built with the `"full"` feature.*
179     #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
180     pub struct PatPath {
181         pub attrs: Vec<Attribute>,
182         pub qself: Option<QSelf>,
183         pub path: Path,
184     }
185 }
186 
187 ast_struct! {
188     /// A range pattern: `1..=2`.
189     ///
190     /// *This type is available only if Syn is built with the `"full"` feature.*
191     #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
192     pub struct PatRange {
193         pub attrs: Vec<Attribute>,
194         pub lo: Box<Expr>,
195         pub limits: RangeLimits,
196         pub hi: Box<Expr>,
197     }
198 }
199 
200 ast_struct! {
201     /// A reference pattern: `&mut var`.
202     ///
203     /// *This type is available only if Syn is built with the `"full"` feature.*
204     #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
205     pub struct PatReference {
206         pub attrs: Vec<Attribute>,
207         pub and_token: Token![&],
208         pub mutability: Option<Token![mut]>,
209         pub pat: Box<Pat>,
210     }
211 }
212 
213 ast_struct! {
214     /// The dots in a tuple or slice pattern: `[0, 1, ..]`
215     ///
216     /// *This type is available only if Syn is built with the `"full"` feature.*
217     #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
218     pub struct PatRest {
219         pub attrs: Vec<Attribute>,
220         pub dot2_token: Token![..],
221     }
222 }
223 
224 ast_struct! {
225     /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`.
226     ///
227     /// *This type is available only if Syn is built with the `"full"` feature.*
228     #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
229     pub struct PatSlice {
230         pub attrs: Vec<Attribute>,
231         pub bracket_token: token::Bracket,
232         pub elems: Punctuated<Pat, Token![,]>,
233     }
234 }
235 
236 ast_struct! {
237     /// A struct or struct variant pattern: `Variant { x, y, .. }`.
238     ///
239     /// *This type is available only if Syn is built with the `"full"` feature.*
240     #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
241     pub struct PatStruct {
242         pub attrs: Vec<Attribute>,
243         pub path: Path,
244         pub brace_token: token::Brace,
245         pub fields: Punctuated<FieldPat, Token![,]>,
246         pub dot2_token: Option<Token![..]>,
247     }
248 }
249 
250 ast_struct! {
251     /// A tuple pattern: `(a, b)`.
252     ///
253     /// *This type is available only if Syn is built with the `"full"` feature.*
254     #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
255     pub struct PatTuple {
256         pub attrs: Vec<Attribute>,
257         pub paren_token: token::Paren,
258         pub elems: Punctuated<Pat, Token![,]>,
259     }
260 }
261 
262 ast_struct! {
263     /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
264     ///
265     /// *This type is available only if Syn is built with the `"full"` feature.*
266     #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
267     pub struct PatTupleStruct {
268         pub attrs: Vec<Attribute>,
269         pub path: Path,
270         pub pat: PatTuple,
271     }
272 }
273 
274 ast_struct! {
275     /// A type ascription pattern: `foo: f64`.
276     ///
277     /// *This type is available only if Syn is built with the `"full"` feature.*
278     #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
279     pub struct PatType {
280         pub attrs: Vec<Attribute>,
281         pub pat: Box<Pat>,
282         pub colon_token: Token![:],
283         pub ty: Box<Type>,
284     }
285 }
286 
287 ast_struct! {
288     /// A pattern that matches any value: `_`.
289     ///
290     /// *This type is available only if Syn is built with the `"full"` feature.*
291     #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
292     pub struct PatWild {
293         pub attrs: Vec<Attribute>,
294         pub underscore_token: Token![_],
295     }
296 }
297 
298 ast_struct! {
299     /// A single field in a struct pattern.
300     ///
301     /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
302     /// the same as `x: x, y: ref y, z: ref mut z` but there is no colon token.
303     ///
304     /// *This type is available only if Syn is built with the `"full"` feature.*
305     #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
306     pub struct FieldPat {
307         pub attrs: Vec<Attribute>,
308         pub member: Member,
309         pub colon_token: Option<Token![:]>,
310         pub pat: Box<Pat>,
311     }
312 }
313 
314 #[cfg(feature = "parsing")]
315 pub mod parsing {
316     use super::*;
317     use crate::ext::IdentExt;
318     use crate::parse::{Parse, ParseBuffer, ParseStream, Result};
319     use crate::path;
320 
321     #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
322     impl Parse for Pat {
parse(input: ParseStream) -> Result<Self>323         fn parse(input: ParseStream) -> Result<Self> {
324             let begin = input.fork();
325             let lookahead = input.lookahead1();
326             if {
327                 let ahead = input.fork();
328                 ahead.parse::<Option<Ident>>()?.is_some()
329                     && (ahead.peek(Token![::])
330                         || ahead.peek(Token![!])
331                         || ahead.peek(token::Brace)
332                         || ahead.peek(token::Paren)
333                         || ahead.peek(Token![..])
334                             && ahead.parse::<RangeLimits>().is_ok()
335                             && !(ahead.is_empty() || ahead.peek(Token![,])))
336             } || {
337                 let ahead = input.fork();
338                 ahead.parse::<Option<Token![self]>>()?.is_some() && ahead.peek(Token![::])
339             } || lookahead.peek(Token![::])
340                 || lookahead.peek(Token![<])
341                 || input.peek(Token![Self])
342                 || input.peek(Token![super])
343                 || input.peek(Token![crate])
344             {
345                 pat_path_or_macro_or_struct_or_range(input)
346             } else if lookahead.peek(Token![_]) {
347                 input.call(pat_wild).map(Pat::Wild)
348             } else if input.peek(Token![box]) {
349                 input.call(pat_box).map(Pat::Box)
350             } else if input.peek(Token![-]) || lookahead.peek(Lit) || lookahead.peek(Token![const])
351             {
352                 pat_lit_or_range(input)
353             } else if lookahead.peek(Token![ref])
354                 || lookahead.peek(Token![mut])
355                 || input.peek(Token![self])
356                 || input.peek(Ident)
357             {
358                 input.call(pat_ident).map(Pat::Ident)
359             } else if lookahead.peek(Token![&]) {
360                 input.call(pat_reference).map(Pat::Reference)
361             } else if lookahead.peek(token::Paren) {
362                 input.call(pat_tuple).map(Pat::Tuple)
363             } else if lookahead.peek(token::Bracket) {
364                 input.call(pat_slice).map(Pat::Slice)
365             } else if lookahead.peek(Token![..]) && !input.peek(Token![...]) {
366                 pat_range_half_open(input, begin)
367             } else if lookahead.peek(Token![const]) {
368                 input.call(pat_const).map(Pat::Verbatim)
369             } else {
370                 Err(lookahead.error())
371             }
372         }
373     }
374 
pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat>375     fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> {
376         let begin = input.fork();
377         let (qself, path) = path::parsing::qpath(input, true)?;
378 
379         if qself.is_none() && input.peek(Token![!]) && !input.peek(Token![!=]) {
380             let mut contains_arguments = false;
381             for segment in &path.segments {
382                 match segment.arguments {
383                     PathArguments::None => {}
384                     PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
385                         contains_arguments = true;
386                     }
387                 }
388             }
389 
390             if !contains_arguments {
391                 let bang_token: Token![!] = input.parse()?;
392                 let (delimiter, tokens) = mac::parse_delimiter(input)?;
393                 return Ok(Pat::Macro(PatMacro {
394                     attrs: Vec::new(),
395                     mac: Macro {
396                         path,
397                         bang_token,
398                         delimiter,
399                         tokens,
400                     },
401                 }));
402             }
403         }
404 
405         if input.peek(token::Brace) {
406             let pat = pat_struct(input, path)?;
407             if qself.is_some() {
408                 Ok(Pat::Verbatim(verbatim::between(begin, input)))
409             } else {
410                 Ok(Pat::Struct(pat))
411             }
412         } else if input.peek(token::Paren) {
413             let pat = pat_tuple_struct(input, path)?;
414             if qself.is_some() {
415                 Ok(Pat::Verbatim(verbatim::between(begin, input)))
416             } else {
417                 Ok(Pat::TupleStruct(pat))
418             }
419         } else if input.peek(Token![..]) {
420             pat_range(input, begin, qself, path)
421         } else {
422             Ok(Pat::Path(PatPath {
423                 attrs: Vec::new(),
424                 qself,
425                 path,
426             }))
427         }
428     }
429 
pat_wild(input: ParseStream) -> Result<PatWild>430     fn pat_wild(input: ParseStream) -> Result<PatWild> {
431         Ok(PatWild {
432             attrs: Vec::new(),
433             underscore_token: input.parse()?,
434         })
435     }
436 
pat_box(input: ParseStream) -> Result<PatBox>437     fn pat_box(input: ParseStream) -> Result<PatBox> {
438         Ok(PatBox {
439             attrs: Vec::new(),
440             box_token: input.parse()?,
441             pat: input.parse()?,
442         })
443     }
444 
pat_ident(input: ParseStream) -> Result<PatIdent>445     fn pat_ident(input: ParseStream) -> Result<PatIdent> {
446         Ok(PatIdent {
447             attrs: Vec::new(),
448             by_ref: input.parse()?,
449             mutability: input.parse()?,
450             ident: input.call(Ident::parse_any)?,
451             subpat: {
452                 if input.peek(Token![@]) {
453                     let at_token: Token![@] = input.parse()?;
454                     let subpat: Pat = input.parse()?;
455                     Some((at_token, Box::new(subpat)))
456                 } else {
457                     None
458                 }
459             },
460         })
461     }
462 
pat_tuple_struct(input: ParseStream, path: Path) -> Result<PatTupleStruct>463     fn pat_tuple_struct(input: ParseStream, path: Path) -> Result<PatTupleStruct> {
464         Ok(PatTupleStruct {
465             attrs: Vec::new(),
466             path,
467             pat: input.call(pat_tuple)?,
468         })
469     }
470 
pat_struct(input: ParseStream, path: Path) -> Result<PatStruct>471     fn pat_struct(input: ParseStream, path: Path) -> Result<PatStruct> {
472         let content;
473         let brace_token = braced!(content in input);
474 
475         let mut fields = Punctuated::new();
476         while !content.is_empty() && !content.peek(Token![..]) {
477             let value = content.call(field_pat)?;
478             fields.push_value(value);
479             if content.is_empty() {
480                 break;
481             }
482             let punct: Token![,] = content.parse()?;
483             fields.push_punct(punct);
484         }
485 
486         let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) {
487             Some(content.parse()?)
488         } else {
489             None
490         };
491 
492         Ok(PatStruct {
493             attrs: Vec::new(),
494             path,
495             brace_token,
496             fields,
497             dot2_token,
498         })
499     }
500 
501     impl Member {
is_unnamed(&self) -> bool502         fn is_unnamed(&self) -> bool {
503             match *self {
504                 Member::Named(_) => false,
505                 Member::Unnamed(_) => true,
506             }
507         }
508     }
509 
field_pat(input: ParseStream) -> Result<FieldPat>510     fn field_pat(input: ParseStream) -> Result<FieldPat> {
511         let attrs = input.call(Attribute::parse_outer)?;
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,
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,
551             member: Member::Named(ident),
552             colon_token: None,
553             pat: Box::new(pat),
554         })
555     }
556 
pat_range( input: ParseStream, begin: ParseBuffer, qself: Option<QSelf>, path: Path, ) -> Result<Pat>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 
pat_range_half_open(input: ParseStream, begin: ParseBuffer) -> Result<Pat>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 
pat_tuple(input: ParseStream) -> Result<PatTuple>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 
pat_reference(input: ParseStream) -> Result<PatReference>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 
pat_lit_or_range(input: ParseStream) -> Result<Pat>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 
pat_lit_expr(input: ParseStream) -> Result<Option<Box<Expr>>>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 
pat_slice(input: ParseStream) -> Result<PatSlice>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 
pat_const(input: ParseStream) -> Result<TokenStream>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 
multi_pat(input: ParseStream) -> Result<Pat>730     pub fn multi_pat(input: ParseStream) -> Result<Pat> {
731         multi_pat_impl(input, None)
732     }
733 
multi_pat_with_leading_vert(input: ParseStream) -> Result<Pat>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 
multi_pat_impl(input: ParseStream, leading_vert: Option<Token![|]>) -> Result<Pat>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")]
763 mod 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 {
to_tokens(&self, tokens: &mut TokenStream)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 {
to_tokens(&self, tokens: &mut TokenStream)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 {
to_tokens(&self, tokens: &mut TokenStream)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 {
to_tokens(&self, tokens: &mut TokenStream)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 {
to_tokens(&self, tokens: &mut TokenStream)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 {
to_tokens(&self, tokens: &mut TokenStream)828         fn to_tokens(&self, tokens: &mut TokenStream) {
829             tokens.append_all(self.attrs.outer());
830             private::print_path(tokens, &self.qself, &self.path);
831         }
832     }
833 
834     #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
835     impl ToTokens for PatTuple {
to_tokens(&self, tokens: &mut TokenStream)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 {
to_tokens(&self, tokens: &mut TokenStream)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 {
to_tokens(&self, tokens: &mut TokenStream)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 {
to_tokens(&self, tokens: &mut TokenStream)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 {
to_tokens(&self, tokens: &mut TokenStream)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 {
to_tokens(&self, tokens: &mut TokenStream)881         fn to_tokens(&self, tokens: &mut TokenStream) {
882             tokens.append_all(self.attrs.outer());
883             self.lo.to_tokens(tokens);
884             match &self.limits {
885                 RangeLimits::HalfOpen(t) => t.to_tokens(tokens),
886                 RangeLimits::Closed(t) => t.to_tokens(tokens),
887             }
888             self.hi.to_tokens(tokens);
889         }
890     }
891 
892     #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
893     impl ToTokens for PatSlice {
to_tokens(&self, tokens: &mut TokenStream)894         fn to_tokens(&self, tokens: &mut TokenStream) {
895             tokens.append_all(self.attrs.outer());
896             self.bracket_token.surround(tokens, |tokens| {
897                 self.elems.to_tokens(tokens);
898             });
899         }
900     }
901 
902     #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
903     impl ToTokens for PatMacro {
to_tokens(&self, tokens: &mut TokenStream)904         fn to_tokens(&self, tokens: &mut TokenStream) {
905             tokens.append_all(self.attrs.outer());
906             self.mac.to_tokens(tokens);
907         }
908     }
909 
910     #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
911     impl ToTokens for PatOr {
to_tokens(&self, tokens: &mut TokenStream)912         fn to_tokens(&self, tokens: &mut TokenStream) {
913             tokens.append_all(self.attrs.outer());
914             self.leading_vert.to_tokens(tokens);
915             self.cases.to_tokens(tokens);
916         }
917     }
918 
919     #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
920     impl ToTokens for FieldPat {
to_tokens(&self, tokens: &mut TokenStream)921         fn to_tokens(&self, tokens: &mut TokenStream) {
922             tokens.append_all(self.attrs.outer());
923             if let Some(colon_token) = &self.colon_token {
924                 self.member.to_tokens(tokens);
925                 colon_token.to_tokens(tokens);
926             }
927             self.pat.to_tokens(tokens);
928         }
929     }
930 }
931