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