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 qself.is_none() && input.peek(Token![!]) && !input.peek(Token![!=]) { 380 let mut contains_arguments = false; 381 for segment in &path.segments { 382 match segment.arguments { 383 PathArguments::None => {} 384 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => { 385 contains_arguments = true; 386 } 387 } 388 } 389 390 if !contains_arguments { 391 let bang_token: Token![!] = input.parse()?; 392 let (delimiter, tokens) = mac::parse_delimiter(input)?; 393 return Ok(Pat::Macro(PatMacro { 394 attrs: Vec::new(), 395 mac: Macro { 396 path, 397 bang_token, 398 delimiter, 399 tokens, 400 }, 401 })); 402 } 403 } 404 405 if input.peek(token::Brace) { 406 let pat = pat_struct(input, path)?; 407 if qself.is_some() { 408 Ok(Pat::Verbatim(verbatim::between(begin, input))) 409 } else { 410 Ok(Pat::Struct(pat)) 411 } 412 } else if input.peek(token::Paren) { 413 let pat = pat_tuple_struct(input, path)?; 414 if qself.is_some() { 415 Ok(Pat::Verbatim(verbatim::between(begin, input))) 416 } else { 417 Ok(Pat::TupleStruct(pat)) 418 } 419 } else if input.peek(Token![..]) { 420 pat_range(input, begin, qself, path) 421 } else { 422 Ok(Pat::Path(PatPath { 423 attrs: Vec::new(), 424 qself, 425 path, 426 })) 427 } 428 } 429 pat_wild(input: ParseStream) -> Result<PatWild>430 fn pat_wild(input: ParseStream) -> Result<PatWild> { 431 Ok(PatWild { 432 attrs: Vec::new(), 433 underscore_token: input.parse()?, 434 }) 435 } 436 pat_box(input: ParseStream) -> Result<PatBox>437 fn pat_box(input: ParseStream) -> Result<PatBox> { 438 Ok(PatBox { 439 attrs: Vec::new(), 440 box_token: input.parse()?, 441 pat: input.parse()?, 442 }) 443 } 444 pat_ident(input: ParseStream) -> Result<PatIdent>445 fn pat_ident(input: ParseStream) -> Result<PatIdent> { 446 Ok(PatIdent { 447 attrs: Vec::new(), 448 by_ref: input.parse()?, 449 mutability: input.parse()?, 450 ident: input.call(Ident::parse_any)?, 451 subpat: { 452 if input.peek(Token![@]) { 453 let at_token: Token![@] = input.parse()?; 454 let subpat: Pat = input.parse()?; 455 Some((at_token, Box::new(subpat))) 456 } else { 457 None 458 } 459 }, 460 }) 461 } 462 pat_tuple_struct(input: ParseStream, path: Path) -> Result<PatTupleStruct>463 fn pat_tuple_struct(input: ParseStream, path: Path) -> Result<PatTupleStruct> { 464 Ok(PatTupleStruct { 465 attrs: Vec::new(), 466 path, 467 pat: input.call(pat_tuple)?, 468 }) 469 } 470 pat_struct(input: ParseStream, path: Path) -> Result<PatStruct>471 fn pat_struct(input: ParseStream, path: Path) -> Result<PatStruct> { 472 let content; 473 let brace_token = braced!(content in input); 474 475 let mut fields = Punctuated::new(); 476 while !content.is_empty() && !content.peek(Token![..]) { 477 let value = content.call(field_pat)?; 478 fields.push_value(value); 479 if content.is_empty() { 480 break; 481 } 482 let punct: Token![,] = content.parse()?; 483 fields.push_punct(punct); 484 } 485 486 let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) { 487 Some(content.parse()?) 488 } else { 489 None 490 }; 491 492 Ok(PatStruct { 493 attrs: Vec::new(), 494 path, 495 brace_token, 496 fields, 497 dot2_token, 498 }) 499 } 500 501 impl Member { is_unnamed(&self) -> bool502 fn is_unnamed(&self) -> bool { 503 match *self { 504 Member::Named(_) => false, 505 Member::Unnamed(_) => true, 506 } 507 } 508 } 509 field_pat(input: ParseStream) -> Result<FieldPat>510 fn field_pat(input: ParseStream) -> Result<FieldPat> { 511 let attrs = input.call(Attribute::parse_outer)?; 512 let boxed: Option<Token![box]> = input.parse()?; 513 let by_ref: Option<Token![ref]> = input.parse()?; 514 let mutability: Option<Token![mut]> = input.parse()?; 515 let member: Member = input.parse()?; 516 517 if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:]) 518 || member.is_unnamed() 519 { 520 return Ok(FieldPat { 521 attrs, 522 member, 523 colon_token: input.parse()?, 524 pat: Box::new(multi_pat_with_leading_vert(input)?), 525 }); 526 } 527 528 let ident = match member { 529 Member::Named(ident) => ident, 530 Member::Unnamed(_) => unreachable!(), 531 }; 532 533 let mut pat = Pat::Ident(PatIdent { 534 attrs: Vec::new(), 535 by_ref, 536 mutability, 537 ident: ident.clone(), 538 subpat: None, 539 }); 540 541 if let Some(boxed) = boxed { 542 pat = Pat::Box(PatBox { 543 attrs: Vec::new(), 544 box_token: boxed, 545 pat: Box::new(pat), 546 }); 547 } 548 549 Ok(FieldPat { 550 attrs, 551 member: Member::Named(ident), 552 colon_token: None, 553 pat: Box::new(pat), 554 }) 555 } 556 pat_range( input: ParseStream, begin: ParseBuffer, qself: Option<QSelf>, path: Path, ) -> Result<Pat>557 fn pat_range( 558 input: ParseStream, 559 begin: ParseBuffer, 560 qself: Option<QSelf>, 561 path: Path, 562 ) -> Result<Pat> { 563 let limits: RangeLimits = input.parse()?; 564 let hi = input.call(pat_lit_expr)?; 565 if let Some(hi) = hi { 566 Ok(Pat::Range(PatRange { 567 attrs: Vec::new(), 568 lo: Box::new(Expr::Path(ExprPath { 569 attrs: Vec::new(), 570 qself, 571 path, 572 })), 573 limits, 574 hi, 575 })) 576 } else { 577 Ok(Pat::Verbatim(verbatim::between(begin, input))) 578 } 579 } 580 pat_range_half_open(input: ParseStream, begin: ParseBuffer) -> Result<Pat>581 fn pat_range_half_open(input: ParseStream, begin: ParseBuffer) -> Result<Pat> { 582 let limits: RangeLimits = input.parse()?; 583 let hi = input.call(pat_lit_expr)?; 584 if hi.is_some() { 585 Ok(Pat::Verbatim(verbatim::between(begin, input))) 586 } else { 587 match limits { 588 RangeLimits::HalfOpen(dot2_token) => Ok(Pat::Rest(PatRest { 589 attrs: Vec::new(), 590 dot2_token, 591 })), 592 RangeLimits::Closed(_) => Err(input.error("expected range upper bound")), 593 } 594 } 595 } 596 pat_tuple(input: ParseStream) -> Result<PatTuple>597 fn pat_tuple(input: ParseStream) -> Result<PatTuple> { 598 let content; 599 let paren_token = parenthesized!(content in input); 600 601 let mut elems = Punctuated::new(); 602 while !content.is_empty() { 603 let value = multi_pat_with_leading_vert(&content)?; 604 elems.push_value(value); 605 if content.is_empty() { 606 break; 607 } 608 let punct = content.parse()?; 609 elems.push_punct(punct); 610 } 611 612 Ok(PatTuple { 613 attrs: Vec::new(), 614 paren_token, 615 elems, 616 }) 617 } 618 pat_reference(input: ParseStream) -> Result<PatReference>619 fn pat_reference(input: ParseStream) -> Result<PatReference> { 620 Ok(PatReference { 621 attrs: Vec::new(), 622 and_token: input.parse()?, 623 mutability: input.parse()?, 624 pat: input.parse()?, 625 }) 626 } 627 pat_lit_or_range(input: ParseStream) -> Result<Pat>628 fn pat_lit_or_range(input: ParseStream) -> Result<Pat> { 629 let begin = input.fork(); 630 let lo = input.call(pat_lit_expr)?.unwrap(); 631 if input.peek(Token![..]) { 632 let limits: RangeLimits = input.parse()?; 633 let hi = input.call(pat_lit_expr)?; 634 if let Some(hi) = hi { 635 Ok(Pat::Range(PatRange { 636 attrs: Vec::new(), 637 lo, 638 limits, 639 hi, 640 })) 641 } else { 642 Ok(Pat::Verbatim(verbatim::between(begin, input))) 643 } 644 } else if let Expr::Verbatim(verbatim) = *lo { 645 Ok(Pat::Verbatim(verbatim)) 646 } else { 647 Ok(Pat::Lit(PatLit { 648 attrs: Vec::new(), 649 expr: lo, 650 })) 651 } 652 } 653 pat_lit_expr(input: ParseStream) -> Result<Option<Box<Expr>>>654 fn pat_lit_expr(input: ParseStream) -> Result<Option<Box<Expr>>> { 655 if input.is_empty() 656 || input.peek(Token![|]) 657 || input.peek(Token![=>]) 658 || input.peek(Token![:]) && !input.peek(Token![::]) 659 || input.peek(Token![,]) 660 || input.peek(Token![;]) 661 { 662 return Ok(None); 663 } 664 665 let neg: Option<Token![-]> = input.parse()?; 666 667 let lookahead = input.lookahead1(); 668 let expr = if lookahead.peek(Lit) { 669 Expr::Lit(input.parse()?) 670 } else if lookahead.peek(Ident) 671 || lookahead.peek(Token![::]) 672 || lookahead.peek(Token![<]) 673 || lookahead.peek(Token![self]) 674 || lookahead.peek(Token![Self]) 675 || lookahead.peek(Token![super]) 676 || lookahead.peek(Token![crate]) 677 { 678 Expr::Path(input.parse()?) 679 } else if lookahead.peek(Token![const]) { 680 Expr::Verbatim(input.call(expr::parsing::expr_const)?) 681 } else { 682 return Err(lookahead.error()); 683 }; 684 685 Ok(Some(Box::new(if let Some(neg) = neg { 686 Expr::Unary(ExprUnary { 687 attrs: Vec::new(), 688 op: UnOp::Neg(neg), 689 expr: Box::new(expr), 690 }) 691 } else { 692 expr 693 }))) 694 } 695 pat_slice(input: ParseStream) -> Result<PatSlice>696 fn pat_slice(input: ParseStream) -> Result<PatSlice> { 697 let content; 698 let bracket_token = bracketed!(content in input); 699 700 let mut elems = Punctuated::new(); 701 while !content.is_empty() { 702 let value = multi_pat_with_leading_vert(&content)?; 703 elems.push_value(value); 704 if content.is_empty() { 705 break; 706 } 707 let punct = content.parse()?; 708 elems.push_punct(punct); 709 } 710 711 Ok(PatSlice { 712 attrs: Vec::new(), 713 bracket_token, 714 elems, 715 }) 716 } 717 pat_const(input: ParseStream) -> Result<TokenStream>718 fn pat_const(input: ParseStream) -> Result<TokenStream> { 719 let begin = input.fork(); 720 input.parse::<Token![const]>()?; 721 722 let content; 723 braced!(content in input); 724 content.call(Attribute::parse_inner)?; 725 content.call(Block::parse_within)?; 726 727 Ok(verbatim::between(begin, input)) 728 } 729 multi_pat(input: ParseStream) -> Result<Pat>730 pub fn multi_pat(input: ParseStream) -> Result<Pat> { 731 multi_pat_impl(input, None) 732 } 733 multi_pat_with_leading_vert(input: ParseStream) -> Result<Pat>734 pub fn multi_pat_with_leading_vert(input: ParseStream) -> Result<Pat> { 735 let leading_vert: Option<Token![|]> = input.parse()?; 736 multi_pat_impl(input, leading_vert) 737 } 738 multi_pat_impl(input: ParseStream, leading_vert: Option<Token![|]>) -> Result<Pat>739 fn multi_pat_impl(input: ParseStream, leading_vert: Option<Token![|]>) -> Result<Pat> { 740 let mut pat: Pat = input.parse()?; 741 if leading_vert.is_some() 742 || input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) 743 { 744 let mut cases = Punctuated::new(); 745 cases.push_value(pat); 746 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) { 747 let punct = input.parse()?; 748 cases.push_punct(punct); 749 let pat: Pat = input.parse()?; 750 cases.push_value(pat); 751 } 752 pat = Pat::Or(PatOr { 753 attrs: Vec::new(), 754 leading_vert, 755 cases, 756 }); 757 } 758 Ok(pat) 759 } 760 } 761 762 #[cfg(feature = "printing")] 763 mod printing { 764 use super::*; 765 use crate::attr::FilterAttrs; 766 use proc_macro2::TokenStream; 767 use quote::{ToTokens, TokenStreamExt}; 768 769 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 770 impl ToTokens for PatWild { to_tokens(&self, tokens: &mut TokenStream)771 fn to_tokens(&self, tokens: &mut TokenStream) { 772 tokens.append_all(self.attrs.outer()); 773 self.underscore_token.to_tokens(tokens); 774 } 775 } 776 777 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 778 impl ToTokens for PatIdent { to_tokens(&self, tokens: &mut TokenStream)779 fn to_tokens(&self, tokens: &mut TokenStream) { 780 tokens.append_all(self.attrs.outer()); 781 self.by_ref.to_tokens(tokens); 782 self.mutability.to_tokens(tokens); 783 self.ident.to_tokens(tokens); 784 if let Some((at_token, subpat)) = &self.subpat { 785 at_token.to_tokens(tokens); 786 subpat.to_tokens(tokens); 787 } 788 } 789 } 790 791 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 792 impl ToTokens for PatStruct { to_tokens(&self, tokens: &mut TokenStream)793 fn to_tokens(&self, tokens: &mut TokenStream) { 794 tokens.append_all(self.attrs.outer()); 795 self.path.to_tokens(tokens); 796 self.brace_token.surround(tokens, |tokens| { 797 self.fields.to_tokens(tokens); 798 // NOTE: We need a comma before the dot2 token if it is present. 799 if !self.fields.empty_or_trailing() && self.dot2_token.is_some() { 800 <Token![,]>::default().to_tokens(tokens); 801 } 802 self.dot2_token.to_tokens(tokens); 803 }); 804 } 805 } 806 807 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 808 impl ToTokens for PatTupleStruct { to_tokens(&self, tokens: &mut TokenStream)809 fn to_tokens(&self, tokens: &mut TokenStream) { 810 tokens.append_all(self.attrs.outer()); 811 self.path.to_tokens(tokens); 812 self.pat.to_tokens(tokens); 813 } 814 } 815 816 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 817 impl ToTokens for PatType { to_tokens(&self, tokens: &mut TokenStream)818 fn to_tokens(&self, tokens: &mut TokenStream) { 819 tokens.append_all(self.attrs.outer()); 820 self.pat.to_tokens(tokens); 821 self.colon_token.to_tokens(tokens); 822 self.ty.to_tokens(tokens); 823 } 824 } 825 826 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 827 impl ToTokens for PatPath { to_tokens(&self, tokens: &mut TokenStream)828 fn to_tokens(&self, tokens: &mut TokenStream) { 829 tokens.append_all(self.attrs.outer()); 830 private::print_path(tokens, &self.qself, &self.path); 831 } 832 } 833 834 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 835 impl ToTokens for PatTuple { to_tokens(&self, tokens: &mut TokenStream)836 fn to_tokens(&self, tokens: &mut TokenStream) { 837 tokens.append_all(self.attrs.outer()); 838 self.paren_token.surround(tokens, |tokens| { 839 self.elems.to_tokens(tokens); 840 }); 841 } 842 } 843 844 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 845 impl ToTokens for PatBox { to_tokens(&self, tokens: &mut TokenStream)846 fn to_tokens(&self, tokens: &mut TokenStream) { 847 tokens.append_all(self.attrs.outer()); 848 self.box_token.to_tokens(tokens); 849 self.pat.to_tokens(tokens); 850 } 851 } 852 853 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 854 impl ToTokens for PatReference { to_tokens(&self, tokens: &mut TokenStream)855 fn to_tokens(&self, tokens: &mut TokenStream) { 856 tokens.append_all(self.attrs.outer()); 857 self.and_token.to_tokens(tokens); 858 self.mutability.to_tokens(tokens); 859 self.pat.to_tokens(tokens); 860 } 861 } 862 863 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 864 impl ToTokens for PatRest { to_tokens(&self, tokens: &mut TokenStream)865 fn to_tokens(&self, tokens: &mut TokenStream) { 866 tokens.append_all(self.attrs.outer()); 867 self.dot2_token.to_tokens(tokens); 868 } 869 } 870 871 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 872 impl ToTokens for PatLit { to_tokens(&self, tokens: &mut TokenStream)873 fn to_tokens(&self, tokens: &mut TokenStream) { 874 tokens.append_all(self.attrs.outer()); 875 self.expr.to_tokens(tokens); 876 } 877 } 878 879 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 880 impl ToTokens for PatRange { to_tokens(&self, tokens: &mut TokenStream)881 fn to_tokens(&self, tokens: &mut TokenStream) { 882 tokens.append_all(self.attrs.outer()); 883 self.lo.to_tokens(tokens); 884 match &self.limits { 885 RangeLimits::HalfOpen(t) => t.to_tokens(tokens), 886 RangeLimits::Closed(t) => t.to_tokens(tokens), 887 } 888 self.hi.to_tokens(tokens); 889 } 890 } 891 892 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 893 impl ToTokens for PatSlice { to_tokens(&self, tokens: &mut TokenStream)894 fn to_tokens(&self, tokens: &mut TokenStream) { 895 tokens.append_all(self.attrs.outer()); 896 self.bracket_token.surround(tokens, |tokens| { 897 self.elems.to_tokens(tokens); 898 }); 899 } 900 } 901 902 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 903 impl ToTokens for PatMacro { to_tokens(&self, tokens: &mut TokenStream)904 fn to_tokens(&self, tokens: &mut TokenStream) { 905 tokens.append_all(self.attrs.outer()); 906 self.mac.to_tokens(tokens); 907 } 908 } 909 910 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 911 impl ToTokens for PatOr { to_tokens(&self, tokens: &mut TokenStream)912 fn to_tokens(&self, tokens: &mut TokenStream) { 913 tokens.append_all(self.attrs.outer()); 914 self.leading_vert.to_tokens(tokens); 915 self.cases.to_tokens(tokens); 916 } 917 } 918 919 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 920 impl ToTokens for FieldPat { to_tokens(&self, tokens: &mut TokenStream)921 fn to_tokens(&self, tokens: &mut TokenStream) { 922 tokens.append_all(self.attrs.outer()); 923 if let Some(colon_token) = &self.colon_token { 924 self.member.to_tokens(tokens); 925 colon_token.to_tokens(tokens); 926 } 927 self.pat.to_tokens(tokens); 928 } 929 } 930 } 931