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