2 use crate::punctuated
::Punctuated
;
3 use proc_macro2
::TokenStream
;
6 /// A pattern in a local binding, function signature, match expression, or
7 /// various other places.
9 /// *This type is available only if Syn is built with the `"full"` feature.*
11 /// # Syntax tree enum
13 /// This type is a [syntax tree enum].
15 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
17 // TODO: change syntax-tree-enum link to an intra rustdoc link, currently
18 // blocked on https://github.com/rust-lang/rust/issues/62833
20 /// A box pattern: `box v`.
23 /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
26 /// A literal pattern: `0`.
28 /// This holds an `Expr` rather than a `Lit` because negative numbers
29 /// are represented as an `Expr::Unary`.
32 /// A macro in pattern position.
35 /// A pattern that matches any one of a set of cases.
38 /// A path pattern like `Color::Red`, optionally qualified with a
41 /// Unqualified path patterns can legally refer to variants, structs,
42 /// constants or associated constants. Qualified path patterns like
43 /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
44 /// associated constants.
47 /// A range pattern: `1..=2`.
50 /// A reference pattern: `&mut var`.
51 Reference(PatReference
),
53 /// The dots in a tuple or slice pattern: `[0, 1, ..]`
56 /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`.
59 /// A struct or struct variant pattern: `Variant { x, y, .. }`.
62 /// A tuple pattern: `(a, b)`.
65 /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
66 TupleStruct(PatTupleStruct
),
68 /// A type ascription pattern: `foo: f64`.
71 /// Tokens in pattern position not interpreted by Syn.
72 Verbatim(TokenStream
),
74 /// A pattern that matches any value: `_`.
83 /// A box pattern: `box v`.
85 /// *This type is available only if Syn is built with the `"full"` feature.*
87 pub attrs
: Vec
<Attribute
>,
88 pub box_token
: Token
![box],
94 /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
96 /// It may also be a unit struct or struct variant (e.g. `None`), or a
97 /// constant; these cannot be distinguished syntactically.
99 /// *This type is available only if Syn is built with the `"full"` feature.*
100 pub struct PatIdent
{
101 pub attrs
: Vec
<Attribute
>,
102 pub by_ref
: Option
<Token
![ref]>,
103 pub mutability
: Option
<Token
![mut]>,
105 pub subpat
: Option
<(Token
![@
], Box
<Pat
>)>,
110 /// A literal pattern: `0`.
112 /// This holds an `Expr` rather than a `Lit` because negative numbers
113 /// are represented as an `Expr::Unary`.
115 /// *This type is available only if Syn is built with the `"full"` feature.*
117 pub attrs
: Vec
<Attribute
>,
123 /// A macro in pattern position.
125 /// *This type is available only if Syn is built with the `"full"` feature.*
126 pub struct PatMacro
{
127 pub attrs
: Vec
<Attribute
>,
133 /// A pattern that matches any one of a set of cases.
135 /// *This type is available only if Syn is built with the `"full"` feature.*
137 pub attrs
: Vec
<Attribute
>,
138 pub leading_vert
: Option
<Token
![|]>,
139 pub cases
: Punctuated
<Pat
, Token
![|]>,
144 /// A path pattern like `Color::Red`, optionally qualified with a
147 /// Unqualified path patterns can legally refer to variants, structs,
148 /// constants or associated constants. Qualified path patterns like
149 /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
150 /// associated constants.
152 /// *This type is available only if Syn is built with the `"full"` feature.*
154 pub attrs
: Vec
<Attribute
>,
155 pub qself
: Option
<QSelf
>,
161 /// A range pattern: `1..=2`.
163 /// *This type is available only if Syn is built with the `"full"` feature.*
164 pub struct PatRange
{
165 pub attrs
: Vec
<Attribute
>,
167 pub limits
: RangeLimits
,
173 /// A reference pattern: `&mut var`.
175 /// *This type is available only if Syn is built with the `"full"` feature.*
176 pub struct PatReference
{
177 pub attrs
: Vec
<Attribute
>,
178 pub and_token
: Token
![&],
179 pub mutability
: Option
<Token
![mut]>,
185 /// The dots in a tuple or slice pattern: `[0, 1, ..]`
187 /// *This type is available only if Syn is built with the `"full"` feature.*
189 pub attrs
: Vec
<Attribute
>,
190 pub dot2_token
: Token
![..],
195 /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`.
197 /// *This type is available only if Syn is built with the `"full"` feature.*
198 pub struct PatSlice
{
199 pub attrs
: Vec
<Attribute
>,
200 pub bracket_token
: token
::Bracket
,
201 pub elems
: Punctuated
<Pat
, Token
![,]>,
206 /// A struct or struct variant pattern: `Variant { x, y, .. }`.
208 /// *This type is available only if Syn is built with the `"full"` feature.*
209 pub struct PatStruct
{
210 pub attrs
: Vec
<Attribute
>,
212 pub brace_token
: token
::Brace
,
213 pub fields
: Punctuated
<FieldPat
, Token
![,]>,
214 pub dot2_token
: Option
<Token
![..]>,
219 /// A tuple pattern: `(a, b)`.
221 /// *This type is available only if Syn is built with the `"full"` feature.*
222 pub struct PatTuple
{
223 pub attrs
: Vec
<Attribute
>,
224 pub paren_token
: token
::Paren
,
225 pub elems
: Punctuated
<Pat
, Token
![,]>,
230 /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
232 /// *This type is available only if Syn is built with the `"full"` feature.*
233 pub struct PatTupleStruct
{
234 pub attrs
: Vec
<Attribute
>,
241 /// A type ascription pattern: `foo: f64`.
243 /// *This type is available only if Syn is built with the `"full"` feature.*
245 pub attrs
: Vec
<Attribute
>,
247 pub colon_token
: Token
![:],
253 /// A pattern that matches any value: `_`.
255 /// *This type is available only if Syn is built with the `"full"` feature.*
257 pub attrs
: Vec
<Attribute
>,
258 pub underscore_token
: Token
![_
],
263 /// A single field in a struct pattern.
265 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
266 /// the same as `x: x, y: ref y, z: ref mut z` but there is no colon token.
268 /// *This type is available only if Syn is built with the `"full"` feature.*
269 pub struct FieldPat
{
270 pub attrs
: Vec
<Attribute
>,
272 pub colon_token
: Option
<Token
![:]>,
277 #[cfg(feature = "parsing")]
280 use crate::ext
::IdentExt
;
281 use crate::parse
::{Parse, ParseBuffer, ParseStream, Result}
;
285 fn parse(input
: ParseStream
) -> Result
<Self> {
286 let begin
= input
.fork();
287 let lookahead
= input
.lookahead1();
288 if lookahead
.peek(Ident
)
290 input
.peek2(Token
![::])
291 || input
.peek2(Token
![!])
292 || input
.peek2(token
::Brace
)
293 || input
.peek2(token
::Paren
)
294 || input
.peek2(Token
![..])
296 let ahead
= input
.fork();
297 ahead
.parse
::<Ident
>()?
;
298 ahead
.parse
::<RangeLimits
>()?
;
299 ahead
.is_empty() || ahead
.peek(Token
![,])
302 || input
.peek(Token
![self]) && input
.peek2(Token
![::])
303 || lookahead
.peek(Token
![::])
304 || lookahead
.peek(Token
![<])
305 || input
.peek(Token
![Self])
306 || input
.peek(Token
![super])
307 || input
.peek(Token
![crate])
309 pat_path_or_macro_or_struct_or_range(input
)
310 } else if lookahead
.peek(Token
![_
]) {
311 input
.call(pat_wild
).map(Pat
::Wild
)
312 } else if input
.peek(Token
![box]) {
313 input
.call(pat_box
).map(Pat
::Box
)
314 } else if input
.peek(Token
![-]) || lookahead
.peek(Lit
) {
315 pat_lit_or_range(input
)
316 } else if lookahead
.peek(Token
![ref])
317 || lookahead
.peek(Token
![mut])
318 || input
.peek(Token
![self])
321 input
.call(pat_ident
).map(Pat
::Ident
)
322 } else if lookahead
.peek(Token
![&]) {
323 input
.call(pat_reference
).map(Pat
::Reference
)
324 } else if lookahead
.peek(token
::Paren
) {
325 input
.call(pat_tuple
).map(Pat
::Tuple
)
326 } else if lookahead
.peek(token
::Bracket
) {
327 input
.call(pat_slice
).map(Pat
::Slice
)
328 } else if lookahead
.peek(Token
![..]) && !input
.peek(Token
![...]) {
329 pat_range_half_open(input
, begin
)
331 Err(lookahead
.error())
336 fn pat_path_or_macro_or_struct_or_range(input
: ParseStream
) -> Result
<Pat
> {
337 let begin
= input
.fork();
338 let (qself
, path
) = path
::parsing
::qpath(input
, true)?
;
340 if input
.peek(Token
![..]) {
341 return pat_range(input
, begin
, qself
, path
);
345 return Ok(Pat
::Path(PatPath
{
352 if input
.peek(Token
![!]) && !input
.peek(Token
![!=]) {
353 let mut contains_arguments
= false;
354 for segment
in &path
.segments
{
355 match segment
.arguments
{
356 PathArguments
::None
=> {}
357 PathArguments
::AngleBracketed(_
) | PathArguments
::Parenthesized(_
) => {
358 contains_arguments
= true;
363 if !contains_arguments
{
364 let bang_token
: Token
![!] = input
.parse()?
;
365 let (delimiter
, tokens
) = mac
::parse_delimiter(input
)?
;
366 return Ok(Pat
::Macro(PatMacro
{
378 if input
.peek(token
::Brace
) {
379 pat_struct(input
, path
).map(Pat
::Struct
)
380 } else if input
.peek(token
::Paren
) {
381 pat_tuple_struct(input
, path
).map(Pat
::TupleStruct
)
382 } else if input
.peek(Token
![..]) {
383 pat_range(input
, begin
, qself
, path
)
385 Ok(Pat
::Path(PatPath
{
393 fn pat_wild(input
: ParseStream
) -> Result
<PatWild
> {
396 underscore_token
: input
.parse()?
,
400 fn pat_box(input
: ParseStream
) -> Result
<PatBox
> {
403 box_token
: input
.parse()?
,
408 fn pat_ident(input
: ParseStream
) -> Result
<PatIdent
> {
411 by_ref
: input
.parse()?
,
412 mutability
: input
.parse()?
,
413 ident
: input
.call(Ident
::parse_any
)?
,
415 if input
.peek(Token
![@
]) {
416 let at_token
: Token
![@
] = input
.parse()?
;
417 let subpat
: Pat
= input
.parse()?
;
418 Some((at_token
, Box
::new(subpat
)))
426 fn pat_tuple_struct(input
: ParseStream
, path
: Path
) -> Result
<PatTupleStruct
> {
430 pat
: input
.call(pat_tuple
)?
,
434 fn pat_struct(input
: ParseStream
, path
: Path
) -> Result
<PatStruct
> {
436 let brace_token
= braced
!(content
in input
);
438 let mut fields
= Punctuated
::new();
439 while !content
.is_empty() && !content
.peek(Token
![..]) {
440 let value
= content
.call(field_pat
)?
;
441 fields
.push_value(value
);
442 if content
.is_empty() {
445 let punct
: Token
![,] = content
.parse()?
;
446 fields
.push_punct(punct
);
449 let dot2_token
= if fields
.empty_or_trailing() && content
.peek(Token
![..]) {
450 Some(content
.parse()?
)
465 fn is_unnamed(&self) -> bool
{
467 Member
::Named(_
) => false,
468 Member
::Unnamed(_
) => true,
473 fn field_pat(input
: ParseStream
) -> Result
<FieldPat
> {
474 let attrs
= input
.call(Attribute
::parse_outer
)?
;
475 let boxed
: Option
<Token
![box]> = input
.parse()?
;
476 let by_ref
: Option
<Token
![ref]> = input
.parse()?
;
477 let mutability
: Option
<Token
![mut]> = input
.parse()?
;
478 let member
: Member
= input
.parse()?
;
480 if boxed
.is_none() && by_ref
.is_none() && mutability
.is_none() && input
.peek(Token
![:])
481 || member
.is_unnamed()
486 colon_token
: input
.parse()?
,
487 pat
: Box
::new(multi_pat(input
)?
),
491 let ident
= match member
{
492 Member
::Named(ident
) => ident
,
493 Member
::Unnamed(_
) => unreachable
!(),
496 let mut pat
= Pat
::Ident(PatIdent
{
500 ident
: ident
.clone(),
504 if let Some(boxed
) = boxed
{
505 pat
= Pat
::Box(PatBox
{
514 member
: Member
::Named(ident
),
523 qself
: Option
<QSelf
>,
526 let limits
: RangeLimits
= input
.parse()?
;
527 let hi
= input
.call(pat_lit_expr
)?
;
528 if let Some(hi
) = hi
{
529 Ok(Pat
::Range(PatRange
{
531 lo
: Box
::new(Expr
::Path(ExprPath
{
540 Ok(Pat
::Verbatim(verbatim
::between(begin
, input
)))
544 fn pat_range_half_open(input
: ParseStream
, begin
: ParseBuffer
) -> Result
<Pat
> {
545 let limits
: RangeLimits
= input
.parse()?
;
546 let hi
= input
.call(pat_lit_expr
)?
;
548 Ok(Pat
::Verbatim(verbatim
::between(begin
, input
)))
551 RangeLimits
::HalfOpen(dot2_token
) => Ok(Pat
::Rest(PatRest
{
555 RangeLimits
::Closed(_
) => Err(input
.error("expected range upper bound")),
560 fn pat_tuple(input
: ParseStream
) -> Result
<PatTuple
> {
562 let paren_token
= parenthesized
!(content
in input
);
564 let mut elems
= Punctuated
::new();
565 while !content
.is_empty() {
566 let value
= multi_pat(&content
)?
;
567 elems
.push_value(value
);
568 if content
.is_empty() {
571 let punct
= content
.parse()?
;
572 elems
.push_punct(punct
);
582 fn pat_reference(input
: ParseStream
) -> Result
<PatReference
> {
585 and_token
: input
.parse()?
,
586 mutability
: input
.parse()?
,
591 fn pat_lit_or_range(input
: ParseStream
) -> Result
<Pat
> {
592 let begin
= input
.fork();
593 let lo
= input
.call(pat_lit_expr
)?
.unwrap();
594 if input
.peek(Token
![..]) {
595 let limits
: RangeLimits
= input
.parse()?
;
596 let hi
= input
.call(pat_lit_expr
)?
;
597 if let Some(hi
) = hi
{
598 Ok(Pat
::Range(PatRange
{
605 Ok(Pat
::Verbatim(verbatim
::between(begin
, input
)))
615 fn pat_lit_expr(input
: ParseStream
) -> Result
<Option
<Box
<Expr
>>> {
617 || input
.peek(Token
![|])
618 || input
.peek(Token
![=>])
619 || input
.peek(Token
![:]) && !input
.peek(Token
![::])
620 || input
.peek(Token
![,])
621 || input
.peek(Token
![;])
626 let neg
: Option
<Token
![-]> = input
.parse()?
;
628 let lookahead
= input
.lookahead1();
629 let expr
= if lookahead
.peek(Lit
) {
630 Expr
::Lit(input
.parse()?
)
631 } else if lookahead
.peek(Ident
)
632 || lookahead
.peek(Token
![::])
633 || lookahead
.peek(Token
![<])
634 || lookahead
.peek(Token
![self])
635 || lookahead
.peek(Token
![Self])
636 || lookahead
.peek(Token
![super])
637 || lookahead
.peek(Token
![crate])
639 Expr
::Path(input
.parse()?
)
641 return Err(lookahead
.error());
644 Ok(Some(Box
::new(if let Some(neg
) = neg
{
645 Expr
::Unary(ExprUnary
{
648 expr
: Box
::new(expr
),
655 fn pat_slice(input
: ParseStream
) -> Result
<PatSlice
> {
657 let bracket_token
= bracketed
!(content
in input
);
659 let mut elems
= Punctuated
::new();
660 while !content
.is_empty() {
661 let value
= multi_pat(&content
)?
;
662 elems
.push_value(value
);
663 if content
.is_empty() {
666 let punct
= content
.parse()?
;
667 elems
.push_punct(punct
);
677 pub fn multi_pat(input
: ParseStream
) -> Result
<Pat
> {
678 multi_pat_impl(input
, None
)
681 pub fn multi_pat_with_leading_vert(input
: ParseStream
) -> Result
<Pat
> {
682 let leading_vert
: Option
<Token
![|]> = input
.parse()?
;
683 multi_pat_impl(input
, leading_vert
)
686 fn multi_pat_impl(input
: ParseStream
, leading_vert
: Option
<Token
![|]>) -> Result
<Pat
> {
687 let mut pat
: Pat
= input
.parse()?
;
688 if leading_vert
.is_some()
689 || input
.peek(Token
![|]) && !input
.peek(Token
![||]) && !input
.peek(Token
![|=])
691 let mut cases
= Punctuated
::new();
692 cases
.push_value(pat
);
693 while input
.peek(Token
![|]) && !input
.peek(Token
![||]) && !input
.peek(Token
![|=]) {
694 let punct
= input
.parse()?
;
695 cases
.push_punct(punct
);
696 let pat
: Pat
= input
.parse()?
;
697 cases
.push_value(pat
);
699 pat
= Pat
::Or(PatOr
{
709 #[cfg(feature = "printing")]
712 use crate::attr
::FilterAttrs
;
713 use proc_macro2
::TokenStream
;
714 use quote
::{ToTokens, TokenStreamExt}
;
716 impl ToTokens
for PatWild
{
717 fn to_tokens(&self, tokens
: &mut TokenStream
) {
718 tokens
.append_all(self.attrs
.outer());
719 self.underscore_token
.to_tokens(tokens
);
723 impl ToTokens
for PatIdent
{
724 fn to_tokens(&self, tokens
: &mut TokenStream
) {
725 tokens
.append_all(self.attrs
.outer());
726 self.by_ref
.to_tokens(tokens
);
727 self.mutability
.to_tokens(tokens
);
728 self.ident
.to_tokens(tokens
);
729 if let Some((at_token
, subpat
)) = &self.subpat
{
730 at_token
.to_tokens(tokens
);
731 subpat
.to_tokens(tokens
);
736 impl ToTokens
for PatStruct
{
737 fn to_tokens(&self, tokens
: &mut TokenStream
) {
738 tokens
.append_all(self.attrs
.outer());
739 self.path
.to_tokens(tokens
);
740 self.brace_token
.surround(tokens
, |tokens
| {
741 self.fields
.to_tokens(tokens
);
742 // NOTE: We need a comma before the dot2 token if it is present.
743 if !self.fields
.empty_or_trailing() && self.dot2_token
.is_some() {
744 <Token
![,]>::default().to_tokens(tokens
);
746 self.dot2_token
.to_tokens(tokens
);
751 impl ToTokens
for PatTupleStruct
{
752 fn to_tokens(&self, tokens
: &mut TokenStream
) {
753 tokens
.append_all(self.attrs
.outer());
754 self.path
.to_tokens(tokens
);
755 self.pat
.to_tokens(tokens
);
759 impl ToTokens
for PatType
{
760 fn to_tokens(&self, tokens
: &mut TokenStream
) {
761 tokens
.append_all(self.attrs
.outer());
762 self.pat
.to_tokens(tokens
);
763 self.colon_token
.to_tokens(tokens
);
764 self.ty
.to_tokens(tokens
);
768 impl ToTokens
for PatPath
{
769 fn to_tokens(&self, tokens
: &mut TokenStream
) {
770 tokens
.append_all(self.attrs
.outer());
771 private
::print_path(tokens
, &self.qself
, &self.path
);
775 impl ToTokens
for PatTuple
{
776 fn to_tokens(&self, tokens
: &mut TokenStream
) {
777 tokens
.append_all(self.attrs
.outer());
778 self.paren_token
.surround(tokens
, |tokens
| {
779 self.elems
.to_tokens(tokens
);
784 impl ToTokens
for PatBox
{
785 fn to_tokens(&self, tokens
: &mut TokenStream
) {
786 tokens
.append_all(self.attrs
.outer());
787 self.box_token
.to_tokens(tokens
);
788 self.pat
.to_tokens(tokens
);
792 impl ToTokens
for PatReference
{
793 fn to_tokens(&self, tokens
: &mut TokenStream
) {
794 tokens
.append_all(self.attrs
.outer());
795 self.and_token
.to_tokens(tokens
);
796 self.mutability
.to_tokens(tokens
);
797 self.pat
.to_tokens(tokens
);
801 impl ToTokens
for PatRest
{
802 fn to_tokens(&self, tokens
: &mut TokenStream
) {
803 tokens
.append_all(self.attrs
.outer());
804 self.dot2_token
.to_tokens(tokens
);
808 impl ToTokens
for PatLit
{
809 fn to_tokens(&self, tokens
: &mut TokenStream
) {
810 tokens
.append_all(self.attrs
.outer());
811 self.expr
.to_tokens(tokens
);
815 impl ToTokens
for PatRange
{
816 fn to_tokens(&self, tokens
: &mut TokenStream
) {
817 tokens
.append_all(self.attrs
.outer());
818 self.lo
.to_tokens(tokens
);
820 RangeLimits
::HalfOpen(t
) => t
.to_tokens(tokens
),
821 RangeLimits
::Closed(t
) => t
.to_tokens(tokens
),
823 self.hi
.to_tokens(tokens
);
827 impl ToTokens
for PatSlice
{
828 fn to_tokens(&self, tokens
: &mut TokenStream
) {
829 tokens
.append_all(self.attrs
.outer());
830 self.bracket_token
.surround(tokens
, |tokens
| {
831 self.elems
.to_tokens(tokens
);
836 impl ToTokens
for PatMacro
{
837 fn to_tokens(&self, tokens
: &mut TokenStream
) {
838 tokens
.append_all(self.attrs
.outer());
839 self.mac
.to_tokens(tokens
);
843 impl ToTokens
for PatOr
{
844 fn to_tokens(&self, tokens
: &mut TokenStream
) {
845 tokens
.append_all(self.attrs
.outer());
846 self.leading_vert
.to_tokens(tokens
);
847 self.cases
.to_tokens(tokens
);
851 impl ToTokens
for FieldPat
{
852 fn to_tokens(&self, tokens
: &mut TokenStream
) {
853 tokens
.append_all(self.attrs
.outer());
854 if let Some(colon_token
) = &self.colon_token
{
855 self.member
.to_tokens(tokens
);
856 colon_token
.to_tokens(tokens
);
858 self.pat
.to_tokens(tokens
);