1use crate::attr::Attribute;
2use crate::expr::{Expr, Member};
3use crate::ident::Ident;
4use crate::path::{Path, QSelf};
5use crate::punctuated::Punctuated;
6use crate::token;
7use crate::ty::Type;
8use alloc::boxed::Box;
9use alloc::vec::Vec;
10use proc_macro2::TokenStream;
11
12pub use crate::expr::{
13 ExprConst as PatConst, ExprLit as PatLit, ExprMacro as PatMacro, ExprPath as PatPath,
14 ExprRange as PatRange,
15};
16
17#[doc =
r" A pattern in a local binding, function signature, match expression, or"]
#[doc = r" various other places."]
#[doc = r""]
#[doc = r" # Syntax tree enum"]
#[doc = r""]
#[doc = r" This type is a [syntax tree enum]."]
#[doc = r""]
#[doc = r" [syntax tree enum]: crate::expr::Expr#syntax-tree-enums"]
#[doc(cfg(feature = "full"))]
#[non_exhaustive]
pub enum Pat {
#[doc = r" A const block: `const { ... }`."]
Const(PatConst),
#[doc = r" A pattern with guard predicate: `Some(x) if x > 0`."]
Guard(PatGuard),
#[doc =
r" A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`."]
Ident(PatIdent),
#[doc = r" A literal pattern: `0`."]
Lit(PatLit),
#[doc = r" A macro in pattern position."]
Macro(PatMacro),
#[doc = r" A pattern that matches any one of a set of cases."]
Or(PatOr),
#[doc = r" A parenthesized pattern: `(A | B)`."]
Paren(PatParen),
#[doc = r" A path pattern like `Color::Red`, optionally qualified with a"]
#[doc = r" self-type."]
#[doc = r""]
#[doc =
r" Unqualified path patterns can legally refer to variants, structs,"]
#[doc =
r" constants or associated constants. Qualified path patterns like"]
#[doc =
r" `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to"]
#[doc = r" associated constants."]
Path(PatPath),
#[doc = r" A range pattern: `1..=2`."]
Range(PatRange),
#[doc = r" A reference pattern: `&mut var`."]
Reference(PatReference),
#[doc = r" The dots in a tuple or slice pattern: `[0, 1, ..]`."]
Rest(PatRest),
#[doc =
r" A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`."]
Slice(PatSlice),
#[doc = r" A struct or struct variant pattern: `Variant { x, y, .. }`."]
Struct(PatStruct),
#[doc = r" A tuple pattern: `(a, b)`."]
Tuple(PatTuple),
#[doc =
r" A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`."]
TupleStruct(PatTupleStruct),
#[doc = r" A type ascription pattern: `foo: f64`."]
Type(PatType),
#[doc = r" Tokens in pattern position not interpreted by Syn."]
#[doc = r""]
#[doc = r#" <div class="warning">"#]
#[doc = r""]
#[doc =
r" Important: see [Compatibility notes][crate#verbatim-variants]."]
#[doc = r""]
#[doc = r" </div>"]
Verbatim(TokenStream),
#[doc = r" A pattern that matches any value: `_`."]
Wild(PatWild),
}
#[doc(cfg(feature = "printing"))]
impl ::quote::ToTokens for Pat {
fn to_tokens(&self, tokens: &mut ::proc_macro2::TokenStream) {
match self {
Pat::Const(_e) => _e.to_tokens(tokens),
Pat::Guard(_e) => _e.to_tokens(tokens),
Pat::Ident(_e) => _e.to_tokens(tokens),
Pat::Lit(_e) => _e.to_tokens(tokens),
Pat::Macro(_e) => _e.to_tokens(tokens),
Pat::Or(_e) => _e.to_tokens(tokens),
Pat::Paren(_e) => _e.to_tokens(tokens),
Pat::Path(_e) => _e.to_tokens(tokens),
Pat::Range(_e) => _e.to_tokens(tokens),
Pat::Reference(_e) => _e.to_tokens(tokens),
Pat::Rest(_e) => _e.to_tokens(tokens),
Pat::Slice(_e) => _e.to_tokens(tokens),
Pat::Struct(_e) => _e.to_tokens(tokens),
Pat::Tuple(_e) => _e.to_tokens(tokens),
Pat::TupleStruct(_e) => _e.to_tokens(tokens),
Pat::Type(_e) => _e.to_tokens(tokens),
Pat::Verbatim(_e) => _e.to_tokens(tokens),
Pat::Wild(_e) => _e.to_tokens(tokens),
}
}
}ast_enum_of_structs! {
18 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
27 #[non_exhaustive]
28 pub enum Pat {
29 Const(PatConst),
31
32 Guard(PatGuard),
34
35 Ident(PatIdent),
37
38 Lit(PatLit),
40
41 Macro(PatMacro),
43
44 Or(PatOr),
46
47 Paren(PatParen),
49
50 Path(PatPath),
58
59 Range(PatRange),
61
62 Reference(PatReference),
64
65 Rest(PatRest),
67
68 Slice(PatSlice),
70
71 Struct(PatStruct),
73
74 Tuple(PatTuple),
76
77 TupleStruct(PatTupleStruct),
79
80 Type(PatType),
82
83 Verbatim(TokenStream),
91
92 Wild(PatWild),
94 }
95}
96
97#[doc =
r" A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`."]
#[doc = r""]
#[doc =
r" It may also be a unit struct or struct variant (e.g. `None`), or a"]
#[doc = r" constant; these cannot be distinguished syntactically."]
#[doc(cfg(feature = "full"))]
pub struct PatIdent {
pub attrs: Vec<Attribute>,
pub by_ref: Option<crate::token::Ref>,
pub mutability: Option<crate::token::Mut>,
pub ident: Ident,
pub subpat: Option<(crate::token::At, Box<Pat>)>,
}ast_struct! {
98 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
103 pub struct PatIdent {
104 pub attrs: Vec<Attribute>,
105 pub by_ref: Option<Token![ref]>,
106 pub mutability: Option<Token![mut]>,
107 pub ident: Ident,
108 pub subpat: Option<(Token![@], Box<Pat>)>,
109 }
110}
111
112#[doc = r" A pattern with guard predicate: `Some(x) if x > 0`."]
#[doc(cfg(feature = "full"))]
pub struct PatGuard {
pub attrs: Vec<Attribute>,
pub pat: Box<Pat>,
pub if_token: crate::token::If,
pub guard: Box<Expr>,
}ast_struct! {
113 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
115 pub struct PatGuard {
116 pub attrs: Vec<Attribute>,
117 pub pat: Box<Pat>,
118 pub if_token: Token![if],
119 pub guard: Box<Expr>,
120 }
121}
122
123#[doc = r" A pattern that matches any one of a set of cases."]
#[doc(cfg(feature = "full"))]
pub struct PatOr {
pub attrs: Vec<Attribute>,
pub leading_vert: Option<crate::token::Or>,
pub cases: Punctuated<Pat, crate::token::Or>,
}ast_struct! {
124 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
126 pub struct PatOr {
127 pub attrs: Vec<Attribute>,
128 pub leading_vert: Option<Token![|]>,
129 pub cases: Punctuated<Pat, Token![|]>,
130 }
131}
132
133#[doc = r" A parenthesized pattern: `(A | B)`."]
#[doc(cfg(feature = "full"))]
pub struct PatParen {
pub attrs: Vec<Attribute>,
pub paren_token: token::Paren,
pub pat: Box<Pat>,
}ast_struct! {
134 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
136 pub struct PatParen {
137 pub attrs: Vec<Attribute>,
138 pub paren_token: token::Paren,
139 pub pat: Box<Pat>,
140 }
141}
142
143#[doc = r" A reference pattern: `&mut var`."]
#[doc(cfg(feature = "full"))]
pub struct PatReference {
pub attrs: Vec<Attribute>,
pub and_token: crate::token::And,
pub mutability: Option<crate::token::Mut>,
pub pat: Box<Pat>,
}ast_struct! {
144 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
146 pub struct PatReference {
147 pub attrs: Vec<Attribute>,
148 pub and_token: Token![&],
149 pub mutability: Option<Token![mut]>,
150 pub pat: Box<Pat>,
151 }
152}
153
154#[doc = r" The dots in a tuple or slice pattern: `[0, 1, ..]`."]
#[doc(cfg(feature = "full"))]
pub struct PatRest {
pub attrs: Vec<Attribute>,
pub dot2_token: crate::token::DotDot,
}ast_struct! {
155 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
157 pub struct PatRest {
158 pub attrs: Vec<Attribute>,
159 pub dot2_token: Token![..],
160 }
161}
162
163#[doc = r" A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`."]
#[doc(cfg(feature = "full"))]
pub struct PatSlice {
pub attrs: Vec<Attribute>,
pub bracket_token: token::Bracket,
pub elems: Punctuated<Pat, crate::token::Comma>,
}ast_struct! {
164 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
166 pub struct PatSlice {
167 pub attrs: Vec<Attribute>,
168 pub bracket_token: token::Bracket,
169 pub elems: Punctuated<Pat, Token![,]>,
170 }
171}
172
173#[doc = r" A struct or struct variant pattern: `Variant { x, y, .. }`."]
#[doc(cfg(feature = "full"))]
pub struct PatStruct {
pub attrs: Vec<Attribute>,
pub qself: Option<QSelf>,
pub path: Path,
pub brace_token: token::Brace,
pub fields: Punctuated<FieldPat, crate::token::Comma>,
pub rest: Option<PatRest>,
}ast_struct! {
174 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
176 pub struct PatStruct {
177 pub attrs: Vec<Attribute>,
178 pub qself: Option<QSelf>,
179 pub path: Path,
180 pub brace_token: token::Brace,
181 pub fields: Punctuated<FieldPat, Token![,]>,
182 pub rest: Option<PatRest>,
183 }
184}
185
186#[doc = r" A tuple pattern: `(a, b)`."]
#[doc(cfg(feature = "full"))]
pub struct PatTuple {
pub attrs: Vec<Attribute>,
pub paren_token: token::Paren,
pub elems: Punctuated<Pat, crate::token::Comma>,
}ast_struct! {
187 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
189 pub struct PatTuple {
190 pub attrs: Vec<Attribute>,
191 pub paren_token: token::Paren,
192 pub elems: Punctuated<Pat, Token![,]>,
193 }
194}
195
196#[doc = r" A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`."]
#[doc(cfg(feature = "full"))]
pub struct PatTupleStruct {
pub attrs: Vec<Attribute>,
pub qself: Option<QSelf>,
pub path: Path,
pub paren_token: token::Paren,
pub elems: Punctuated<Pat, crate::token::Comma>,
}ast_struct! {
197 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
199 pub struct PatTupleStruct {
200 pub attrs: Vec<Attribute>,
201 pub qself: Option<QSelf>,
202 pub path: Path,
203 pub paren_token: token::Paren,
204 pub elems: Punctuated<Pat, Token![,]>,
205 }
206}
207
208#[doc = r" A type ascription pattern: `foo: f64`."]
#[doc(cfg(feature = "full"))]
pub struct PatType {
pub attrs: Vec<Attribute>,
pub pat: Box<Pat>,
pub colon_token: crate::token::Colon,
pub ty: Box<Type>,
}ast_struct! {
209 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
211 pub struct PatType {
212 pub attrs: Vec<Attribute>,
213 pub pat: Box<Pat>,
214 pub colon_token: Token![:],
215 pub ty: Box<Type>,
216 }
217}
218
219#[doc = r" A pattern that matches any value: `_`."]
#[doc(cfg(feature = "full"))]
pub struct PatWild {
pub attrs: Vec<Attribute>,
pub underscore_token: crate::token::Underscore,
}ast_struct! {
220 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
222 pub struct PatWild {
223 pub attrs: Vec<Attribute>,
224 pub underscore_token: Token![_],
225 }
226}
227
228#[doc = r" A single field in a struct pattern."]
#[doc = r""]
#[doc =
r" Patterns like the fields of `Pat { x, ref y, ref mut z }` are treated"]
#[doc =
r" the same as `x: x, y: ref y, z: ref mut z` but there is no colon token."]
#[doc(cfg(feature = "full"))]
pub struct FieldPat {
pub attrs: Vec<Attribute>,
pub member: Member,
pub colon_token: Option<crate::token::Colon>,
pub pat: Box<Pat>,
}ast_struct! {
229 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
234 pub struct FieldPat {
235 pub attrs: Vec<Attribute>,
236 pub member: Member,
237 pub colon_token: Option<Token![:]>,
238 pub pat: Box<Pat>,
239 }
240}
241
242#[cfg(feature = "parsing")]
243pub(crate) mod parsing {
244 use crate::attr::Attribute;
245 use crate::buffer::Cursor;
246 use crate::error::{self, Result};
247 use crate::expr::{
248 Expr, ExprConst, ExprLit, ExprMacro, ExprPath, ExprRange, Member, RangeLimits,
249 };
250 use crate::ext::IdentExt as _;
251 use crate::ident::Ident;
252 use crate::lit::Lit;
253 use crate::mac::{self, Macro};
254 use crate::parse::{Parse, ParseStream};
255 use crate::pat::{
256 FieldPat, Pat, PatGuard, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice,
257 PatStruct, PatTuple, PatTupleStruct, PatType, PatWild,
258 };
259 use crate::path::{self, Path, QSelf};
260 use crate::punctuated::Punctuated;
261 use crate::stmt::Block;
262 use crate::token;
263 use crate::verbatim;
264 use alloc::boxed::Box;
265 use alloc::vec::Vec;
266 use proc_macro2::TokenStream;
267
268 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
269 impl Pat {
270 pub fn parse_single(input: ParseStream) -> Result<Self> {
295 let begin = input.cursor();
296 let lookahead = input.lookahead1();
297 if lookahead.peek(Ident)
298 && (input.peek2(crate::token::PathSepToken![::])
299 || input.peek2(crate::token::NotToken![!])
300 || input.peek2(token::Brace)
301 || input.peek2(token::Paren)
302 || input.peek2(crate::token::DotDotToken![..]))
303 || input.peek(crate::token::SelfValueToken![self]) && input.peek2(crate::token::PathSepToken![::])
304 || lookahead.peek(crate::token::PathSepToken![::])
305 || lookahead.peek(crate::token::LtToken![<])
306 || input.peek(crate::token::SelfTypeToken![Self])
307 || input.peek(crate::token::SuperToken![super])
308 || input.peek(crate::token::CrateToken![crate])
309 {
310 pat_path_or_macro_or_struct_or_range(input)
311 } else if lookahead.peek(crate::token::UnderscoreToken![_]) {
312 input.call(pat_wild).map(Pat::Wild)
313 } else if input.peek(crate::token::BoxToken![box]) {
314 pat_box(begin, input)
315 } else if input.peek(crate::token::MinusToken![-]) || lookahead.peek(Lit) || lookahead.peek(crate::token::ConstToken![const])
316 {
317 pat_lit_or_range(input)
318 } else if lookahead.peek(crate::token::RefToken![ref])
319 || lookahead.peek(crate::token::MutToken![mut])
320 || input.peek(crate::token::SelfValueToken![self])
321 || input.peek(Ident)
322 {
323 input.call(pat_ident).map(Pat::Ident)
324 } else if lookahead.peek(crate::token::AndToken![&]) {
325 input.call(pat_reference).map(Pat::Reference)
326 } else if lookahead.peek(token::Paren) {
327 input.call(pat_paren_or_tuple)
328 } else if lookahead.peek(token::Bracket) {
329 input.call(pat_slice).map(Pat::Slice)
330 } else if lookahead.peek(crate::token::DotDotToken![..]) && !input.peek(crate::token::DotDotDotToken![...]) {
331 pat_range_half_open(input)
332 } else if lookahead.peek(crate::token::ConstToken![const]) {
333 input.call(pat_const).map(Pat::Verbatim)
334 } else {
335 Err(lookahead.error())
336 }
337 }
338
339 pub fn parse_multi(input: ParseStream) -> Result<Self> {
341 let allow_guard = false;
342 multi_pat_impl(input, None, allow_guard)
343 }
344
345 pub fn parse_multi_with_leading_vert(input: ParseStream) -> Result<Self> {
388 let leading_vert: Option<crate::token::OrToken![|]> = input.parse()?;
389 let allow_guard = false;
390 multi_pat_impl(input, leading_vert, allow_guard)
391 }
392
393 pub(crate) fn parse_multi_with_leading_vert_and_guard(input: ParseStream) -> Result<Self> {
394 let leading_vert: Option<crate::token::OrToken![|]> = input.parse()?;
395 let allow_guard = true;
396 multi_pat_impl(input, leading_vert, allow_guard)
397 }
398 }
399
400 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
401 impl Parse for PatType {
402 fn parse(input: ParseStream) -> Result<Self> {
403 Ok(PatType {
404 attrs: Vec::new(),
405 pat: Box::new(Pat::parse_single(input)?),
406 colon_token: input.parse()?,
407 ty: input.parse()?,
408 })
409 }
410 }
411
412 fn multi_pat_impl(
413 input: ParseStream,
414 leading_vert: Option<crate::token::OrToken![|]>,
415 allow_guard: bool,
416 ) -> Result<Pat> {
417 let mut pat = Pat::parse_single(input)?;
418 if leading_vert.is_some()
419 || input.peek(crate::token::OrToken![|]) && !input.peek(crate::token::OrOrToken![||]) && !input.peek(crate::token::OrEqToken![|=])
420 {
421 let mut cases = Punctuated::new();
422 cases.push_value(pat);
423 while input.peek(crate::token::OrToken![|]) && !input.peek(crate::token::OrOrToken![||]) && !input.peek(crate::token::OrEqToken![|=]) {
424 let punct = input.parse()?;
425 cases.push_punct(punct);
426 let pat = Pat::parse_single(input)?;
427 cases.push_value(pat);
428 }
429 pat = Pat::Or(PatOr {
430 attrs: Vec::new(),
431 leading_vert,
432 cases,
433 });
434 }
435 if allow_guard && input.peek(crate::token::IfToken![if]) {
436 let if_token: crate::token::IfToken![if] = input.parse()?;
437 let guard: Expr = input.parse()?;
438 pat = Pat::Guard(PatGuard {
439 attrs: Vec::new(),
440 pat: Box::new(pat),
441 if_token,
442 guard: Box::new(guard),
443 });
444 }
445 Ok(pat)
446 }
447
448 fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> {
449 let expr_style = true;
450 let (qself, path) = path::parsing::qpath(input, expr_style)?;
451
452 if qself.is_none()
453 && input.peek(crate::token::NotToken![!])
454 && !input.peek(crate::token::NeToken![!=])
455 && path.is_mod_style()
456 {
457 let bang_token: crate::token::NotToken![!] = input.parse()?;
458 let (delimiter, tokens) = mac::parse_delimiter(input)?;
459 return Ok(Pat::Macro(ExprMacro {
460 attrs: Vec::new(),
461 mac: Macro {
462 path,
463 bang_token,
464 delimiter,
465 tokens,
466 },
467 }));
468 }
469
470 if input.peek(token::Brace) {
471 pat_struct(input, qself, path).map(Pat::Struct)
472 } else if input.peek(token::Paren) {
473 pat_tuple_struct(input, qself, path).map(Pat::TupleStruct)
474 } else if input.peek(crate::token::DotDotToken![..]) {
475 pat_range(input, qself, path)
476 } else {
477 Ok(Pat::Path(ExprPath {
478 attrs: Vec::new(),
479 qself,
480 path,
481 }))
482 }
483 }
484
485 fn pat_wild(input: ParseStream) -> Result<PatWild> {
486 Ok(PatWild {
487 attrs: Vec::new(),
488 underscore_token: input.parse()?,
489 })
490 }
491
492 fn pat_box(begin: Cursor, input: ParseStream) -> Result<Pat> {
493 input.parse::<crate::token::BoxToken![box]>()?;
494 Pat::parse_single(input)?;
495 Ok(Pat::Verbatim(verbatim::between(begin, input.cursor())))
496 }
497
498 fn pat_ident(input: ParseStream) -> Result<PatIdent> {
499 Ok(PatIdent {
500 attrs: Vec::new(),
501 by_ref: input.parse()?,
502 mutability: input.parse()?,
503 ident: {
504 if input.peek(crate::token::SelfValueToken![self]) {
505 input.call(Ident::parse_any)?
506 } else {
507 input.parse()?
508 }
509 },
510 subpat: {
511 if input.peek(crate::token::AtToken![@]) {
512 let at_token: crate::token::AtToken![@] = input.parse()?;
513 let subpat = Pat::parse_single(input)?;
514 Some((at_token, Box::new(subpat)))
515 } else {
516 None
517 }
518 },
519 })
520 }
521
522 fn pat_tuple_struct(
523 input: ParseStream,
524 qself: Option<QSelf>,
525 path: Path,
526 ) -> Result<PatTupleStruct> {
527 let content;
528 let paren_token = match crate::__private::parse_parens(&input) {
crate::__private::Ok(parens) => {
content = parens.content;
_ = content;
parens.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
}parenthesized!(content in input);
529
530 let mut elems = Punctuated::new();
531 while !content.is_empty() {
532 let value = Pat::parse_multi_with_leading_vert(&content)?;
533 elems.push_value(value);
534 if content.is_empty() {
535 break;
536 }
537 let punct = content.parse()?;
538 elems.push_punct(punct);
539 }
540
541 Ok(PatTupleStruct {
542 attrs: Vec::new(),
543 qself,
544 path,
545 paren_token,
546 elems,
547 })
548 }
549
550 fn pat_struct(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<PatStruct> {
551 let content;
552 let brace_token = match crate::__private::parse_braces(&input) {
crate::__private::Ok(braces) => {
content = braces.content;
_ = content;
braces.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
}braced!(content in input);
553
554 let mut fields = Punctuated::new();
555 let mut rest = None;
556 while !content.is_empty() {
557 let attrs = content.call(Attribute::parse_outer)?;
558 if content.peek(crate::token::DotDotToken![..]) {
559 rest = Some(PatRest {
560 attrs,
561 dot2_token: content.parse()?,
562 });
563 break;
564 }
565 let mut value = content.call(field_pat)?;
566 value.attrs = attrs;
567 fields.push_value(value);
568 if content.is_empty() {
569 break;
570 }
571 let punct: crate::token::CommaToken![,] = content.parse()?;
572 fields.push_punct(punct);
573 }
574
575 Ok(PatStruct {
576 attrs: Vec::new(),
577 qself,
578 path,
579 brace_token,
580 fields,
581 rest,
582 })
583 }
584
585 fn field_pat(input: ParseStream) -> Result<FieldPat> {
586 let begin = input.cursor();
587 let boxed: Option<crate::token::BoxToken![box]> = input.parse()?;
588 let by_ref: Option<crate::token::RefToken![ref]> = input.parse()?;
589 let mutability: Option<crate::token::MutToken![mut]> = input.parse()?;
590
591 let member = if boxed.is_some() || by_ref.is_some() || mutability.is_some() {
592 input.parse().map(Member::Named)
593 } else {
594 input.parse()
595 }?;
596
597 if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(crate::token::ColonToken![:])
598 || !member.is_named()
599 {
600 return Ok(FieldPat {
601 attrs: Vec::new(),
602 member,
603 colon_token: Some(input.parse()?),
604 pat: Box::new(Pat::parse_multi_with_leading_vert(input)?),
605 });
606 }
607
608 let ident = match member {
609 Member::Named(ident) => ident,
610 Member::Unnamed(_) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
611 };
612
613 let pat = if boxed.is_some() {
614 Pat::Verbatim(verbatim::between(begin, input.cursor()))
615 } else {
616 Pat::Ident(PatIdent {
617 attrs: Vec::new(),
618 by_ref,
619 mutability,
620 ident: ident.clone(),
621 subpat: None,
622 })
623 };
624
625 Ok(FieldPat {
626 attrs: Vec::new(),
627 member: Member::Named(ident),
628 colon_token: None,
629 pat: Box::new(pat),
630 })
631 }
632
633 fn pat_range(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<Pat> {
634 let limits = RangeLimits::parse_obsolete(input)?;
635 let end = input.call(pat_range_bound)?;
636 if let (RangeLimits::Closed(_), None) = (&limits, &end) {
637 return Err(input.error("expected range upper bound"));
638 }
639 Ok(Pat::Range(ExprRange {
640 attrs: Vec::new(),
641 start: Some(Box::new(Expr::Path(ExprPath {
642 attrs: Vec::new(),
643 qself,
644 path,
645 }))),
646 limits,
647 end: end.map(PatRangeBound::into_expr),
648 }))
649 }
650
651 fn pat_range_half_open(input: ParseStream) -> Result<Pat> {
652 let limits: RangeLimits = input.parse()?;
653 let end = input.call(pat_range_bound)?;
654 if end.is_some() {
655 Ok(Pat::Range(ExprRange {
656 attrs: Vec::new(),
657 start: None,
658 limits,
659 end: end.map(PatRangeBound::into_expr),
660 }))
661 } else {
662 match limits {
663 RangeLimits::HalfOpen(dot2_token) => Ok(Pat::Rest(PatRest {
664 attrs: Vec::new(),
665 dot2_token,
666 })),
667 RangeLimits::Closed(_) => Err(input.error("expected range upper bound")),
668 }
669 }
670 }
671
672 fn pat_paren_or_tuple(input: ParseStream) -> Result<Pat> {
673 let content;
674 let paren_token = match crate::__private::parse_parens(&input) {
crate::__private::Ok(parens) => {
content = parens.content;
_ = content;
parens.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
}parenthesized!(content in input);
675
676 let mut elems = Punctuated::new();
677 while !content.is_empty() {
678 let value = Pat::parse_multi_with_leading_vert(&content)?;
679 if content.is_empty() {
680 if elems.is_empty() && !#[allow(non_exhaustive_omitted_patterns)] match value {
Pat::Rest(_) => true,
_ => false,
}matches!(value, Pat::Rest(_)) {
681 return Ok(Pat::Paren(PatParen {
682 attrs: Vec::new(),
683 paren_token,
684 pat: Box::new(value),
685 }));
686 }
687 elems.push_value(value);
688 break;
689 }
690 elems.push_value(value);
691 let punct = content.parse()?;
692 elems.push_punct(punct);
693 }
694
695 Ok(Pat::Tuple(PatTuple {
696 attrs: Vec::new(),
697 paren_token,
698 elems,
699 }))
700 }
701
702 fn pat_reference(input: ParseStream) -> Result<PatReference> {
703 Ok(PatReference {
704 attrs: Vec::new(),
705 and_token: input.parse()?,
706 mutability: input.parse()?,
707 pat: Box::new(Pat::parse_single(input)?),
708 })
709 }
710
711 fn pat_lit_or_range(input: ParseStream) -> Result<Pat> {
712 let start = input.call(pat_range_bound)?.unwrap();
713 if input.peek(crate::token::DotDotToken![..]) {
714 let limits = RangeLimits::parse_obsolete(input)?;
715 let end = input.call(pat_range_bound)?;
716 if let (RangeLimits::Closed(_), None) = (&limits, &end) {
717 return Err(input.error("expected range upper bound"));
718 }
719 Ok(Pat::Range(ExprRange {
720 attrs: Vec::new(),
721 start: Some(start.into_expr()),
722 limits,
723 end: end.map(PatRangeBound::into_expr),
724 }))
725 } else {
726 Ok(start.into_pat())
727 }
728 }
729
730 enum PatRangeBound {
732 Const(ExprConst),
733 Lit(ExprLit),
734 Path(ExprPath),
735 }
736
737 impl PatRangeBound {
738 fn into_expr(self) -> Box<Expr> {
739 Box::new(match self {
740 PatRangeBound::Const(pat) => Expr::Const(pat),
741 PatRangeBound::Lit(pat) => Expr::Lit(pat),
742 PatRangeBound::Path(pat) => Expr::Path(pat),
743 })
744 }
745
746 fn into_pat(self) -> Pat {
747 match self {
748 PatRangeBound::Const(pat) => Pat::Const(pat),
749 PatRangeBound::Lit(pat) => Pat::Lit(pat),
750 PatRangeBound::Path(pat) => Pat::Path(pat),
751 }
752 }
753 }
754
755 fn pat_range_bound(input: ParseStream) -> Result<Option<PatRangeBound>> {
756 if input.is_empty()
757 || input.peek(crate::token::OrToken![|])
758 || input.peek(crate::token::EqToken![=])
759 || input.peek(crate::token::ColonToken![:]) && !input.peek(crate::token::PathSepToken![::])
760 || input.peek(crate::token::CommaToken![,])
761 || input.peek(crate::token::SemiToken![;])
762 || input.peek(crate::token::IfToken![if])
763 {
764 return Ok(None);
765 }
766
767 let lookahead = input.lookahead1();
768 let expr = if lookahead.peek(Lit) {
769 PatRangeBound::Lit(input.parse()?)
770 } else if lookahead.peek(Ident)
771 || lookahead.peek(crate::token::PathSepToken![::])
772 || lookahead.peek(crate::token::LtToken![<])
773 || lookahead.peek(crate::token::SelfValueToken![self])
774 || lookahead.peek(crate::token::SelfTypeToken![Self])
775 || lookahead.peek(crate::token::SuperToken![super])
776 || lookahead.peek(crate::token::CrateToken![crate])
777 {
778 PatRangeBound::Path(input.parse()?)
779 } else if lookahead.peek(crate::token::ConstToken![const]) {
780 PatRangeBound::Const(input.parse()?)
781 } else {
782 return Err(lookahead.error());
783 };
784
785 Ok(Some(expr))
786 }
787
788 fn pat_slice(input: ParseStream) -> Result<PatSlice> {
789 let content;
790 let bracket_token = match crate::__private::parse_brackets(&input) {
crate::__private::Ok(brackets) => {
content = brackets.content;
_ = content;
brackets.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
}bracketed!(content in input);
791
792 let mut elems = Punctuated::new();
793 while !content.is_empty() {
794 let value = Pat::parse_multi_with_leading_vert(&content)?;
795 match value {
796 Pat::Range(pat) if pat.start.is_none() || pat.end.is_none() => {
797 let (start, end) = match pat.limits {
798 RangeLimits::HalfOpen(dot_dot) => (dot_dot.spans[0], dot_dot.spans[1]),
799 RangeLimits::Closed(dot_dot_eq) => {
800 (dot_dot_eq.spans[0], dot_dot_eq.spans[2])
801 }
802 };
803 let msg = "range pattern is not allowed unparenthesized inside slice pattern";
804 return Err(error::new2(start, end, msg));
805 }
806 _ => {}
807 }
808 elems.push_value(value);
809 if content.is_empty() {
810 break;
811 }
812 let punct = content.parse()?;
813 elems.push_punct(punct);
814 }
815
816 Ok(PatSlice {
817 attrs: Vec::new(),
818 bracket_token,
819 elems,
820 })
821 }
822
823 fn pat_const(input: ParseStream) -> Result<TokenStream> {
824 let begin = input.cursor();
825 input.parse::<crate::token::ConstToken![const]>()?;
826
827 let content;
828 match crate::__private::parse_braces(&input) {
crate::__private::Ok(braces) => {
content = braces.content;
_ = content;
braces.token
}
crate::__private::Err(error) => { return crate::__private::Err(error); }
};braced!(content in input);
829 content.call(Attribute::parse_inner)?;
830 content.call(Block::parse_within)?;
831
832 Ok(verbatim::between(begin, input.cursor()))
833 }
834}
835
836#[cfg(feature = "printing")]
837mod printing {
838 use crate::attr::FilterAttrs;
839 use crate::pat::{
840 FieldPat, Pat, PatGuard, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice,
841 PatStruct, PatTuple, PatTupleStruct, PatType, PatWild,
842 };
843 use crate::path;
844 use crate::path::printing::PathStyle;
845 use proc_macro2::TokenStream;
846 use quote::{ToTokens, TokenStreamExt as _};
847
848 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
849 impl ToTokens for PatIdent {
850 fn to_tokens(&self, tokens: &mut TokenStream) {
851 tokens.append_all(self.attrs.outer());
852 self.by_ref.to_tokens(tokens);
853 self.mutability.to_tokens(tokens);
854 self.ident.to_tokens(tokens);
855 if let Some((at_token, subpat)) = &self.subpat {
856 at_token.to_tokens(tokens);
857 subpat.to_tokens(tokens);
858 }
859 }
860 }
861
862 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
863 impl ToTokens for PatGuard {
864 fn to_tokens(&self, tokens: &mut TokenStream) {
865 tokens.append_all(self.attrs.outer());
866 self.pat.to_tokens(tokens);
867 self.if_token.to_tokens(tokens);
868 self.guard.to_tokens(tokens);
869 }
870 }
871
872 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
873 impl ToTokens for PatOr {
874 fn to_tokens(&self, tokens: &mut TokenStream) {
875 tokens.append_all(self.attrs.outer());
876 self.leading_vert.to_tokens(tokens);
877 self.cases.to_tokens(tokens);
878 }
879 }
880
881 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
882 impl ToTokens for PatParen {
883 fn to_tokens(&self, tokens: &mut TokenStream) {
884 tokens.append_all(self.attrs.outer());
885 self.paren_token.surround(tokens, |tokens| {
886 self.pat.to_tokens(tokens);
887 });
888 }
889 }
890
891 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
892 impl ToTokens for PatReference {
893 fn to_tokens(&self, tokens: &mut TokenStream) {
894 tokens.append_all(self.attrs.outer());
895 self.and_token.to_tokens(tokens);
896 self.mutability.to_tokens(tokens);
897 self.pat.to_tokens(tokens);
898 }
899 }
900
901 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
902 impl ToTokens for PatRest {
903 fn to_tokens(&self, tokens: &mut TokenStream) {
904 tokens.append_all(self.attrs.outer());
905 self.dot2_token.to_tokens(tokens);
906 }
907 }
908
909 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
910 impl ToTokens for PatSlice {
911 fn to_tokens(&self, tokens: &mut TokenStream) {
912 tokens.append_all(self.attrs.outer());
913 self.bracket_token.surround(tokens, |tokens| {
914 self.elems.to_tokens(tokens);
915 });
916 }
917 }
918
919 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
920 impl ToTokens for PatStruct {
921 fn to_tokens(&self, tokens: &mut TokenStream) {
922 tokens.append_all(self.attrs.outer());
923 path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
924 self.brace_token.surround(tokens, |tokens| {
925 self.fields.to_tokens(tokens);
926 if !self.fields.empty_or_trailing() && self.rest.is_some() {
928 <crate::token::CommaToken![,]>::default().to_tokens(tokens);
929 }
930 self.rest.to_tokens(tokens);
931 });
932 }
933 }
934
935 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
936 impl ToTokens for PatTuple {
937 fn to_tokens(&self, tokens: &mut TokenStream) {
938 tokens.append_all(self.attrs.outer());
939 self.paren_token.surround(tokens, |tokens| {
940 self.elems.to_tokens(tokens);
941 if self.elems.len() == 1
945 && !self.elems.trailing_punct()
946 && !#[allow(non_exhaustive_omitted_patterns)] match self.elems[0] {
Pat::Rest { .. } => true,
_ => false,
}matches!(self.elems[0], Pat::Rest { .. })
947 {
948 <crate::token::CommaToken![,]>::default().to_tokens(tokens);
949 }
950 });
951 }
952 }
953
954 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
955 impl ToTokens for PatTupleStruct {
956 fn to_tokens(&self, tokens: &mut TokenStream) {
957 tokens.append_all(self.attrs.outer());
958 path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
959 self.paren_token.surround(tokens, |tokens| {
960 self.elems.to_tokens(tokens);
961 });
962 }
963 }
964
965 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
966 impl ToTokens for PatType {
967 fn to_tokens(&self, tokens: &mut TokenStream) {
968 tokens.append_all(self.attrs.outer());
969 self.pat.to_tokens(tokens);
970 self.colon_token.to_tokens(tokens);
971 self.ty.to_tokens(tokens);
972 }
973 }
974
975 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
976 impl ToTokens for PatWild {
977 fn to_tokens(&self, tokens: &mut TokenStream) {
978 tokens.append_all(self.attrs.outer());
979 self.underscore_token.to_tokens(tokens);
980 }
981 }
982
983 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
984 impl ToTokens for FieldPat {
985 fn to_tokens(&self, tokens: &mut TokenStream) {
986 tokens.append_all(self.attrs.outer());
987 if let Some(colon_token) = &self.colon_token {
988 self.member.to_tokens(tokens);
989 colon_token.to_tokens(tokens);
990 }
991 self.pat.to_tokens(tokens);
992 }
993 }
994}