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