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