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