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 #[cfg_attr(not(syn_no_non_exhaustive), non_exhaustive)] 18 pub enum Pat { 19 /// A box pattern: `box v`. 20 Box(PatBox), 21 22 /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`. 23 Ident(PatIdent), 24 25 /// A literal pattern: `0`. 26 /// 27 /// This holds an `Expr` rather than a `Lit` because negative numbers 28 /// are represented as an `Expr::Unary`. 29 Lit(PatLit), 30 31 /// A macro in pattern position. 32 Macro(PatMacro), 33 34 /// A pattern that matches any one of a set of cases. 35 Or(PatOr), 36 37 /// A path pattern like `Color::Red`, optionally qualified with a 38 /// self-type. 39 /// 40 /// Unqualified path patterns can legally refer to variants, structs, 41 /// constants or associated constants. Qualified path patterns like 42 /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to 43 /// associated constants. 44 Path(PatPath), 45 46 /// A range pattern: `1..=2`. 47 Range(PatRange), 48 49 /// A reference pattern: `&mut var`. 50 Reference(PatReference), 51 52 /// The dots in a tuple or slice pattern: `[0, 1, ..]` 53 Rest(PatRest), 54 55 /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`. 56 Slice(PatSlice), 57 58 /// A struct or struct variant pattern: `Variant { x, y, .. }`. 59 Struct(PatStruct), 60 61 /// A tuple pattern: `(a, b)`. 62 Tuple(PatTuple), 63 64 /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`. 65 TupleStruct(PatTupleStruct), 66 67 /// A type ascription pattern: `foo: f64`. 68 Type(PatType), 69 70 /// Tokens in pattern position not interpreted by Syn. 71 Verbatim(TokenStream), 72 73 /// A pattern that matches any value: `_`. 74 Wild(PatWild), 75 76 // Not public API. 77 // 78 // For testing exhaustiveness in downstream code, use the following idiom: 79 // 80 // match pat { 81 // Pat::Box(pat) => {...} 82 // Pat::Ident(pat) => {...} 83 // ... 84 // Pat::Wild(pat) => {...} 85 // 86 // #[cfg_attr(test, deny(non_exhaustive_omitted_patterns))] 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 #[cfg(syn_no_non_exhaustive)] 95 #[doc(hidden)] 96 __NonExhaustive, 97 } 98 } 99 100 ast_struct! { 101 /// A box pattern: `box v`. 102 /// 103 /// *This type is available only if Syn is built with the `"full"` feature.* 104 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 105 pub struct PatBox { 106 pub attrs: Vec<Attribute>, 107 pub box_token: Token![box], 108 pub pat: Box<Pat>, 109 } 110 } 111 112 ast_struct! { 113 /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`. 114 /// 115 /// It may also be a unit struct or struct variant (e.g. `None`), or a 116 /// constant; these cannot be distinguished syntactically. 117 /// 118 /// *This type is available only if Syn is built with the `"full"` feature.* 119 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 120 pub struct PatIdent { 121 pub attrs: Vec<Attribute>, 122 pub by_ref: Option<Token![ref]>, 123 pub mutability: Option<Token![mut]>, 124 pub ident: Ident, 125 pub subpat: Option<(Token![@], Box<Pat>)>, 126 } 127 } 128 129 ast_struct! { 130 /// A literal pattern: `0`. 131 /// 132 /// This holds an `Expr` rather than a `Lit` because negative numbers 133 /// are represented as an `Expr::Unary`. 134 /// 135 /// *This type is available only if Syn is built with the `"full"` feature.* 136 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 137 pub struct PatLit { 138 pub attrs: Vec<Attribute>, 139 pub expr: Box<Expr>, 140 } 141 } 142 143 ast_struct! { 144 /// A macro in pattern position. 145 /// 146 /// *This type is available only if Syn is built with the `"full"` feature.* 147 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 148 pub struct PatMacro { 149 pub attrs: Vec<Attribute>, 150 pub mac: Macro, 151 } 152 } 153 154 ast_struct! { 155 /// A pattern that matches any one of a set of cases. 156 /// 157 /// *This type is available only if Syn is built with the `"full"` feature.* 158 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 159 pub struct PatOr { 160 pub attrs: Vec<Attribute>, 161 pub leading_vert: Option<Token![|]>, 162 pub cases: Punctuated<Pat, Token![|]>, 163 } 164 } 165 166 ast_struct! { 167 /// A path pattern like `Color::Red`, optionally qualified with a 168 /// self-type. 169 /// 170 /// Unqualified path patterns can legally refer to variants, structs, 171 /// constants or associated constants. Qualified path patterns like 172 /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to 173 /// associated constants. 174 /// 175 /// *This type is available only if Syn is built with the `"full"` feature.* 176 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 177 pub struct PatPath { 178 pub attrs: Vec<Attribute>, 179 pub qself: Option<QSelf>, 180 pub path: Path, 181 } 182 } 183 184 ast_struct! { 185 /// A range pattern: `1..=2`. 186 /// 187 /// *This type is available only if Syn is built with the `"full"` feature.* 188 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 189 pub struct PatRange { 190 pub attrs: Vec<Attribute>, 191 pub lo: Box<Expr>, 192 pub limits: RangeLimits, 193 pub hi: Box<Expr>, 194 } 195 } 196 197 ast_struct! { 198 /// A reference pattern: `&mut var`. 199 /// 200 /// *This type is available only if Syn is built with the `"full"` feature.* 201 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 202 pub struct PatReference { 203 pub attrs: Vec<Attribute>, 204 pub and_token: Token![&], 205 pub mutability: Option<Token![mut]>, 206 pub pat: Box<Pat>, 207 } 208 } 209 210 ast_struct! { 211 /// The dots in a tuple or slice pattern: `[0, 1, ..]` 212 /// 213 /// *This type is available only if Syn is built with the `"full"` feature.* 214 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 215 pub struct PatRest { 216 pub attrs: Vec<Attribute>, 217 pub dot2_token: Token![..], 218 } 219 } 220 221 ast_struct! { 222 /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`. 223 /// 224 /// *This type is available only if Syn is built with the `"full"` feature.* 225 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 226 pub struct PatSlice { 227 pub attrs: Vec<Attribute>, 228 pub bracket_token: token::Bracket, 229 pub elems: Punctuated<Pat, Token![,]>, 230 } 231 } 232 233 ast_struct! { 234 /// A struct or struct variant pattern: `Variant { x, y, .. }`. 235 /// 236 /// *This type is available only if Syn is built with the `"full"` feature.* 237 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 238 pub struct PatStruct { 239 pub attrs: Vec<Attribute>, 240 pub path: Path, 241 pub brace_token: token::Brace, 242 pub fields: Punctuated<FieldPat, Token![,]>, 243 pub dot2_token: Option<Token![..]>, 244 } 245 } 246 247 ast_struct! { 248 /// A tuple pattern: `(a, b)`. 249 /// 250 /// *This type is available only if Syn is built with the `"full"` feature.* 251 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 252 pub struct PatTuple { 253 pub attrs: Vec<Attribute>, 254 pub paren_token: token::Paren, 255 pub elems: Punctuated<Pat, Token![,]>, 256 } 257 } 258 259 ast_struct! { 260 /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`. 261 /// 262 /// *This type is available only if Syn is built with the `"full"` feature.* 263 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 264 pub struct PatTupleStruct { 265 pub attrs: Vec<Attribute>, 266 pub path: Path, 267 pub pat: PatTuple, 268 } 269 } 270 271 ast_struct! { 272 /// A type ascription pattern: `foo: f64`. 273 /// 274 /// *This type is available only if Syn is built with the `"full"` feature.* 275 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 276 pub struct PatType { 277 pub attrs: Vec<Attribute>, 278 pub pat: Box<Pat>, 279 pub colon_token: Token![:], 280 pub ty: Box<Type>, 281 } 282 } 283 284 ast_struct! { 285 /// A pattern that matches any value: `_`. 286 /// 287 /// *This type is available only if Syn is built with the `"full"` feature.* 288 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 289 pub struct PatWild { 290 pub attrs: Vec<Attribute>, 291 pub underscore_token: Token![_], 292 } 293 } 294 295 ast_struct! { 296 /// A single field in a struct pattern. 297 /// 298 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated 299 /// the same as `x: x, y: ref y, z: ref mut z` but there is no colon token. 300 /// 301 /// *This type is available only if Syn is built with the `"full"` feature.* 302 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 303 pub struct FieldPat { 304 pub attrs: Vec<Attribute>, 305 pub member: Member, 306 pub colon_token: Option<Token![:]>, 307 pub pat: Box<Pat>, 308 } 309 } 310 311 #[cfg(feature = "parsing")] 312 pub mod parsing { 313 use super::*; 314 use crate::ext::IdentExt; 315 use crate::parse::{Parse, ParseBuffer, ParseStream, Result}; 316 use crate::path; 317 318 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 319 impl Parse for Pat { parse(input: ParseStream) -> Result<Self>320 fn parse(input: ParseStream) -> Result<Self> { 321 let begin = input.fork(); 322 let lookahead = input.lookahead1(); 323 if { 324 let ahead = input.fork(); 325 ahead.parse::<Option<Ident>>()?.is_some() 326 && (ahead.peek(Token![::]) 327 || ahead.peek(Token![!]) 328 || ahead.peek(token::Brace) 329 || ahead.peek(token::Paren) 330 || ahead.peek(Token![..]) 331 && ahead.parse::<RangeLimits>().is_ok() 332 && !(ahead.is_empty() || ahead.peek(Token![,]))) 333 } || { 334 let ahead = input.fork(); 335 ahead.parse::<Option<Token![self]>>()?.is_some() && ahead.peek(Token![::]) 336 } || lookahead.peek(Token![::]) 337 || lookahead.peek(Token![<]) 338 || input.peek(Token![Self]) 339 || input.peek(Token![super]) 340 || input.peek(Token![crate]) 341 { 342 pat_path_or_macro_or_struct_or_range(input) 343 } else if lookahead.peek(Token![_]) { 344 input.call(pat_wild).map(Pat::Wild) 345 } else if input.peek(Token![box]) { 346 input.call(pat_box).map(Pat::Box) 347 } else if input.peek(Token![-]) || lookahead.peek(Lit) || lookahead.peek(Token![const]) 348 { 349 pat_lit_or_range(input) 350 } else if lookahead.peek(Token![ref]) 351 || lookahead.peek(Token![mut]) 352 || input.peek(Token![self]) 353 || input.peek(Ident) 354 { 355 input.call(pat_ident).map(Pat::Ident) 356 } else if lookahead.peek(Token![&]) { 357 input.call(pat_reference).map(Pat::Reference) 358 } else if lookahead.peek(token::Paren) { 359 input.call(pat_tuple).map(Pat::Tuple) 360 } else if lookahead.peek(token::Bracket) { 361 input.call(pat_slice).map(Pat::Slice) 362 } else if lookahead.peek(Token![..]) && !input.peek(Token![...]) { 363 pat_range_half_open(input, begin) 364 } else if lookahead.peek(Token![const]) { 365 input.call(pat_const).map(Pat::Verbatim) 366 } else { 367 Err(lookahead.error()) 368 } 369 } 370 } 371 pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat>372 fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> { 373 let begin = input.fork(); 374 let (qself, path) = path::parsing::qpath(input, true)?; 375 376 if qself.is_none() && input.peek(Token![!]) && !input.peek(Token![!=]) { 377 let mut contains_arguments = false; 378 for segment in &path.segments { 379 match segment.arguments { 380 PathArguments::None => {} 381 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => { 382 contains_arguments = true; 383 } 384 } 385 } 386 387 if !contains_arguments { 388 let bang_token: Token![!] = input.parse()?; 389 let (delimiter, tokens) = mac::parse_delimiter(input)?; 390 return Ok(Pat::Macro(PatMacro { 391 attrs: Vec::new(), 392 mac: Macro { 393 path, 394 bang_token, 395 delimiter, 396 tokens, 397 }, 398 })); 399 } 400 } 401 402 if input.peek(token::Brace) { 403 let pat = pat_struct(begin.fork(), input, path)?; 404 if qself.is_some() { 405 Ok(Pat::Verbatim(verbatim::between(begin, input))) 406 } else { 407 Ok(pat) 408 } 409 } else if input.peek(token::Paren) { 410 let pat = pat_tuple_struct(input, path)?; 411 if qself.is_some() { 412 Ok(Pat::Verbatim(verbatim::between(begin, input))) 413 } else { 414 Ok(Pat::TupleStruct(pat)) 415 } 416 } else if input.peek(Token![..]) { 417 pat_range(input, begin, qself, path) 418 } else { 419 Ok(Pat::Path(PatPath { 420 attrs: Vec::new(), 421 qself, 422 path, 423 })) 424 } 425 } 426 pat_wild(input: ParseStream) -> Result<PatWild>427 fn pat_wild(input: ParseStream) -> Result<PatWild> { 428 Ok(PatWild { 429 attrs: Vec::new(), 430 underscore_token: input.parse()?, 431 }) 432 } 433 pat_box(input: ParseStream) -> Result<PatBox>434 fn pat_box(input: ParseStream) -> Result<PatBox> { 435 Ok(PatBox { 436 attrs: Vec::new(), 437 box_token: input.parse()?, 438 pat: input.parse()?, 439 }) 440 } 441 pat_ident(input: ParseStream) -> Result<PatIdent>442 fn pat_ident(input: ParseStream) -> Result<PatIdent> { 443 Ok(PatIdent { 444 attrs: Vec::new(), 445 by_ref: input.parse()?, 446 mutability: input.parse()?, 447 ident: input.call(Ident::parse_any)?, 448 subpat: { 449 if input.peek(Token![@]) { 450 let at_token: Token![@] = input.parse()?; 451 let subpat: Pat = input.parse()?; 452 Some((at_token, Box::new(subpat))) 453 } else { 454 None 455 } 456 }, 457 }) 458 } 459 pat_tuple_struct(input: ParseStream, path: Path) -> Result<PatTupleStruct>460 fn pat_tuple_struct(input: ParseStream, path: Path) -> Result<PatTupleStruct> { 461 Ok(PatTupleStruct { 462 attrs: Vec::new(), 463 path, 464 pat: input.call(pat_tuple)?, 465 }) 466 } 467 pat_struct(begin: ParseBuffer, input: ParseStream, path: Path) -> Result<Pat>468 fn pat_struct(begin: ParseBuffer, input: ParseStream, path: Path) -> Result<Pat> { 469 let content; 470 let brace_token = braced!(content in input); 471 472 let mut fields = Punctuated::new(); 473 let mut dot2_token = None; 474 while !content.is_empty() { 475 let attrs = content.call(Attribute::parse_outer)?; 476 if content.peek(Token![..]) { 477 dot2_token = Some(content.parse()?); 478 if !attrs.is_empty() { 479 return Ok(Pat::Verbatim(verbatim::between(begin, input))); 480 } 481 break; 482 } 483 let mut value = content.call(field_pat)?; 484 value.attrs = attrs; 485 fields.push_value(value); 486 if content.is_empty() { 487 break; 488 } 489 let punct: Token![,] = content.parse()?; 490 fields.push_punct(punct); 491 } 492 493 Ok(Pat::Struct(PatStruct { 494 attrs: Vec::new(), 495 path, 496 brace_token, 497 fields, 498 dot2_token, 499 })) 500 } 501 502 impl Member { is_unnamed(&self) -> bool503 fn is_unnamed(&self) -> bool { 504 match *self { 505 Member::Named(_) => false, 506 Member::Unnamed(_) => true, 507 } 508 } 509 } 510 field_pat(input: ParseStream) -> Result<FieldPat>511 fn field_pat(input: ParseStream) -> Result<FieldPat> { 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: Vec::new(), 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: Vec::new(), 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 path::printing::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 self.limits.to_tokens(tokens); 885 self.hi.to_tokens(tokens); 886 } 887 } 888 889 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 890 impl ToTokens for PatSlice { to_tokens(&self, tokens: &mut TokenStream)891 fn to_tokens(&self, tokens: &mut TokenStream) { 892 tokens.append_all(self.attrs.outer()); 893 self.bracket_token.surround(tokens, |tokens| { 894 self.elems.to_tokens(tokens); 895 }); 896 } 897 } 898 899 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 900 impl ToTokens for PatMacro { to_tokens(&self, tokens: &mut TokenStream)901 fn to_tokens(&self, tokens: &mut TokenStream) { 902 tokens.append_all(self.attrs.outer()); 903 self.mac.to_tokens(tokens); 904 } 905 } 906 907 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 908 impl ToTokens for PatOr { to_tokens(&self, tokens: &mut TokenStream)909 fn to_tokens(&self, tokens: &mut TokenStream) { 910 tokens.append_all(self.attrs.outer()); 911 self.leading_vert.to_tokens(tokens); 912 self.cases.to_tokens(tokens); 913 } 914 } 915 916 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 917 impl ToTokens for FieldPat { to_tokens(&self, tokens: &mut TokenStream)918 fn to_tokens(&self, tokens: &mut TokenStream) { 919 tokens.append_all(self.attrs.outer()); 920 if let Some(colon_token) = &self.colon_token { 921 self.member.to_tokens(tokens); 922 colon_token.to_tokens(tokens); 923 } 924 self.pat.to_tokens(tokens); 925 } 926 } 927 } 928