1use crate::attr::Attribute;
2use crate::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"]
#[non_exhaustive]
pub enum Pat {
#[doc = r" A const block: `const { ... }`."]
Const(PatConst),
#[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."]
Verbatim(TokenStream),
#[doc = r" A pattern that matches any value: `_`."]
Wild(PatWild),
}
impl From<PatConst> for Pat {
fn from(e: PatConst) -> Pat { Pat::Const(e) }
}
impl From<PatIdent> for Pat {
fn from(e: PatIdent) -> Pat { Pat::Ident(e) }
}
impl From<PatLit> for Pat {
fn from(e: PatLit) -> Pat { Pat::Lit(e) }
}
impl From<PatMacro> for Pat {
fn from(e: PatMacro) -> Pat { Pat::Macro(e) }
}
impl From<PatOr> for Pat {
fn from(e: PatOr) -> Pat { Pat::Or(e) }
}
impl From<PatParen> for Pat {
fn from(e: PatParen) -> Pat { Pat::Paren(e) }
}
impl From<PatPath> for Pat {
fn from(e: PatPath) -> Pat { Pat::Path(e) }
}
impl From<PatRange> for Pat {
fn from(e: PatRange) -> Pat { Pat::Range(e) }
}
impl From<PatReference> for Pat {
fn from(e: PatReference) -> Pat { Pat::Reference(e) }
}
impl From<PatRest> for Pat {
fn from(e: PatRest) -> Pat { Pat::Rest(e) }
}
impl From<PatSlice> for Pat {
fn from(e: PatSlice) -> Pat { Pat::Slice(e) }
}
impl From<PatStruct> for Pat {
fn from(e: PatStruct) -> Pat { Pat::Struct(e) }
}
impl From<PatTuple> for Pat {
fn from(e: PatTuple) -> Pat { Pat::Tuple(e) }
}
impl From<PatTupleStruct> for Pat {
fn from(e: PatTupleStruct) -> Pat { Pat::TupleStruct(e) }
}
impl From<PatType> for Pat {
fn from(e: PatType) -> Pat { Pat::Type(e) }
}
impl From<PatWild> for Pat {
fn from(e: PatWild) -> Pat { Pat::Wild(e) }
}
impl ::quote::ToTokens for Pat {
fn to_tokens(&self, tokens: &mut ::proc_macro2::TokenStream) {
match self {
Pat::Const(_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 Ident(PatIdent),
34
35 Lit(PatLit),
37
38 Macro(PatMacro),
40
41 Or(PatOr),
43
44 Paren(PatParen),
46
47 Path(PatPath),
55
56 Range(PatRange),
58
59 Reference(PatReference),
61
62 Rest(PatRest),
64
65 Slice(PatSlice),
67
68 Struct(PatStruct),
70
71 Tuple(PatTuple),
73
74 TupleStruct(PatTupleStruct),
76
77 Type(PatType),
79
80 Verbatim(TokenStream),
82
83 Wild(PatWild),
85
86 }
104}
105
106#[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."]
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! {
107 #[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#[doc = r" A pattern that matches any one of a set of cases."]
pub struct PatOr {
pub attrs: Vec<Attribute>,
pub leading_vert: Option<crate::token::Or>,
pub cases: Punctuated<Pat, crate::token::Or>,
}ast_struct! {
122 #[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#[doc = r" A parenthesized pattern: `(A | B)`."]
pub struct PatParen {
pub attrs: Vec<Attribute>,
pub paren_token: token::Paren,
pub pat: Box<Pat>,
}ast_struct! {
132 #[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#[doc = r" A reference pattern: `&mut var`."]
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! {
142 #[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#[doc = r" The dots in a tuple or slice pattern: `[0, 1, ..]`."]
pub struct PatRest {
pub attrs: Vec<Attribute>,
pub dot2_token: crate::token::DotDot,
}ast_struct! {
153 #[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#[doc = r" A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`."]
pub struct PatSlice {
pub attrs: Vec<Attribute>,
pub bracket_token: token::Bracket,
pub elems: Punctuated<Pat, crate::token::Comma>,
}ast_struct! {
162 #[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#[doc = r" A struct or struct variant pattern: `Variant { x, y, .. }`."]
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! {
172 #[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#[doc = r" A tuple pattern: `(a, b)`."]
pub struct PatTuple {
pub attrs: Vec<Attribute>,
pub paren_token: token::Paren,
pub elems: Punctuated<Pat, crate::token::Comma>,
}ast_struct! {
185 #[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#[doc = r" A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`."]
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! {
195 #[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#[doc = r" A type ascription pattern: `foo: f64`."]
pub struct PatType {
pub attrs: Vec<Attribute>,
pub pat: Box<Pat>,
pub colon_token: crate::token::Colon,
pub ty: Box<Type>,
}ast_struct! {
207 #[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#[doc = r" A pattern that matches any value: `_`."]
pub struct PatWild {
pub attrs: Vec<Attribute>,
pub underscore_token: crate::token::Underscore,
}ast_struct! {
218 #[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#[doc = r" A single field in a struct pattern."]
#[doc = r""]
#[doc =
r" Patterns like the fields of Foo `{ 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."]
pub struct FieldPat {
pub attrs: Vec<Attribute>,
pub member: Member,
pub colon_token: Option<crate::token::Colon>,
pub pat: Box<Pat>,
}ast_struct! {
227 #[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")]
241pub(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 alloc::boxed::Box;
262 use alloc::vec::Vec;
263 use proc_macro2::TokenStream;
264
265 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
266 impl Pat {
267 pub fn parse_single(input: ParseStream) -> Result<Self> {
292 let begin = input.fork();
293 let lookahead = input.lookahead1();
294 if lookahead.peek(Ident)
295 && (input.peek2(crate::token::PathSepToken![::])
296 || input.peek2(crate::token::NotToken![!])
297 || input.peek2(token::Brace)
298 || input.peek2(token::Paren)
299 || input.peek2(crate::token::DotDotToken![..]))
300 || input.peek(crate::token::SelfValueToken![self]) && input.peek2(crate::token::PathSepToken![::])
301 || lookahead.peek(crate::token::PathSepToken![::])
302 || lookahead.peek(crate::token::LtToken![<])
303 || input.peek(crate::token::SelfTypeToken![Self])
304 || input.peek(crate::token::SuperToken![super])
305 || input.peek(crate::token::CrateToken![crate])
306 {
307 pat_path_or_macro_or_struct_or_range(input)
308 } else if lookahead.peek(crate::token::UnderscoreToken![_]) {
309 input.call(pat_wild).map(Pat::Wild)
310 } else if input.peek(crate::token::BoxToken![box]) {
311 pat_box(begin, input)
312 } else if input.peek(crate::token::MinusToken![-]) || lookahead.peek(Lit) || lookahead.peek(crate::token::ConstToken![const])
313 {
314 pat_lit_or_range(input)
315 } else if lookahead.peek(crate::token::RefToken![ref])
316 || lookahead.peek(crate::token::MutToken![mut])
317 || input.peek(crate::token::SelfValueToken![self])
318 || input.peek(Ident)
319 {
320 input.call(pat_ident).map(Pat::Ident)
321 } else if lookahead.peek(crate::token::AndToken![&]) {
322 input.call(pat_reference).map(Pat::Reference)
323 } else if lookahead.peek(token::Paren) {
324 input.call(pat_paren_or_tuple)
325 } else if lookahead.peek(token::Bracket) {
326 input.call(pat_slice).map(Pat::Slice)
327 } else if lookahead.peek(crate::token::DotDotToken![..]) && !input.peek(crate::token::DotDotDotToken![...]) {
328 pat_range_half_open(input)
329 } else if lookahead.peek(crate::token::ConstToken![const]) {
330 input.call(pat_const).map(Pat::Verbatim)
331 } else {
332 Err(lookahead.error())
333 }
334 }
335
336 pub fn parse_multi(input: ParseStream) -> Result<Self> {
338 multi_pat_impl(input, None)
339 }
340
341 pub fn parse_multi_with_leading_vert(input: ParseStream) -> Result<Self> {
384 let leading_vert: Option<crate::token::OrToken![|]> = input.parse()?;
385 multi_pat_impl(input, leading_vert)
386 }
387 }
388
389 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
390 impl Parse for PatType {
391 fn parse(input: ParseStream) -> Result<Self> {
392 Ok(PatType {
393 attrs: Vec::new(),
394 pat: Box::new(Pat::parse_single(input)?),
395 colon_token: input.parse()?,
396 ty: input.parse()?,
397 })
398 }
399 }
400
401 fn multi_pat_impl(input: ParseStream, leading_vert: Option<crate::token::OrToken![|]>) -> Result<Pat> {
402 let mut pat = Pat::parse_single(input)?;
403 if leading_vert.is_some()
404 || input.peek(crate::token::OrToken![|]) && !input.peek(crate::token::OrOrToken![||]) && !input.peek(crate::token::OrEqToken![|=])
405 {
406 let mut cases = Punctuated::new();
407 cases.push_value(pat);
408 while input.peek(crate::token::OrToken![|]) && !input.peek(crate::token::OrOrToken![||]) && !input.peek(crate::token::OrEqToken![|=]) {
409 let punct = input.parse()?;
410 cases.push_punct(punct);
411 let pat = Pat::parse_single(input)?;
412 cases.push_value(pat);
413 }
414 pat = Pat::Or(PatOr {
415 attrs: Vec::new(),
416 leading_vert,
417 cases,
418 });
419 }
420 Ok(pat)
421 }
422
423 fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> {
424 let expr_style = true;
425 let (qself, path) = path::parsing::qpath(input, expr_style)?;
426
427 if qself.is_none()
428 && input.peek(crate::token::NotToken![!])
429 && !input.peek(crate::token::NeToken![!=])
430 && path.is_mod_style()
431 {
432 let bang_token: crate::token::NotToken![!] = input.parse()?;
433 let (delimiter, tokens) = mac::parse_delimiter(input)?;
434 return Ok(Pat::Macro(ExprMacro {
435 attrs: Vec::new(),
436 mac: Macro {
437 path,
438 bang_token,
439 delimiter,
440 tokens,
441 },
442 }));
443 }
444
445 if input.peek(token::Brace) {
446 pat_struct(input, qself, path).map(Pat::Struct)
447 } else if input.peek(token::Paren) {
448 pat_tuple_struct(input, qself, path).map(Pat::TupleStruct)
449 } else if input.peek(crate::token::DotDotToken![..]) {
450 pat_range(input, qself, path)
451 } else {
452 Ok(Pat::Path(ExprPath {
453 attrs: Vec::new(),
454 qself,
455 path,
456 }))
457 }
458 }
459
460 fn pat_wild(input: ParseStream) -> Result<PatWild> {
461 Ok(PatWild {
462 attrs: Vec::new(),
463 underscore_token: input.parse()?,
464 })
465 }
466
467 fn pat_box(begin: ParseBuffer, input: ParseStream) -> Result<Pat> {
468 input.parse::<crate::token::BoxToken![box]>()?;
469 Pat::parse_single(input)?;
470 Ok(Pat::Verbatim(verbatim::between(&begin, input)))
471 }
472
473 fn pat_ident(input: ParseStream) -> Result<PatIdent> {
474 Ok(PatIdent {
475 attrs: Vec::new(),
476 by_ref: input.parse()?,
477 mutability: input.parse()?,
478 ident: {
479 if input.peek(crate::token::SelfValueToken![self]) {
480 input.call(Ident::parse_any)?
481 } else {
482 input.parse()?
483 }
484 },
485 subpat: {
486 if input.peek(crate::token::AtToken![@]) {
487 let at_token: crate::token::AtToken![@] = input.parse()?;
488 let subpat = Pat::parse_single(input)?;
489 Some((at_token, Box::new(subpat)))
490 } else {
491 None
492 }
493 },
494 })
495 }
496
497 fn pat_tuple_struct(
498 input: ParseStream,
499 qself: Option<QSelf>,
500 path: Path,
501 ) -> Result<PatTupleStruct> {
502 let content;
503 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);
504
505 let mut elems = Punctuated::new();
506 while !content.is_empty() {
507 let value = Pat::parse_multi_with_leading_vert(&content)?;
508 elems.push_value(value);
509 if content.is_empty() {
510 break;
511 }
512 let punct = content.parse()?;
513 elems.push_punct(punct);
514 }
515
516 Ok(PatTupleStruct {
517 attrs: Vec::new(),
518 qself,
519 path,
520 paren_token,
521 elems,
522 })
523 }
524
525 fn pat_struct(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<PatStruct> {
526 let content;
527 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);
528
529 let mut fields = Punctuated::new();
530 let mut rest = None;
531 while !content.is_empty() {
532 let attrs = content.call(Attribute::parse_outer)?;
533 if content.peek(crate::token::DotDotToken![..]) {
534 rest = Some(PatRest {
535 attrs,
536 dot2_token: content.parse()?,
537 });
538 break;
539 }
540 let mut value = content.call(field_pat)?;
541 value.attrs = attrs;
542 fields.push_value(value);
543 if content.is_empty() {
544 break;
545 }
546 let punct: crate::token::CommaToken![,] = content.parse()?;
547 fields.push_punct(punct);
548 }
549
550 Ok(PatStruct {
551 attrs: Vec::new(),
552 qself,
553 path,
554 brace_token,
555 fields,
556 rest,
557 })
558 }
559
560 fn field_pat(input: ParseStream) -> Result<FieldPat> {
561 let begin = input.fork();
562 let boxed: Option<crate::token::BoxToken![box]> = input.parse()?;
563 let by_ref: Option<crate::token::RefToken![ref]> = input.parse()?;
564 let mutability: Option<crate::token::MutToken![mut]> = input.parse()?;
565
566 let member = if boxed.is_some() || by_ref.is_some() || mutability.is_some() {
567 input.parse().map(Member::Named)
568 } else {
569 input.parse()
570 }?;
571
572 if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(crate::token::ColonToken![:])
573 || !member.is_named()
574 {
575 return Ok(FieldPat {
576 attrs: Vec::new(),
577 member,
578 colon_token: Some(input.parse()?),
579 pat: Box::new(Pat::parse_multi_with_leading_vert(input)?),
580 });
581 }
582
583 let ident = match member {
584 Member::Named(ident) => ident,
585 Member::Unnamed(_) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
586 };
587
588 let pat = if boxed.is_some() {
589 Pat::Verbatim(verbatim::between(&begin, input))
590 } else {
591 Pat::Ident(PatIdent {
592 attrs: Vec::new(),
593 by_ref,
594 mutability,
595 ident: ident.clone(),
596 subpat: None,
597 })
598 };
599
600 Ok(FieldPat {
601 attrs: Vec::new(),
602 member: Member::Named(ident),
603 colon_token: None,
604 pat: Box::new(pat),
605 })
606 }
607
608 fn pat_range(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<Pat> {
609 let limits = RangeLimits::parse_obsolete(input)?;
610 let end = input.call(pat_range_bound)?;
611 if let (RangeLimits::Closed(_), None) = (&limits, &end) {
612 return Err(input.error("expected range upper bound"));
613 }
614 Ok(Pat::Range(ExprRange {
615 attrs: Vec::new(),
616 start: Some(Box::new(Expr::Path(ExprPath {
617 attrs: Vec::new(),
618 qself,
619 path,
620 }))),
621 limits,
622 end: end.map(PatRangeBound::into_expr),
623 }))
624 }
625
626 fn pat_range_half_open(input: ParseStream) -> Result<Pat> {
627 let limits: RangeLimits = input.parse()?;
628 let end = input.call(pat_range_bound)?;
629 if end.is_some() {
630 Ok(Pat::Range(ExprRange {
631 attrs: Vec::new(),
632 start: None,
633 limits,
634 end: end.map(PatRangeBound::into_expr),
635 }))
636 } else {
637 match limits {
638 RangeLimits::HalfOpen(dot2_token) => Ok(Pat::Rest(PatRest {
639 attrs: Vec::new(),
640 dot2_token,
641 })),
642 RangeLimits::Closed(_) => Err(input.error("expected range upper bound")),
643 }
644 }
645 }
646
647 fn pat_paren_or_tuple(input: ParseStream) -> Result<Pat> {
648 let content;
649 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);
650
651 let mut elems = Punctuated::new();
652 while !content.is_empty() {
653 let value = Pat::parse_multi_with_leading_vert(&content)?;
654 if content.is_empty() {
655 if elems.is_empty() && !#[allow(non_exhaustive_omitted_patterns)] match value {
Pat::Rest(_) => true,
_ => false,
}matches!(value, Pat::Rest(_)) {
656 return Ok(Pat::Paren(PatParen {
657 attrs: Vec::new(),
658 paren_token,
659 pat: Box::new(value),
660 }));
661 }
662 elems.push_value(value);
663 break;
664 }
665 elems.push_value(value);
666 let punct = content.parse()?;
667 elems.push_punct(punct);
668 }
669
670 Ok(Pat::Tuple(PatTuple {
671 attrs: Vec::new(),
672 paren_token,
673 elems,
674 }))
675 }
676
677 fn pat_reference(input: ParseStream) -> Result<PatReference> {
678 Ok(PatReference {
679 attrs: Vec::new(),
680 and_token: input.parse()?,
681 mutability: input.parse()?,
682 pat: Box::new(Pat::parse_single(input)?),
683 })
684 }
685
686 fn pat_lit_or_range(input: ParseStream) -> Result<Pat> {
687 let start = input.call(pat_range_bound)?.unwrap();
688 if input.peek(crate::token::DotDotToken![..]) {
689 let limits = RangeLimits::parse_obsolete(input)?;
690 let end = input.call(pat_range_bound)?;
691 if let (RangeLimits::Closed(_), None) = (&limits, &end) {
692 return Err(input.error("expected range upper bound"));
693 }
694 Ok(Pat::Range(ExprRange {
695 attrs: Vec::new(),
696 start: Some(start.into_expr()),
697 limits,
698 end: end.map(PatRangeBound::into_expr),
699 }))
700 } else {
701 Ok(start.into_pat())
702 }
703 }
704
705 enum PatRangeBound {
707 Const(ExprConst),
708 Lit(ExprLit),
709 Path(ExprPath),
710 }
711
712 impl PatRangeBound {
713 fn into_expr(self) -> Box<Expr> {
714 Box::new(match self {
715 PatRangeBound::Const(pat) => Expr::Const(pat),
716 PatRangeBound::Lit(pat) => Expr::Lit(pat),
717 PatRangeBound::Path(pat) => Expr::Path(pat),
718 })
719 }
720
721 fn into_pat(self) -> Pat {
722 match self {
723 PatRangeBound::Const(pat) => Pat::Const(pat),
724 PatRangeBound::Lit(pat) => Pat::Lit(pat),
725 PatRangeBound::Path(pat) => Pat::Path(pat),
726 }
727 }
728 }
729
730 fn pat_range_bound(input: ParseStream) -> Result<Option<PatRangeBound>> {
731 if input.is_empty()
732 || input.peek(crate::token::OrToken![|])
733 || input.peek(crate::token::EqToken![=])
734 || input.peek(crate::token::ColonToken![:]) && !input.peek(crate::token::PathSepToken![::])
735 || input.peek(crate::token::CommaToken![,])
736 || input.peek(crate::token::SemiToken![;])
737 || input.peek(crate::token::IfToken![if])
738 {
739 return Ok(None);
740 }
741
742 let lookahead = input.lookahead1();
743 let expr = if lookahead.peek(Lit) {
744 PatRangeBound::Lit(input.parse()?)
745 } else if lookahead.peek(Ident)
746 || lookahead.peek(crate::token::PathSepToken![::])
747 || lookahead.peek(crate::token::LtToken![<])
748 || lookahead.peek(crate::token::SelfValueToken![self])
749 || lookahead.peek(crate::token::SelfTypeToken![Self])
750 || lookahead.peek(crate::token::SuperToken![super])
751 || lookahead.peek(crate::token::CrateToken![crate])
752 {
753 PatRangeBound::Path(input.parse()?)
754 } else if lookahead.peek(crate::token::ConstToken![const]) {
755 PatRangeBound::Const(input.parse()?)
756 } else {
757 return Err(lookahead.error());
758 };
759
760 Ok(Some(expr))
761 }
762
763 fn pat_slice(input: ParseStream) -> Result<PatSlice> {
764 let content;
765 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);
766
767 let mut elems = Punctuated::new();
768 while !content.is_empty() {
769 let value = Pat::parse_multi_with_leading_vert(&content)?;
770 match value {
771 Pat::Range(pat) if pat.start.is_none() || pat.end.is_none() => {
772 let (start, end) = match pat.limits {
773 RangeLimits::HalfOpen(dot_dot) => (dot_dot.spans[0], dot_dot.spans[1]),
774 RangeLimits::Closed(dot_dot_eq) => {
775 (dot_dot_eq.spans[0], dot_dot_eq.spans[2])
776 }
777 };
778 let msg = "range pattern is not allowed unparenthesized inside slice pattern";
779 return Err(error::new2(start, end, msg));
780 }
781 _ => {}
782 }
783 elems.push_value(value);
784 if content.is_empty() {
785 break;
786 }
787 let punct = content.parse()?;
788 elems.push_punct(punct);
789 }
790
791 Ok(PatSlice {
792 attrs: Vec::new(),
793 bracket_token,
794 elems,
795 })
796 }
797
798 fn pat_const(input: ParseStream) -> Result<TokenStream> {
799 let begin = input.fork();
800 input.parse::<crate::token::ConstToken![const]>()?;
801
802 let content;
803 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);
804 content.call(Attribute::parse_inner)?;
805 content.call(Block::parse_within)?;
806
807 Ok(verbatim::between(&begin, input))
808 }
809}
810
811#[cfg(feature = "printing")]
812mod printing {
813 use crate::attr::FilterAttrs;
814 use crate::pat::{
815 FieldPat, Pat, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice, PatStruct,
816 PatTuple, PatTupleStruct, PatType, PatWild,
817 };
818 use crate::path;
819 use crate::path::printing::PathStyle;
820 use proc_macro2::TokenStream;
821 use quote::{ToTokens, TokenStreamExt as _};
822
823 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
824 impl ToTokens for PatIdent {
825 fn to_tokens(&self, tokens: &mut TokenStream) {
826 tokens.append_all(self.attrs.outer());
827 self.by_ref.to_tokens(tokens);
828 self.mutability.to_tokens(tokens);
829 self.ident.to_tokens(tokens);
830 if let Some((at_token, subpat)) = &self.subpat {
831 at_token.to_tokens(tokens);
832 subpat.to_tokens(tokens);
833 }
834 }
835 }
836
837 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
838 impl ToTokens for PatOr {
839 fn to_tokens(&self, tokens: &mut TokenStream) {
840 tokens.append_all(self.attrs.outer());
841 self.leading_vert.to_tokens(tokens);
842 self.cases.to_tokens(tokens);
843 }
844 }
845
846 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
847 impl ToTokens for PatParen {
848 fn to_tokens(&self, tokens: &mut TokenStream) {
849 tokens.append_all(self.attrs.outer());
850 self.paren_token.surround(tokens, |tokens| {
851 self.pat.to_tokens(tokens);
852 });
853 }
854 }
855
856 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
857 impl ToTokens for PatReference {
858 fn to_tokens(&self, tokens: &mut TokenStream) {
859 tokens.append_all(self.attrs.outer());
860 self.and_token.to_tokens(tokens);
861 self.mutability.to_tokens(tokens);
862 self.pat.to_tokens(tokens);
863 }
864 }
865
866 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
867 impl ToTokens for PatRest {
868 fn to_tokens(&self, tokens: &mut TokenStream) {
869 tokens.append_all(self.attrs.outer());
870 self.dot2_token.to_tokens(tokens);
871 }
872 }
873
874 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
875 impl ToTokens for PatSlice {
876 fn to_tokens(&self, tokens: &mut TokenStream) {
877 tokens.append_all(self.attrs.outer());
878 self.bracket_token.surround(tokens, |tokens| {
879 self.elems.to_tokens(tokens);
880 });
881 }
882 }
883
884 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
885 impl ToTokens for PatStruct {
886 fn to_tokens(&self, tokens: &mut TokenStream) {
887 tokens.append_all(self.attrs.outer());
888 path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
889 self.brace_token.surround(tokens, |tokens| {
890 self.fields.to_tokens(tokens);
891 if !self.fields.empty_or_trailing() && self.rest.is_some() {
893 <crate::token::CommaToken![,]>::default().to_tokens(tokens);
894 }
895 self.rest.to_tokens(tokens);
896 });
897 }
898 }
899
900 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
901 impl ToTokens for PatTuple {
902 fn to_tokens(&self, tokens: &mut TokenStream) {
903 tokens.append_all(self.attrs.outer());
904 self.paren_token.surround(tokens, |tokens| {
905 self.elems.to_tokens(tokens);
906 if self.elems.len() == 1
910 && !self.elems.trailing_punct()
911 && !#[allow(non_exhaustive_omitted_patterns)] match self.elems[0] {
Pat::Rest { .. } => true,
_ => false,
}matches!(self.elems[0], Pat::Rest { .. })
912 {
913 <crate::token::CommaToken![,]>::default().to_tokens(tokens);
914 }
915 });
916 }
917 }
918
919 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
920 impl ToTokens for PatTupleStruct {
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.paren_token.surround(tokens, |tokens| {
925 self.elems.to_tokens(tokens);
926 });
927 }
928 }
929
930 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
931 impl ToTokens for PatType {
932 fn to_tokens(&self, tokens: &mut TokenStream) {
933 tokens.append_all(self.attrs.outer());
934 self.pat.to_tokens(tokens);
935 self.colon_token.to_tokens(tokens);
936 self.ty.to_tokens(tokens);
937 }
938 }
939
940 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
941 impl ToTokens for PatWild {
942 fn to_tokens(&self, tokens: &mut TokenStream) {
943 tokens.append_all(self.attrs.outer());
944 self.underscore_token.to_tokens(tokens);
945 }
946 }
947
948 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
949 impl ToTokens for FieldPat {
950 fn to_tokens(&self, tokens: &mut TokenStream) {
951 tokens.append_all(self.attrs.outer());
952 if let Some(colon_token) = &self.colon_token {
953 self.member.to_tokens(tokens);
954 colon_token.to_tokens(tokens);
955 }
956 self.pat.to_tokens(tokens);
957 }
958 }
959}