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