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