1 use super::*; 2 use crate::punctuated::Punctuated; 3 use proc_macro2::TokenStream; 4 5 ast_enum_of_structs! { 6 /// A pattern in a local binding, function signature, match expression, or 7 /// various other places. 8 /// 9 /// *This type is available only if Syn is built with the `"full"` feature.* 10 /// 11 /// # Syntax tree enum 12 /// 13 /// This type is a [syntax tree enum]. 14 /// 15 /// [syntax tree enum]: Expr#syntax-tree-enums 16 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 17 pub enum Pat { 18 /// A box pattern: `box v`. 19 Box(PatBox), 20 21 /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`. 22 Ident(PatIdent), 23 24 /// A literal pattern: `0`. 25 /// 26 /// This holds an `Expr` rather than a `Lit` because negative numbers 27 /// are represented as an `Expr::Unary`. 28 Lit(PatLit), 29 30 /// A macro in pattern position. 31 Macro(PatMacro), 32 33 /// A pattern that matches any one of a set of cases. 34 Or(PatOr), 35 36 /// A path pattern like `Color::Red`, optionally qualified with a 37 /// self-type. 38 /// 39 /// Unqualified path patterns can legally refer to variants, structs, 40 /// constants or associated constants. Qualified path patterns like 41 /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to 42 /// associated constants. 43 Path(PatPath), 44 45 /// A range pattern: `1..=2`. 46 Range(PatRange), 47 48 /// A reference pattern: `&mut var`. 49 Reference(PatReference), 50 51 /// The dots in a tuple or slice pattern: `[0, 1, ..]` 52 Rest(PatRest), 53 54 /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`. 55 Slice(PatSlice), 56 57 /// A struct or struct variant pattern: `Variant { x, y, .. }`. 58 Struct(PatStruct), 59 60 /// A tuple pattern: `(a, b)`. 61 Tuple(PatTuple), 62 63 /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`. 64 TupleStruct(PatTupleStruct), 65 66 /// A type ascription pattern: `foo: f64`. 67 Type(PatType), 68 69 /// Tokens in pattern position not interpreted by Syn. 70 Verbatim(TokenStream), 71 72 /// A pattern that matches any value: `_`. 73 Wild(PatWild), 74 75 // The following is the only supported idiom for exhaustive matching of 76 // this enum. 77 // 78 // match expr { 79 // Pat::Box(e) => {...} 80 // Pat::Ident(e) => {...} 81 // ... 82 // Pat::Wild(e) => {...} 83 // 84 // #[cfg(test)] 85 // Pat::__TestExhaustive(_) => unimplemented!(), 86 // #[cfg(not(test))] 87 // _ => { /* some sane fallback */ } 88 // } 89 // 90 // This way we fail your tests but don't break your library when adding 91 // a variant. You will be notified by a test failure when a variant is 92 // added, so that you can add code to handle it, but your library will 93 // continue to compile and work for downstream users in the interim. 94 // 95 // Once `deny(reachable)` is available in rustc, Pat will be 96 // reimplemented as a non_exhaustive enum. 97 // https://github.com/rust-lang/rust/issues/44109#issuecomment-521781237 98 #[doc(hidden)] 99 __TestExhaustive(crate::private), 100 } 101 } 102 103 ast_struct! { 104 /// A box pattern: `box v`. 105 /// 106 /// *This type is available only if Syn is built with the `"full"` feature.* 107 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 108 pub struct PatBox { 109 pub attrs: Vec<Attribute>, 110 pub box_token: Token![box], 111 pub pat: Box<Pat>, 112 } 113 } 114 115 ast_struct! { 116 /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`. 117 /// 118 /// It may also be a unit struct or struct variant (e.g. `None`), or a 119 /// constant; these cannot be distinguished syntactically. 120 /// 121 /// *This type is available only if Syn is built with the `"full"` feature.* 122 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 123 pub struct PatIdent { 124 pub attrs: Vec<Attribute>, 125 pub by_ref: Option<Token![ref]>, 126 pub mutability: Option<Token![mut]>, 127 pub ident: Ident, 128 pub subpat: Option<(Token![@], Box<Pat>)>, 129 } 130 } 131 132 ast_struct! { 133 /// A literal pattern: `0`. 134 /// 135 /// This holds an `Expr` rather than a `Lit` because negative numbers 136 /// are represented as an `Expr::Unary`. 137 /// 138 /// *This type is available only if Syn is built with the `"full"` feature.* 139 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 140 pub struct PatLit { 141 pub attrs: Vec<Attribute>, 142 pub expr: Box<Expr>, 143 } 144 } 145 146 ast_struct! { 147 /// A macro in pattern position. 148 /// 149 /// *This type is available only if Syn is built with the `"full"` feature.* 150 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 151 pub struct PatMacro { 152 pub attrs: Vec<Attribute>, 153 pub mac: Macro, 154 } 155 } 156 157 ast_struct! { 158 /// A pattern that matches any one of a set of cases. 159 /// 160 /// *This type is available only if Syn is built with the `"full"` feature.* 161 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 162 pub struct PatOr { 163 pub attrs: Vec<Attribute>, 164 pub leading_vert: Option<Token![|]>, 165 pub cases: Punctuated<Pat, Token![|]>, 166 } 167 } 168 169 ast_struct! { 170 /// A path pattern like `Color::Red`, optionally qualified with a 171 /// self-type. 172 /// 173 /// Unqualified path patterns can legally refer to variants, structs, 174 /// constants or associated constants. Qualified path patterns like 175 /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to 176 /// associated constants. 177 /// 178 /// *This type is available only if Syn is built with the `"full"` feature.* 179 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 180 pub struct PatPath { 181 pub attrs: Vec<Attribute>, 182 pub qself: Option<QSelf>, 183 pub path: Path, 184 } 185 } 186 187 ast_struct! { 188 /// A range pattern: `1..=2`. 189 /// 190 /// *This type is available only if Syn is built with the `"full"` feature.* 191 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 192 pub struct PatRange { 193 pub attrs: Vec<Attribute>, 194 pub lo: Box<Expr>, 195 pub limits: RangeLimits, 196 pub hi: Box<Expr>, 197 } 198 } 199 200 ast_struct! { 201 /// A reference pattern: `&mut var`. 202 /// 203 /// *This type is available only if Syn is built with the `"full"` feature.* 204 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 205 pub struct PatReference { 206 pub attrs: Vec<Attribute>, 207 pub and_token: Token![&], 208 pub mutability: Option<Token![mut]>, 209 pub pat: Box<Pat>, 210 } 211 } 212 213 ast_struct! { 214 /// The dots in a tuple or slice pattern: `[0, 1, ..]` 215 /// 216 /// *This type is available only if Syn is built with the `"full"` feature.* 217 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 218 pub struct PatRest { 219 pub attrs: Vec<Attribute>, 220 pub dot2_token: Token![..], 221 } 222 } 223 224 ast_struct! { 225 /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`. 226 /// 227 /// *This type is available only if Syn is built with the `"full"` feature.* 228 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 229 pub struct PatSlice { 230 pub attrs: Vec<Attribute>, 231 pub bracket_token: token::Bracket, 232 pub elems: Punctuated<Pat, Token![,]>, 233 } 234 } 235 236 ast_struct! { 237 /// A struct or struct variant pattern: `Variant { x, y, .. }`. 238 /// 239 /// *This type is available only if Syn is built with the `"full"` feature.* 240 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 241 pub struct PatStruct { 242 pub attrs: Vec<Attribute>, 243 pub path: Path, 244 pub brace_token: token::Brace, 245 pub fields: Punctuated<FieldPat, Token![,]>, 246 pub dot2_token: Option<Token![..]>, 247 } 248 } 249 250 ast_struct! { 251 /// A tuple pattern: `(a, b)`. 252 /// 253 /// *This type is available only if Syn is built with the `"full"` feature.* 254 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 255 pub struct PatTuple { 256 pub attrs: Vec<Attribute>, 257 pub paren_token: token::Paren, 258 pub elems: Punctuated<Pat, Token![,]>, 259 } 260 } 261 262 ast_struct! { 263 /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`. 264 /// 265 /// *This type is available only if Syn is built with the `"full"` feature.* 266 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 267 pub struct PatTupleStruct { 268 pub attrs: Vec<Attribute>, 269 pub path: Path, 270 pub pat: PatTuple, 271 } 272 } 273 274 ast_struct! { 275 /// A type ascription pattern: `foo: f64`. 276 /// 277 /// *This type is available only if Syn is built with the `"full"` feature.* 278 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 279 pub struct PatType { 280 pub attrs: Vec<Attribute>, 281 pub pat: Box<Pat>, 282 pub colon_token: Token![:], 283 pub ty: Box<Type>, 284 } 285 } 286 287 ast_struct! { 288 /// A pattern that matches any value: `_`. 289 /// 290 /// *This type is available only if Syn is built with the `"full"` feature.* 291 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 292 pub struct PatWild { 293 pub attrs: Vec<Attribute>, 294 pub underscore_token: Token![_], 295 } 296 } 297 298 ast_struct! { 299 /// A single field in a struct pattern. 300 /// 301 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated 302 /// the same as `x: x, y: ref y, z: ref mut z` but there is no colon token. 303 /// 304 /// *This type is available only if Syn is built with the `"full"` feature.* 305 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 306 pub struct FieldPat { 307 pub attrs: Vec<Attribute>, 308 pub member: Member, 309 pub colon_token: Option<Token![:]>, 310 pub pat: Box<Pat>, 311 } 312 } 313 314 #[cfg(feature = "parsing")] 315 pub mod parsing { 316 use super::*; 317 use crate::ext::IdentExt; 318 use crate::parse::{Parse, ParseBuffer, ParseStream, Result}; 319 use crate::path; 320 321 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 322 impl Parse for Pat { parse(input: ParseStream) -> Result<Self>323 fn parse(input: ParseStream) -> Result<Self> { 324 let begin = input.fork(); 325 let lookahead = input.lookahead1(); 326 if { 327 let ahead = input.fork(); 328 ahead.parse::<Option<Ident>>()?.is_some() 329 && (ahead.peek(Token![::]) 330 || ahead.peek(Token![!]) 331 || ahead.peek(token::Brace) 332 || ahead.peek(token::Paren) 333 || ahead.peek(Token![..]) 334 && ahead.parse::<RangeLimits>().is_ok() 335 && !(ahead.is_empty() || ahead.peek(Token![,]))) 336 } || { 337 let ahead = input.fork(); 338 ahead.parse::<Option<Token![self]>>()?.is_some() && ahead.peek(Token![::]) 339 } || lookahead.peek(Token![::]) 340 || lookahead.peek(Token![<]) 341 || input.peek(Token![Self]) 342 || input.peek(Token![super]) 343 || input.peek(Token![crate]) 344 { 345 pat_path_or_macro_or_struct_or_range(input) 346 } else if lookahead.peek(Token![_]) { 347 input.call(pat_wild).map(Pat::Wild) 348 } else if input.peek(Token![box]) { 349 input.call(pat_box).map(Pat::Box) 350 } else if input.peek(Token![-]) || lookahead.peek(Lit) || lookahead.peek(Token![const]) 351 { 352 pat_lit_or_range(input) 353 } else if lookahead.peek(Token![ref]) 354 || lookahead.peek(Token![mut]) 355 || input.peek(Token![self]) 356 || input.peek(Ident) 357 { 358 input.call(pat_ident).map(Pat::Ident) 359 } else if lookahead.peek(Token![&]) { 360 input.call(pat_reference).map(Pat::Reference) 361 } else if lookahead.peek(token::Paren) { 362 input.call(pat_tuple).map(Pat::Tuple) 363 } else if lookahead.peek(token::Bracket) { 364 input.call(pat_slice).map(Pat::Slice) 365 } else if lookahead.peek(Token![..]) && !input.peek(Token![...]) { 366 pat_range_half_open(input, begin) 367 } else if lookahead.peek(Token![const]) { 368 input.call(pat_const).map(Pat::Verbatim) 369 } else { 370 Err(lookahead.error()) 371 } 372 } 373 } 374 pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat>375 fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> { 376 let begin = input.fork(); 377 let (qself, path) = path::parsing::qpath(input, true)?; 378 379 if input.peek(Token![..]) { 380 return pat_range(input, begin, qself, path); 381 } 382 383 if qself.is_some() { 384 return Ok(Pat::Path(PatPath { 385 attrs: Vec::new(), 386 qself, 387 path, 388 })); 389 } 390 391 if input.peek(Token![!]) && !input.peek(Token![!=]) { 392 let mut contains_arguments = false; 393 for segment in &path.segments { 394 match segment.arguments { 395 PathArguments::None => {} 396 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => { 397 contains_arguments = true; 398 } 399 } 400 } 401 402 if !contains_arguments { 403 let bang_token: Token![!] = input.parse()?; 404 let (delimiter, tokens) = mac::parse_delimiter(input)?; 405 return Ok(Pat::Macro(PatMacro { 406 attrs: Vec::new(), 407 mac: Macro { 408 path, 409 bang_token, 410 delimiter, 411 tokens, 412 }, 413 })); 414 } 415 } 416 417 if input.peek(token::Brace) { 418 pat_struct(input, path).map(Pat::Struct) 419 } else if input.peek(token::Paren) { 420 pat_tuple_struct(input, path).map(Pat::TupleStruct) 421 } else if input.peek(Token![..]) { 422 pat_range(input, begin, qself, path) 423 } else { 424 Ok(Pat::Path(PatPath { 425 attrs: Vec::new(), 426 qself, 427 path, 428 })) 429 } 430 } 431 pat_wild(input: ParseStream) -> Result<PatWild>432 fn pat_wild(input: ParseStream) -> Result<PatWild> { 433 Ok(PatWild { 434 attrs: Vec::new(), 435 underscore_token: input.parse()?, 436 }) 437 } 438 pat_box(input: ParseStream) -> Result<PatBox>439 fn pat_box(input: ParseStream) -> Result<PatBox> { 440 Ok(PatBox { 441 attrs: Vec::new(), 442 box_token: input.parse()?, 443 pat: input.parse()?, 444 }) 445 } 446 pat_ident(input: ParseStream) -> Result<PatIdent>447 fn pat_ident(input: ParseStream) -> Result<PatIdent> { 448 Ok(PatIdent { 449 attrs: Vec::new(), 450 by_ref: input.parse()?, 451 mutability: input.parse()?, 452 ident: input.call(Ident::parse_any)?, 453 subpat: { 454 if input.peek(Token![@]) { 455 let at_token: Token![@] = input.parse()?; 456 let subpat: Pat = input.parse()?; 457 Some((at_token, Box::new(subpat))) 458 } else { 459 None 460 } 461 }, 462 }) 463 } 464 pat_tuple_struct(input: ParseStream, path: Path) -> Result<PatTupleStruct>465 fn pat_tuple_struct(input: ParseStream, path: Path) -> Result<PatTupleStruct> { 466 Ok(PatTupleStruct { 467 attrs: Vec::new(), 468 path, 469 pat: input.call(pat_tuple)?, 470 }) 471 } 472 pat_struct(input: ParseStream, path: Path) -> Result<PatStruct>473 fn pat_struct(input: ParseStream, path: Path) -> Result<PatStruct> { 474 let content; 475 let brace_token = braced!(content in input); 476 477 let mut fields = Punctuated::new(); 478 while !content.is_empty() && !content.peek(Token![..]) { 479 let value = content.call(field_pat)?; 480 fields.push_value(value); 481 if content.is_empty() { 482 break; 483 } 484 let punct: Token![,] = content.parse()?; 485 fields.push_punct(punct); 486 } 487 488 let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) { 489 Some(content.parse()?) 490 } else { 491 None 492 }; 493 494 Ok(PatStruct { 495 attrs: Vec::new(), 496 path, 497 brace_token, 498 fields, 499 dot2_token, 500 }) 501 } 502 503 impl Member { is_unnamed(&self) -> bool504 fn is_unnamed(&self) -> bool { 505 match *self { 506 Member::Named(_) => false, 507 Member::Unnamed(_) => true, 508 } 509 } 510 } 511 field_pat(input: ParseStream) -> Result<FieldPat>512 fn field_pat(input: ParseStream) -> Result<FieldPat> { 513 let attrs = input.call(Attribute::parse_outer)?; 514 let boxed: Option<Token![box]> = input.parse()?; 515 let by_ref: Option<Token![ref]> = input.parse()?; 516 let mutability: Option<Token![mut]> = input.parse()?; 517 let member: Member = input.parse()?; 518 519 if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:]) 520 || member.is_unnamed() 521 { 522 return Ok(FieldPat { 523 attrs, 524 member, 525 colon_token: input.parse()?, 526 pat: Box::new(multi_pat_with_leading_vert(input)?), 527 }); 528 } 529 530 let ident = match member { 531 Member::Named(ident) => ident, 532 Member::Unnamed(_) => unreachable!(), 533 }; 534 535 let mut pat = Pat::Ident(PatIdent { 536 attrs: Vec::new(), 537 by_ref, 538 mutability, 539 ident: ident.clone(), 540 subpat: None, 541 }); 542 543 if let Some(boxed) = boxed { 544 pat = Pat::Box(PatBox { 545 attrs: Vec::new(), 546 box_token: boxed, 547 pat: Box::new(pat), 548 }); 549 } 550 551 Ok(FieldPat { 552 attrs, 553 member: Member::Named(ident), 554 colon_token: None, 555 pat: Box::new(pat), 556 }) 557 } 558 pat_range( input: ParseStream, begin: ParseBuffer, qself: Option<QSelf>, path: Path, ) -> Result<Pat>559 fn pat_range( 560 input: ParseStream, 561 begin: ParseBuffer, 562 qself: Option<QSelf>, 563 path: Path, 564 ) -> Result<Pat> { 565 let limits: RangeLimits = input.parse()?; 566 let hi = input.call(pat_lit_expr)?; 567 if let Some(hi) = hi { 568 Ok(Pat::Range(PatRange { 569 attrs: Vec::new(), 570 lo: Box::new(Expr::Path(ExprPath { 571 attrs: Vec::new(), 572 qself, 573 path, 574 })), 575 limits, 576 hi, 577 })) 578 } else { 579 Ok(Pat::Verbatim(verbatim::between(begin, input))) 580 } 581 } 582 pat_range_half_open(input: ParseStream, begin: ParseBuffer) -> Result<Pat>583 fn pat_range_half_open(input: ParseStream, begin: ParseBuffer) -> Result<Pat> { 584 let limits: RangeLimits = input.parse()?; 585 let hi = input.call(pat_lit_expr)?; 586 if hi.is_some() { 587 Ok(Pat::Verbatim(verbatim::between(begin, input))) 588 } else { 589 match limits { 590 RangeLimits::HalfOpen(dot2_token) => Ok(Pat::Rest(PatRest { 591 attrs: Vec::new(), 592 dot2_token, 593 })), 594 RangeLimits::Closed(_) => Err(input.error("expected range upper bound")), 595 } 596 } 597 } 598 pat_tuple(input: ParseStream) -> Result<PatTuple>599 fn pat_tuple(input: ParseStream) -> Result<PatTuple> { 600 let content; 601 let paren_token = parenthesized!(content in input); 602 603 let mut elems = Punctuated::new(); 604 while !content.is_empty() { 605 let value = multi_pat_with_leading_vert(&content)?; 606 elems.push_value(value); 607 if content.is_empty() { 608 break; 609 } 610 let punct = content.parse()?; 611 elems.push_punct(punct); 612 } 613 614 Ok(PatTuple { 615 attrs: Vec::new(), 616 paren_token, 617 elems, 618 }) 619 } 620 pat_reference(input: ParseStream) -> Result<PatReference>621 fn pat_reference(input: ParseStream) -> Result<PatReference> { 622 Ok(PatReference { 623 attrs: Vec::new(), 624 and_token: input.parse()?, 625 mutability: input.parse()?, 626 pat: input.parse()?, 627 }) 628 } 629 pat_lit_or_range(input: ParseStream) -> Result<Pat>630 fn pat_lit_or_range(input: ParseStream) -> Result<Pat> { 631 let begin = input.fork(); 632 let lo = input.call(pat_lit_expr)?.unwrap(); 633 if input.peek(Token![..]) { 634 let limits: RangeLimits = input.parse()?; 635 let hi = input.call(pat_lit_expr)?; 636 if let Some(hi) = hi { 637 Ok(Pat::Range(PatRange { 638 attrs: Vec::new(), 639 lo, 640 limits, 641 hi, 642 })) 643 } else { 644 Ok(Pat::Verbatim(verbatim::between(begin, input))) 645 } 646 } else if let Expr::Verbatim(verbatim) = *lo { 647 Ok(Pat::Verbatim(verbatim)) 648 } else { 649 Ok(Pat::Lit(PatLit { 650 attrs: Vec::new(), 651 expr: lo, 652 })) 653 } 654 } 655 pat_lit_expr(input: ParseStream) -> Result<Option<Box<Expr>>>656 fn pat_lit_expr(input: ParseStream) -> Result<Option<Box<Expr>>> { 657 if input.is_empty() 658 || input.peek(Token![|]) 659 || input.peek(Token![=>]) 660 || input.peek(Token![:]) && !input.peek(Token![::]) 661 || input.peek(Token![,]) 662 || input.peek(Token![;]) 663 { 664 return Ok(None); 665 } 666 667 let neg: Option<Token![-]> = input.parse()?; 668 669 let lookahead = input.lookahead1(); 670 let expr = if lookahead.peek(Lit) { 671 Expr::Lit(input.parse()?) 672 } else if lookahead.peek(Ident) 673 || lookahead.peek(Token![::]) 674 || lookahead.peek(Token![<]) 675 || lookahead.peek(Token![self]) 676 || lookahead.peek(Token![Self]) 677 || lookahead.peek(Token![super]) 678 || lookahead.peek(Token![crate]) 679 { 680 Expr::Path(input.parse()?) 681 } else if lookahead.peek(Token![const]) { 682 Expr::Verbatim(input.call(expr::parsing::expr_const)?) 683 } else { 684 return Err(lookahead.error()); 685 }; 686 687 Ok(Some(Box::new(if let Some(neg) = neg { 688 Expr::Unary(ExprUnary { 689 attrs: Vec::new(), 690 op: UnOp::Neg(neg), 691 expr: Box::new(expr), 692 }) 693 } else { 694 expr 695 }))) 696 } 697 pat_slice(input: ParseStream) -> Result<PatSlice>698 fn pat_slice(input: ParseStream) -> Result<PatSlice> { 699 let content; 700 let bracket_token = bracketed!(content in input); 701 702 let mut elems = Punctuated::new(); 703 while !content.is_empty() { 704 let value = multi_pat_with_leading_vert(&content)?; 705 elems.push_value(value); 706 if content.is_empty() { 707 break; 708 } 709 let punct = content.parse()?; 710 elems.push_punct(punct); 711 } 712 713 Ok(PatSlice { 714 attrs: Vec::new(), 715 bracket_token, 716 elems, 717 }) 718 } 719 pat_const(input: ParseStream) -> Result<TokenStream>720 fn pat_const(input: ParseStream) -> Result<TokenStream> { 721 let begin = input.fork(); 722 input.parse::<Token![const]>()?; 723 724 let content; 725 braced!(content in input); 726 content.call(Attribute::parse_inner)?; 727 content.call(Block::parse_within)?; 728 729 Ok(verbatim::between(begin, input)) 730 } 731 multi_pat(input: ParseStream) -> Result<Pat>732 pub fn multi_pat(input: ParseStream) -> Result<Pat> { 733 multi_pat_impl(input, None) 734 } 735 multi_pat_with_leading_vert(input: ParseStream) -> Result<Pat>736 pub fn multi_pat_with_leading_vert(input: ParseStream) -> Result<Pat> { 737 let leading_vert: Option<Token![|]> = input.parse()?; 738 multi_pat_impl(input, leading_vert) 739 } 740 multi_pat_impl(input: ParseStream, leading_vert: Option<Token![|]>) -> Result<Pat>741 fn multi_pat_impl(input: ParseStream, leading_vert: Option<Token![|]>) -> Result<Pat> { 742 let mut pat: Pat = input.parse()?; 743 if leading_vert.is_some() 744 || input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) 745 { 746 let mut cases = Punctuated::new(); 747 cases.push_value(pat); 748 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) { 749 let punct = input.parse()?; 750 cases.push_punct(punct); 751 let pat: Pat = input.parse()?; 752 cases.push_value(pat); 753 } 754 pat = Pat::Or(PatOr { 755 attrs: Vec::new(), 756 leading_vert, 757 cases, 758 }); 759 } 760 Ok(pat) 761 } 762 } 763 764 #[cfg(feature = "printing")] 765 mod printing { 766 use super::*; 767 use crate::attr::FilterAttrs; 768 use proc_macro2::TokenStream; 769 use quote::{ToTokens, TokenStreamExt}; 770 771 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 772 impl ToTokens for PatWild { to_tokens(&self, tokens: &mut TokenStream)773 fn to_tokens(&self, tokens: &mut TokenStream) { 774 tokens.append_all(self.attrs.outer()); 775 self.underscore_token.to_tokens(tokens); 776 } 777 } 778 779 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 780 impl ToTokens for PatIdent { to_tokens(&self, tokens: &mut TokenStream)781 fn to_tokens(&self, tokens: &mut TokenStream) { 782 tokens.append_all(self.attrs.outer()); 783 self.by_ref.to_tokens(tokens); 784 self.mutability.to_tokens(tokens); 785 self.ident.to_tokens(tokens); 786 if let Some((at_token, subpat)) = &self.subpat { 787 at_token.to_tokens(tokens); 788 subpat.to_tokens(tokens); 789 } 790 } 791 } 792 793 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 794 impl ToTokens for PatStruct { to_tokens(&self, tokens: &mut TokenStream)795 fn to_tokens(&self, tokens: &mut TokenStream) { 796 tokens.append_all(self.attrs.outer()); 797 self.path.to_tokens(tokens); 798 self.brace_token.surround(tokens, |tokens| { 799 self.fields.to_tokens(tokens); 800 // NOTE: We need a comma before the dot2 token if it is present. 801 if !self.fields.empty_or_trailing() && self.dot2_token.is_some() { 802 <Token![,]>::default().to_tokens(tokens); 803 } 804 self.dot2_token.to_tokens(tokens); 805 }); 806 } 807 } 808 809 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 810 impl ToTokens for PatTupleStruct { to_tokens(&self, tokens: &mut TokenStream)811 fn to_tokens(&self, tokens: &mut TokenStream) { 812 tokens.append_all(self.attrs.outer()); 813 self.path.to_tokens(tokens); 814 self.pat.to_tokens(tokens); 815 } 816 } 817 818 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 819 impl ToTokens for PatType { to_tokens(&self, tokens: &mut TokenStream)820 fn to_tokens(&self, tokens: &mut TokenStream) { 821 tokens.append_all(self.attrs.outer()); 822 self.pat.to_tokens(tokens); 823 self.colon_token.to_tokens(tokens); 824 self.ty.to_tokens(tokens); 825 } 826 } 827 828 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 829 impl ToTokens for PatPath { to_tokens(&self, tokens: &mut TokenStream)830 fn to_tokens(&self, tokens: &mut TokenStream) { 831 tokens.append_all(self.attrs.outer()); 832 private::print_path(tokens, &self.qself, &self.path); 833 } 834 } 835 836 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 837 impl ToTokens for PatTuple { to_tokens(&self, tokens: &mut TokenStream)838 fn to_tokens(&self, tokens: &mut TokenStream) { 839 tokens.append_all(self.attrs.outer()); 840 self.paren_token.surround(tokens, |tokens| { 841 self.elems.to_tokens(tokens); 842 }); 843 } 844 } 845 846 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 847 impl ToTokens for PatBox { to_tokens(&self, tokens: &mut TokenStream)848 fn to_tokens(&self, tokens: &mut TokenStream) { 849 tokens.append_all(self.attrs.outer()); 850 self.box_token.to_tokens(tokens); 851 self.pat.to_tokens(tokens); 852 } 853 } 854 855 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 856 impl ToTokens for PatReference { to_tokens(&self, tokens: &mut TokenStream)857 fn to_tokens(&self, tokens: &mut TokenStream) { 858 tokens.append_all(self.attrs.outer()); 859 self.and_token.to_tokens(tokens); 860 self.mutability.to_tokens(tokens); 861 self.pat.to_tokens(tokens); 862 } 863 } 864 865 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 866 impl ToTokens for PatRest { to_tokens(&self, tokens: &mut TokenStream)867 fn to_tokens(&self, tokens: &mut TokenStream) { 868 tokens.append_all(self.attrs.outer()); 869 self.dot2_token.to_tokens(tokens); 870 } 871 } 872 873 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 874 impl ToTokens for PatLit { to_tokens(&self, tokens: &mut TokenStream)875 fn to_tokens(&self, tokens: &mut TokenStream) { 876 tokens.append_all(self.attrs.outer()); 877 self.expr.to_tokens(tokens); 878 } 879 } 880 881 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 882 impl ToTokens for PatRange { to_tokens(&self, tokens: &mut TokenStream)883 fn to_tokens(&self, tokens: &mut TokenStream) { 884 tokens.append_all(self.attrs.outer()); 885 self.lo.to_tokens(tokens); 886 match &self.limits { 887 RangeLimits::HalfOpen(t) => t.to_tokens(tokens), 888 RangeLimits::Closed(t) => t.to_tokens(tokens), 889 } 890 self.hi.to_tokens(tokens); 891 } 892 } 893 894 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 895 impl ToTokens for PatSlice { to_tokens(&self, tokens: &mut TokenStream)896 fn to_tokens(&self, tokens: &mut TokenStream) { 897 tokens.append_all(self.attrs.outer()); 898 self.bracket_token.surround(tokens, |tokens| { 899 self.elems.to_tokens(tokens); 900 }); 901 } 902 } 903 904 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 905 impl ToTokens for PatMacro { to_tokens(&self, tokens: &mut TokenStream)906 fn to_tokens(&self, tokens: &mut TokenStream) { 907 tokens.append_all(self.attrs.outer()); 908 self.mac.to_tokens(tokens); 909 } 910 } 911 912 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 913 impl ToTokens for PatOr { to_tokens(&self, tokens: &mut TokenStream)914 fn to_tokens(&self, tokens: &mut TokenStream) { 915 tokens.append_all(self.attrs.outer()); 916 self.leading_vert.to_tokens(tokens); 917 self.cases.to_tokens(tokens); 918 } 919 } 920 921 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 922 impl ToTokens for FieldPat { to_tokens(&self, tokens: &mut TokenStream)923 fn to_tokens(&self, tokens: &mut TokenStream) { 924 tokens.append_all(self.attrs.outer()); 925 if let Some(colon_token) = &self.colon_token { 926 self.member.to_tokens(tokens); 927 colon_token.to_tokens(tokens); 928 } 929 self.pat.to_tokens(tokens); 930 } 931 } 932 } 933