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 /// # Syntax tree enum
10 ///
11 /// This type is a [syntax tree enum].
12 ///
13 /// [syntax tree enum]: Expr#syntax-tree-enums
14 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
15 #[non_exhaustive]
16 pub enum Pat {
17 /// A const block: `const { ... }`.
18 Const(PatConst),
19
20 /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
21 Ident(PatIdent),
22
23 /// A literal pattern: `0`.
24 Lit(PatLit),
25
26 /// A macro in pattern position.
27 Macro(PatMacro),
28
29 /// A pattern that matches any one of a set of cases.
30 Or(PatOr),
31
32 /// A parenthesized pattern: `(A | B)`.
33 Paren(PatParen),
34
35 /// A path pattern like `Color::Red`, optionally qualified with a
36 /// self-type.
37 ///
38 /// Unqualified path patterns can legally refer to variants, structs,
39 /// constants or associated constants. Qualified path patterns like
40 /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
41 /// associated constants.
42 Path(PatPath),
43
44 /// A range pattern: `1..=2`.
45 Range(PatRange),
46
47 /// A reference pattern: `&mut var`.
48 Reference(PatReference),
49
50 /// The dots in a tuple or slice pattern: `[0, 1, ..]`.
51 Rest(PatRest),
52
53 /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`.
54 Slice(PatSlice),
55
56 /// A struct or struct variant pattern: `Variant { x, y, .. }`.
57 Struct(PatStruct),
58
59 /// A tuple pattern: `(a, b)`.
60 Tuple(PatTuple),
61
62 /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
63 TupleStruct(PatTupleStruct),
64
65 /// A type ascription pattern: `foo: f64`.
66 Type(PatType),
67
68 /// Tokens in pattern position not interpreted by Syn.
69 Verbatim(TokenStream),
70
71 /// A pattern that matches any value: `_`.
72 Wild(PatWild),
73
74 // For testing exhaustiveness in downstream code, use the following idiom:
75 //
76 // match pat {
77 // Pat::Box(pat) => {...}
78 // Pat::Ident(pat) => {...}
79 // ...
80 // Pat::Wild(pat) => {...}
81 //
82 // #[cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
83 // _ => { /* some sane fallback */ }
84 // }
85 //
86 // This way we fail your tests but don't break your library when adding
87 // a variant. You will be notified by a test failure when a variant is
88 // added, so that you can add code to handle it, but your library will
89 // continue to compile and work for downstream users in the interim.
90 }
91}
92
93ast_struct! {
94 /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
95 ///
96 /// It may also be a unit struct or struct variant (e.g. `None`), or a
97 /// constant; these cannot be distinguished syntactically.
98 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
99 pub struct PatIdent {
100 pub attrs: Vec<Attribute>,
101 pub by_ref: Option<Token![ref]>,
102 pub mutability: Option<Token![mut]>,
103 pub ident: Ident,
104 pub subpat: Option<(Token![@], Box<Pat>)>,
105 }
106}
107
108ast_struct! {
109 /// A pattern that matches any one of a set of cases.
110 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
111 pub struct PatOr {
112 pub attrs: Vec<Attribute>,
113 pub leading_vert: Option<Token![|]>,
114 pub cases: Punctuated<Pat, Token![|]>,
115 }
116}
117
118ast_struct! {
119 /// A parenthesized pattern: `(A | B)`.
120 pub struct PatParen {
121 pub attrs: Vec<Attribute>,
122 pub paren_token: token::Paren,
123 pub pat: Box<Pat>,
124 }
125}
126
127ast_struct! {
128 /// A reference pattern: `&mut var`.
129 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
130 pub struct PatReference {
131 pub attrs: Vec<Attribute>,
132 pub and_token: Token![&],
133 pub mutability: Option<Token![mut]>,
134 pub pat: Box<Pat>,
135 }
136}
137
138ast_struct! {
139 /// The dots in a tuple or slice pattern: `[0, 1, ..]`.
140 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
141 pub struct PatRest {
142 pub attrs: Vec<Attribute>,
143 pub dot2_token: Token![..],
144 }
145}
146
147ast_struct! {
148 /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`.
149 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
150 pub struct PatSlice {
151 pub attrs: Vec<Attribute>,
152 pub bracket_token: token::Bracket,
153 pub elems: Punctuated<Pat, Token![,]>,
154 }
155}
156
157ast_struct! {
158 /// A struct or struct variant pattern: `Variant { x, y, .. }`.
159 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
160 pub struct PatStruct {
161 pub attrs: Vec<Attribute>,
162 pub qself: Option<QSelf>,
163 pub path: Path,
164 pub brace_token: token::Brace,
165 pub fields: Punctuated<FieldPat, Token![,]>,
166 pub rest: Option<PatRest>,
167 }
168}
169
170ast_struct! {
171 /// A tuple pattern: `(a, b)`.
172 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
173 pub struct PatTuple {
174 pub attrs: Vec<Attribute>,
175 pub paren_token: token::Paren,
176 pub elems: Punctuated<Pat, Token![,]>,
177 }
178}
179
180ast_struct! {
181 /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
182 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
183 pub struct PatTupleStruct {
184 pub attrs: Vec<Attribute>,
185 pub qself: Option<QSelf>,
186 pub path: Path,
187 pub paren_token: token::Paren,
188 pub elems: Punctuated<Pat, Token![,]>,
189 }
190}
191
192ast_struct! {
193 /// A type ascription pattern: `foo: f64`.
194 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
195 pub struct PatType {
196 pub attrs: Vec<Attribute>,
197 pub pat: Box<Pat>,
198 pub colon_token: Token![:],
199 pub ty: Box<Type>,
200 }
201}
202
203ast_struct! {
204 /// A pattern that matches any value: `_`.
205 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
206 pub struct PatWild {
207 pub attrs: Vec<Attribute>,
208 pub underscore_token: Token![_],
209 }
210}
211
212ast_struct! {
213 /// A single field in a struct pattern.
214 ///
215 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
216 /// the same as `x: x, y: ref y, z: ref mut z` but there is no colon token.
217 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
218 pub struct FieldPat {
219 pub attrs: Vec<Attribute>,
220 pub member: Member,
221 pub colon_token: Option<Token![:]>,
222 pub pat: Box<Pat>,
223 }
224}
225
226#[cfg(feature = "parsing")]
227pub(crate) mod parsing {
228 use super::*;
229 use crate::ext::IdentExt;
230 use crate::parse::{ParseBuffer, ParseStream, Result};
231 use crate::path;
232
233 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
234 impl Pat {
235 /// Parse a pattern that does _not_ involve `|` at the top level.
236 ///
237 /// This parser matches the behavior of the `$:pat_param` macro_rules
238 /// matcher, and on editions prior to Rust 2021, the behavior of
239 /// `$:pat`.
240 ///
241 /// In Rust syntax, some examples of where this syntax would occur are
242 /// in the argument pattern of functions and closures. Patterns using
243 /// `|` are not allowed to occur in these positions.
244 ///
245 /// ```compile_fail
246 /// fn f(Some(_) | None: Option<T>) {
247 /// let _ = |Some(_) | None: Option<T>| {};
248 /// // ^^^^^^^^^^^^^^^^^^^^^^^^^??? :(
249 /// }
250 /// ```
251 ///
252 /// ```console
253 /// error: top-level or-patterns are not allowed in function parameters
254 /// --> src/main.rs:1:6
255 /// |
256 /// 1 | fn f(Some(_) | None: Option<T>) {
257 /// | ^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(Some(_) | None)`
258 /// ```
259 pub fn parse_single(input: ParseStream) -> Result<Self> {
260 let begin = input.fork();
261 let lookahead = input.lookahead1();
262 if lookahead.peek(Ident)
263 && (input.peek2(Token![::])
264 || input.peek2(Token![!])
265 || input.peek2(token::Brace)
266 || input.peek2(token::Paren)
267 || input.peek2(Token![..]))
268 || input.peek(Token![self]) && input.peek2(Token![::])
269 || lookahead.peek(Token![::])
270 || lookahead.peek(Token![<])
271 || input.peek(Token![Self])
272 || input.peek(Token![super])
273 || input.peek(Token![crate])
274 {
275 pat_path_or_macro_or_struct_or_range(input)
276 } else if lookahead.peek(Token![_]) {
277 input.call(pat_wild).map(Pat::Wild)
278 } else if input.peek(Token![box]) {
279 pat_box(begin, input)
280 } else if input.peek(Token![-]) || lookahead.peek(Lit) || lookahead.peek(Token![const])
281 {
282 pat_lit_or_range(input)
283 } else if lookahead.peek(Token![ref])
284 || lookahead.peek(Token![mut])
285 || input.peek(Token![self])
286 || input.peek(Ident)
287 {
288 input.call(pat_ident).map(Pat::Ident)
289 } else if lookahead.peek(Token![&]) {
290 input.call(pat_reference).map(Pat::Reference)
291 } else if lookahead.peek(token::Paren) {
292 input.call(pat_paren_or_tuple)
293 } else if lookahead.peek(token::Bracket) {
294 input.call(pat_slice).map(Pat::Slice)
295 } else if lookahead.peek(Token![..]) && !input.peek(Token![...]) {
296 pat_range_half_open(input)
297 } else if lookahead.peek(Token![const]) {
298 input.call(pat_const).map(Pat::Verbatim)
299 } else {
300 Err(lookahead.error())
301 }
302 }
303
304 /// Parse a pattern, possibly involving `|`, but not a leading `|`.
305 pub fn parse_multi(input: ParseStream) -> Result<Self> {
306 multi_pat_impl(input, None)
307 }
308
309 /// Parse a pattern, possibly involving `|`, possibly including a
310 /// leading `|`.
311 ///
312 /// This parser matches the behavior of the Rust 2021 edition's `$:pat`
313 /// macro_rules matcher.
314 ///
315 /// In Rust syntax, an example of where this syntax would occur is in
316 /// the pattern of a `match` arm, where the language permits an optional
317 /// leading `|`, although it is not idiomatic to write one there in
318 /// handwritten code.
319 ///
320 /// ```
321 /// # let wat = None;
322 /// match wat {
323 /// | None | Some(false) => {}
324 /// | Some(true) => {}
325 /// }
326 /// ```
327 ///
328 /// The compiler accepts it only to facilitate some situations in
329 /// macro-generated code where a macro author might need to write:
330 ///
331 /// ```
332 /// # macro_rules! doc {
333 /// # ($value:expr, ($($conditions1:pat),*), ($($conditions2:pat),*), $then:expr) => {
334 /// match $value {
335 /// $(| $conditions1)* $(| $conditions2)* => $then
336 /// }
337 /// # };
338 /// # }
339 /// #
340 /// # doc!(true, (true), (false), {});
341 /// # doc!(true, (), (true, false), {});
342 /// # doc!(true, (true, false), (), {});
343 /// ```
344 ///
345 /// Expressing the same thing correctly in the case that either one (but
346 /// not both) of `$conditions1` and `$conditions2` might be empty,
347 /// without leading `|`, is complex.
348 ///
349 /// Use [`Pat::parse_multi`] instead if you are not intending to support
350 /// macro-generated macro input.
351 pub fn parse_multi_with_leading_vert(input: ParseStream) -> Result<Self> {
352 let leading_vert: Option<Token![|]> = input.parse()?;
353 multi_pat_impl(input, leading_vert)
354 }
355 }
356
357 fn multi_pat_impl(input: ParseStream, leading_vert: Option<Token![|]>) -> Result<Pat> {
358 let mut pat = Pat::parse_single(input)?;
359 if leading_vert.is_some()
360 || input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=])
361 {
362 let mut cases = Punctuated::new();
363 cases.push_value(pat);
364 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
365 let punct = input.parse()?;
366 cases.push_punct(punct);
367 let pat = Pat::parse_single(input)?;
368 cases.push_value(pat);
369 }
370 pat = Pat::Or(PatOr {
371 attrs: Vec::new(),
372 leading_vert,
373 cases,
374 });
375 }
376 Ok(pat)
377 }
378
379 fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> {
380 let (qself, path) = path::parsing::qpath(input, true)?;
381
382 if qself.is_none()
383 && input.peek(Token![!])
384 && !input.peek(Token![!=])
385 && path.is_mod_style()
386 {
387 let bang_token: Token![!] = input.parse()?;
388 let (delimiter, tokens) = mac::parse_delimiter(input)?;
389 return Ok(Pat::Macro(ExprMacro {
390 attrs: Vec::new(),
391 mac: Macro {
392 path,
393 bang_token,
394 delimiter,
395 tokens,
396 },
397 }));
398 }
399
400 if input.peek(token::Brace) {
401 pat_struct(input, qself, path).map(Pat::Struct)
402 } else if input.peek(token::Paren) {
403 pat_tuple_struct(input, qself, path).map(Pat::TupleStruct)
404 } else if input.peek(Token![..]) {
405 pat_range(input, qself, path)
406 } else {
407 Ok(Pat::Path(ExprPath {
408 attrs: Vec::new(),
409 qself,
410 path,
411 }))
412 }
413 }
414
415 fn pat_wild(input: ParseStream) -> Result<PatWild> {
416 Ok(PatWild {
417 attrs: Vec::new(),
418 underscore_token: input.parse()?,
419 })
420 }
421
422 fn pat_box(begin: ParseBuffer, input: ParseStream) -> Result<Pat> {
423 input.parse::<Token![box]>()?;
424 Pat::parse_single(input)?;
425 Ok(Pat::Verbatim(verbatim::between(&begin, input)))
426 }
427
428 fn pat_ident(input: ParseStream) -> Result<PatIdent> {
429 Ok(PatIdent {
430 attrs: Vec::new(),
431 by_ref: input.parse()?,
432 mutability: input.parse()?,
433 ident: input.call(Ident::parse_any)?,
434 subpat: {
435 if input.peek(Token![@]) {
436 let at_token: Token![@] = input.parse()?;
437 let subpat = Pat::parse_single(input)?;
438 Some((at_token, Box::new(subpat)))
439 } else {
440 None
441 }
442 },
443 })
444 }
445
446 fn pat_tuple_struct(
447 input: ParseStream,
448 qself: Option<QSelf>,
449 path: Path,
450 ) -> Result<PatTupleStruct> {
451 let content;
452 let paren_token = parenthesized!(content in input);
453
454 let mut elems = Punctuated::new();
455 while !content.is_empty() {
456 let value = Pat::parse_multi_with_leading_vert(&content)?;
457 elems.push_value(value);
458 if content.is_empty() {
459 break;
460 }
461 let punct = content.parse()?;
462 elems.push_punct(punct);
463 }
464
465 Ok(PatTupleStruct {
466 attrs: Vec::new(),
467 qself,
468 path,
469 paren_token,
470 elems,
471 })
472 }
473
474 fn pat_struct(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<PatStruct> {
475 let content;
476 let brace_token = braced!(content in input);
477
478 let mut fields = Punctuated::new();
479 let mut rest = None;
480 while !content.is_empty() {
481 let attrs = content.call(Attribute::parse_outer)?;
482 if content.peek(Token![..]) {
483 rest = Some(PatRest {
484 attrs,
485 dot2_token: content.parse()?,
486 });
487 break;
488 }
489 let mut value = content.call(field_pat)?;
490 value.attrs = attrs;
491 fields.push_value(value);
492 if content.is_empty() {
493 break;
494 }
495 let punct: Token![,] = content.parse()?;
496 fields.push_punct(punct);
497 }
498
499 Ok(PatStruct {
500 attrs: Vec::new(),
501 qself,
502 path,
503 brace_token,
504 fields,
505 rest,
506 })
507 }
508
509 impl Member {
510 fn is_unnamed(&self) -> bool {
511 match self {
512 Member::Named(_) => false,
513 Member::Unnamed(_) => true,
514 }
515 }
516 }
517
518 fn field_pat(input: ParseStream) -> Result<FieldPat> {
519 let begin = input.fork();
520 let boxed: Option<Token![box]> = input.parse()?;
521 let by_ref: Option<Token![ref]> = input.parse()?;
522 let mutability: Option<Token![mut]> = input.parse()?;
523
524 let member = if boxed.is_some() || by_ref.is_some() || mutability.is_some() {
525 input.parse().map(Member::Named)
526 } else {
527 input.parse()
528 }?;
529
530 if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
531 || member.is_unnamed()
532 {
533 return Ok(FieldPat {
534 attrs: Vec::new(),
535 member,
536 colon_token: Some(input.parse()?),
537 pat: Box::new(Pat::parse_multi_with_leading_vert(input)?),
538 });
539 }
540
541 let ident = match member {
542 Member::Named(ident) => ident,
543 Member::Unnamed(_) => unreachable!(),
544 };
545
546 let pat = if boxed.is_some() {
547 Pat::Verbatim(verbatim::between(&begin, input))
548 } else {
549 Pat::Ident(PatIdent {
550 attrs: Vec::new(),
551 by_ref,
552 mutability,
553 ident: ident.clone(),
554 subpat: None,
555 })
556 };
557
558 Ok(FieldPat {
559 attrs: Vec::new(),
560 member: Member::Named(ident),
561 colon_token: None,
562 pat: Box::new(pat),
563 })
564 }
565
566 fn pat_range(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<Pat> {
567 let limits = RangeLimits::parse_obsolete(input)?;
568 let end = input.call(pat_range_bound)?;
569 if let (RangeLimits::Closed(_), None) = (&limits, &end) {
570 return Err(input.error("expected range upper bound"));
571 }
572 Ok(Pat::Range(ExprRange {
573 attrs: Vec::new(),
574 start: Some(Box::new(Expr::Path(ExprPath {
575 attrs: Vec::new(),
576 qself,
577 path,
578 }))),
579 limits,
580 end: end.map(PatRangeBound::into_expr),
581 }))
582 }
583
584 fn pat_range_half_open(input: ParseStream) -> Result<Pat> {
585 let limits: RangeLimits = input.parse()?;
586 let end = input.call(pat_range_bound)?;
587 if end.is_some() {
588 Ok(Pat::Range(ExprRange {
589 attrs: Vec::new(),
590 start: None,
591 limits,
592 end: end.map(PatRangeBound::into_expr),
593 }))
594 } else {
595 match limits {
596 RangeLimits::HalfOpen(dot2_token) => Ok(Pat::Rest(PatRest {
597 attrs: Vec::new(),
598 dot2_token,
599 })),
600 RangeLimits::Closed(_) => Err(input.error("expected range upper bound")),
601 }
602 }
603 }
604
605 fn pat_paren_or_tuple(input: ParseStream) -> Result<Pat> {
606 let content;
607 let paren_token = parenthesized!(content in input);
608
609 let mut elems = Punctuated::new();
610 while !content.is_empty() {
611 let value = Pat::parse_multi_with_leading_vert(&content)?;
612 if content.is_empty() {
613 if elems.is_empty() && !matches!(value, Pat::Rest(_)) {
614 return Ok(Pat::Paren(PatParen {
615 attrs: Vec::new(),
616 paren_token,
617 pat: Box::new(value),
618 }));
619 }
620 elems.push_value(value);
621 break;
622 }
623 elems.push_value(value);
624 let punct = content.parse()?;
625 elems.push_punct(punct);
626 }
627
628 Ok(Pat::Tuple(PatTuple {
629 attrs: Vec::new(),
630 paren_token,
631 elems,
632 }))
633 }
634
635 fn pat_reference(input: ParseStream) -> Result<PatReference> {
636 Ok(PatReference {
637 attrs: Vec::new(),
638 and_token: input.parse()?,
639 mutability: input.parse()?,
640 pat: Box::new(Pat::parse_single(input)?),
641 })
642 }
643
644 fn pat_lit_or_range(input: ParseStream) -> Result<Pat> {
645 let start = input.call(pat_range_bound)?.unwrap();
646 if input.peek(Token![..]) {
647 let limits = RangeLimits::parse_obsolete(input)?;
648 let end = input.call(pat_range_bound)?;
649 if let (RangeLimits::Closed(_), None) = (&limits, &end) {
650 return Err(input.error("expected range upper bound"));
651 }
652 Ok(Pat::Range(ExprRange {
653 attrs: Vec::new(),
654 start: Some(start.into_expr()),
655 limits,
656 end: end.map(PatRangeBound::into_expr),
657 }))
658 } else {
659 Ok(start.into_pat())
660 }
661 }
662
663 // Patterns that can appear on either side of a range pattern.
664 enum PatRangeBound {
665 Const(ExprConst),
666 Lit(ExprLit),
667 Path(ExprPath),
668 }
669
670 impl PatRangeBound {
671 fn into_expr(self) -> Box<Expr> {
672 Box::new(match self {
673 PatRangeBound::Const(pat) => Expr::Const(pat),
674 PatRangeBound::Lit(pat) => Expr::Lit(pat),
675 PatRangeBound::Path(pat) => Expr::Path(pat),
676 })
677 }
678
679 fn into_pat(self) -> Pat {
680 match self {
681 PatRangeBound::Const(pat) => Pat::Const(pat),
682 PatRangeBound::Lit(pat) => Pat::Lit(pat),
683 PatRangeBound::Path(pat) => Pat::Path(pat),
684 }
685 }
686 }
687
688 fn pat_range_bound(input: ParseStream) -> Result<Option<PatRangeBound>> {
689 if input.is_empty()
690 || input.peek(Token![|])
691 || input.peek(Token![=])
692 || input.peek(Token![:]) && !input.peek(Token![::])
693 || input.peek(Token![,])
694 || input.peek(Token![;])
695 || input.peek(Token![if])
696 {
697 return Ok(None);
698 }
699
700 let lookahead = input.lookahead1();
701 let expr = if lookahead.peek(Lit) {
702 PatRangeBound::Lit(input.parse()?)
703 } else if lookahead.peek(Ident)
704 || lookahead.peek(Token![::])
705 || lookahead.peek(Token![<])
706 || lookahead.peek(Token![self])
707 || lookahead.peek(Token![Self])
708 || lookahead.peek(Token![super])
709 || lookahead.peek(Token![crate])
710 {
711 PatRangeBound::Path(input.parse()?)
712 } else if lookahead.peek(Token![const]) {
713 PatRangeBound::Const(input.parse()?)
714 } else {
715 return Err(lookahead.error());
716 };
717
718 Ok(Some(expr))
719 }
720
721 fn pat_slice(input: ParseStream) -> Result<PatSlice> {
722 let content;
723 let bracket_token = bracketed!(content in input);
724
725 let mut elems = Punctuated::new();
726 while !content.is_empty() {
727 let value = Pat::parse_multi_with_leading_vert(&content)?;
728 match value {
729 Pat::Range(pat) if pat.start.is_none() || pat.end.is_none() => {
730 let (start, end) = match pat.limits {
731 RangeLimits::HalfOpen(dot_dot) => (dot_dot.spans[0], dot_dot.spans[1]),
732 RangeLimits::Closed(dot_dot_eq) => {
733 (dot_dot_eq.spans[0], dot_dot_eq.spans[2])
734 }
735 };
736 let msg = "range pattern is not allowed unparenthesized inside slice pattern";
737 return Err(error::new2(start, end, msg));
738 }
739 _ => {}
740 }
741 elems.push_value(value);
742 if content.is_empty() {
743 break;
744 }
745 let punct = content.parse()?;
746 elems.push_punct(punct);
747 }
748
749 Ok(PatSlice {
750 attrs: Vec::new(),
751 bracket_token,
752 elems,
753 })
754 }
755
756 fn pat_const(input: ParseStream) -> Result<TokenStream> {
757 let begin = input.fork();
758 input.parse::<Token![const]>()?;
759
760 let content;
761 braced!(content in input);
762 content.call(Attribute::parse_inner)?;
763 content.call(Block::parse_within)?;
764
765 Ok(verbatim::between(&begin, input))
766 }
767}
768
769#[cfg(feature = "printing")]
770mod printing {
771 use super::*;
772 use crate::attr::FilterAttrs;
773 use proc_macro2::TokenStream;
774 use quote::{ToTokens, TokenStreamExt};
775
776 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
777 impl ToTokens for PatIdent {
778 fn to_tokens(&self, tokens: &mut TokenStream) {
779 tokens.append_all(self.attrs.outer());
780 self.by_ref.to_tokens(tokens);
781 self.mutability.to_tokens(tokens);
782 self.ident.to_tokens(tokens);
783 if let Some((at_token, subpat)) = &self.subpat {
784 at_token.to_tokens(tokens);
785 subpat.to_tokens(tokens);
786 }
787 }
788 }
789
790 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
791 impl ToTokens for PatOr {
792 fn to_tokens(&self, tokens: &mut TokenStream) {
793 tokens.append_all(self.attrs.outer());
794 self.leading_vert.to_tokens(tokens);
795 self.cases.to_tokens(tokens);
796 }
797 }
798
799 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
800 impl ToTokens for PatParen {
801 fn to_tokens(&self, tokens: &mut TokenStream) {
802 tokens.append_all(self.attrs.outer());
803 self.paren_token.surround(tokens, |tokens| {
804 self.pat.to_tokens(tokens);
805 });
806 }
807 }
808
809 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
810 impl ToTokens for PatReference {
811 fn to_tokens(&self, tokens: &mut TokenStream) {
812 tokens.append_all(self.attrs.outer());
813 self.and_token.to_tokens(tokens);
814 self.mutability.to_tokens(tokens);
815 self.pat.to_tokens(tokens);
816 }
817 }
818
819 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
820 impl ToTokens for PatRest {
821 fn to_tokens(&self, tokens: &mut TokenStream) {
822 tokens.append_all(self.attrs.outer());
823 self.dot2_token.to_tokens(tokens);
824 }
825 }
826
827 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
828 impl ToTokens for PatSlice {
829 fn to_tokens(&self, tokens: &mut TokenStream) {
830 tokens.append_all(self.attrs.outer());
831 self.bracket_token.surround(tokens, |tokens| {
832 self.elems.to_tokens(tokens);
833 });
834 }
835 }
836
837 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
838 impl ToTokens for PatStruct {
839 fn to_tokens(&self, tokens: &mut TokenStream) {
840 tokens.append_all(self.attrs.outer());
841 path::printing::print_path(tokens, &self.qself, &self.path);
842 self.brace_token.surround(tokens, |tokens| {
843 self.fields.to_tokens(tokens);
844 // NOTE: We need a comma before the dot2 token if it is present.
845 if !self.fields.empty_or_trailing() && self.rest.is_some() {
846 <Token![,]>::default().to_tokens(tokens);
847 }
848 self.rest.to_tokens(tokens);
849 });
850 }
851 }
852
853 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
854 impl ToTokens for PatTuple {
855 fn to_tokens(&self, tokens: &mut TokenStream) {
856 tokens.append_all(self.attrs.outer());
857 self.paren_token.surround(tokens, |tokens| {
858 self.elems.to_tokens(tokens);
859 });
860 }
861 }
862
863 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
864 impl ToTokens for PatTupleStruct {
865 fn to_tokens(&self, tokens: &mut TokenStream) {
866 tokens.append_all(self.attrs.outer());
867 path::printing::print_path(tokens, &self.qself, &self.path);
868 self.paren_token.surround(tokens, |tokens| {
869 self.elems.to_tokens(tokens);
870 });
871 }
872 }
873
874 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
875 impl ToTokens for PatType {
876 fn to_tokens(&self, tokens: &mut TokenStream) {
877 tokens.append_all(self.attrs.outer());
878 self.pat.to_tokens(tokens);
879 self.colon_token.to_tokens(tokens);
880 self.ty.to_tokens(tokens);
881 }
882 }
883
884 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
885 impl ToTokens for PatWild {
886 fn to_tokens(&self, tokens: &mut TokenStream) {
887 tokens.append_all(self.attrs.outer());
888 self.underscore_token.to_tokens(tokens);
889 }
890 }
891
892 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
893 impl ToTokens for FieldPat {
894 fn to_tokens(&self, tokens: &mut TokenStream) {
895 tokens.append_all(self.attrs.outer());
896 if let Some(colon_token) = &self.colon_token {
897 self.member.to_tokens(tokens);
898 colon_token.to_tokens(tokens);
899 }
900 self.pat.to_tokens(tokens);
901 }
902 }
903}
904