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