1 use super::*; 2 use crate::punctuated::Punctuated; 3 use proc_macro2::{Span, TokenStream}; 4 #[cfg(feature = "printing")] 5 use quote::IdentFragment; 6 #[cfg(feature = "printing")] 7 use std::fmt::{self, Display}; 8 use std::hash::{Hash, Hasher}; 9 #[cfg(feature = "parsing")] 10 use std::mem; 11 12 ast_enum_of_structs! { 13 /// A Rust expression. 14 /// 15 /// *This type is available only if Syn is built with the `"derive"` or `"full"` 16 /// feature, but most of the variants are not available unless "full" is enabled.* 17 /// 18 /// # Syntax tree enums 19 /// 20 /// This type is a syntax tree enum. In Syn this and other syntax tree enums 21 /// are designed to be traversed using the following rebinding idiom. 22 /// 23 /// ``` 24 /// # use syn::Expr; 25 /// # 26 /// # fn example(expr: Expr) { 27 /// # const IGNORE: &str = stringify! { 28 /// let expr: Expr = /* ... */; 29 /// # }; 30 /// match expr { 31 /// Expr::MethodCall(expr) => { 32 /// /* ... */ 33 /// } 34 /// Expr::Cast(expr) => { 35 /// /* ... */ 36 /// } 37 /// Expr::If(expr) => { 38 /// /* ... */ 39 /// } 40 /// 41 /// /* ... */ 42 /// # _ => {} 43 /// # } 44 /// # } 45 /// ``` 46 /// 47 /// We begin with a variable `expr` of type `Expr` that has no fields 48 /// (because it is an enum), and by matching on it and rebinding a variable 49 /// with the same name `expr` we effectively imbue our variable with all of 50 /// the data fields provided by the variant that it turned out to be. So for 51 /// example above if we ended up in the `MethodCall` case then we get to use 52 /// `expr.receiver`, `expr.args` etc; if we ended up in the `If` case we get 53 /// to use `expr.cond`, `expr.then_branch`, `expr.else_branch`. 54 /// 55 /// This approach avoids repeating the variant names twice on every line. 56 /// 57 /// ``` 58 /// # use syn::{Expr, ExprMethodCall}; 59 /// # 60 /// # fn example(expr: Expr) { 61 /// // Repetitive; recommend not doing this. 62 /// match expr { 63 /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => { 64 /// # } 65 /// # _ => {} 66 /// # } 67 /// # } 68 /// ``` 69 /// 70 /// In general, the name to which a syntax tree enum variant is bound should 71 /// be a suitable name for the complete syntax tree enum type. 72 /// 73 /// ``` 74 /// # use syn::{Expr, ExprField}; 75 /// # 76 /// # fn example(discriminant: ExprField) { 77 /// // Binding is called `base` which is the name I would use if I were 78 /// // assigning `*discriminant.base` without an `if let`. 79 /// if let Expr::Tuple(base) = *discriminant.base { 80 /// # } 81 /// # } 82 /// ``` 83 /// 84 /// A sign that you may not be choosing the right variable names is if you 85 /// see names getting repeated in your code, like accessing 86 /// `receiver.receiver` or `pat.pat` or `cond.cond`. 87 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 88 #[non_exhaustive] 89 pub enum Expr { 90 /// A slice literal expression: `[a, b, c, d]`. 91 Array(ExprArray), 92 93 /// An assignment expression: `a = compute()`. 94 Assign(ExprAssign), 95 96 /// An async block: `async { ... }`. 97 Async(ExprAsync), 98 99 /// An await expression: `fut.await`. 100 Await(ExprAwait), 101 102 /// A binary operation: `a + b`, `a += b`. 103 Binary(ExprBinary), 104 105 /// A blocked scope: `{ ... }`. 106 Block(ExprBlock), 107 108 /// A `break`, with an optional label to break and an optional 109 /// expression. 110 Break(ExprBreak), 111 112 /// A function call expression: `invoke(a, b)`. 113 Call(ExprCall), 114 115 /// A cast expression: `foo as f64`. 116 Cast(ExprCast), 117 118 /// A closure expression: `|a, b| a + b`. 119 Closure(ExprClosure), 120 121 /// A const block: `const { ... }`. 122 Const(ExprConst), 123 124 /// A `continue`, with an optional label. 125 Continue(ExprContinue), 126 127 /// Access of a named struct field (`obj.k`) or unnamed tuple struct 128 /// field (`obj.0`). 129 Field(ExprField), 130 131 /// A for loop: `for pat in expr { ... }`. 132 ForLoop(ExprForLoop), 133 134 /// An expression contained within invisible delimiters. 135 /// 136 /// This variant is important for faithfully representing the precedence 137 /// of expressions and is related to `None`-delimited spans in a 138 /// `TokenStream`. 139 Group(ExprGroup), 140 141 /// An `if` expression with an optional `else` block: `if expr { ... } 142 /// else { ... }`. 143 /// 144 /// The `else` branch expression may only be an `If` or `Block` 145 /// expression, not any of the other types of expression. 146 If(ExprIf), 147 148 /// A square bracketed indexing expression: `vector[2]`. 149 Index(ExprIndex), 150 151 /// The inferred value of a const generic argument, denoted `_`. 152 Infer(ExprInfer), 153 154 /// A `let` guard: `let Some(x) = opt`. 155 Let(ExprLet), 156 157 /// A literal in place of an expression: `1`, `"foo"`. 158 Lit(ExprLit), 159 160 /// Conditionless loop: `loop { ... }`. 161 Loop(ExprLoop), 162 163 /// A macro invocation expression: `format!("{}", q)`. 164 Macro(ExprMacro), 165 166 /// A `match` expression: `match n { Some(n) => {}, None => {} }`. 167 Match(ExprMatch), 168 169 /// A method call expression: `x.foo::<T>(a, b)`. 170 MethodCall(ExprMethodCall), 171 172 /// A parenthesized expression: `(a + b)`. 173 Paren(ExprParen), 174 175 /// A path like `std::mem::replace` possibly containing generic 176 /// parameters and a qualified self-type. 177 /// 178 /// A plain identifier like `x` is a path of length 1. 179 Path(ExprPath), 180 181 /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`. 182 Range(ExprRange), 183 184 /// A referencing operation: `&a` or `&mut a`. 185 Reference(ExprReference), 186 187 /// An array literal constructed from one repeated element: `[0u8; N]`. 188 Repeat(ExprRepeat), 189 190 /// A `return`, with an optional value to be returned. 191 Return(ExprReturn), 192 193 /// A struct literal expression: `Point { x: 1, y: 1 }`. 194 /// 195 /// The `rest` provides the value of the remaining fields as in `S { a: 196 /// 1, b: 1, ..rest }`. 197 Struct(ExprStruct), 198 199 /// A try-expression: `expr?`. 200 Try(ExprTry), 201 202 /// A try block: `try { ... }`. 203 TryBlock(ExprTryBlock), 204 205 /// A tuple expression: `(a, b, c, d)`. 206 Tuple(ExprTuple), 207 208 /// A unary operation: `!x`, `*x`. 209 Unary(ExprUnary), 210 211 /// An unsafe block: `unsafe { ... }`. 212 Unsafe(ExprUnsafe), 213 214 /// Tokens in expression position not interpreted by Syn. 215 Verbatim(TokenStream), 216 217 /// A while loop: `while expr { ... }`. 218 While(ExprWhile), 219 220 /// A yield expression: `yield expr`. 221 Yield(ExprYield), 222 223 // For testing exhaustiveness in downstream code, use the following idiom: 224 // 225 // match expr { 226 // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))] 227 // 228 // Expr::Array(expr) => {...} 229 // Expr::Assign(expr) => {...} 230 // ... 231 // Expr::Yield(expr) => {...} 232 // 233 // _ => { /* some sane fallback */ } 234 // } 235 // 236 // This way we fail your tests but don't break your library when adding 237 // a variant. You will be notified by a test failure when a variant is 238 // added, so that you can add code to handle it, but your library will 239 // continue to compile and work for downstream users in the interim. 240 } 241 } 242 243 ast_struct! { 244 /// A slice literal expression: `[a, b, c, d]`. 245 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 246 pub struct ExprArray #full { 247 pub attrs: Vec<Attribute>, 248 pub bracket_token: token::Bracket, 249 pub elems: Punctuated<Expr, Token![,]>, 250 } 251 } 252 253 ast_struct! { 254 /// An assignment expression: `a = compute()`. 255 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 256 pub struct ExprAssign #full { 257 pub attrs: Vec<Attribute>, 258 pub left: Box<Expr>, 259 pub eq_token: Token![=], 260 pub right: Box<Expr>, 261 } 262 } 263 264 ast_struct! { 265 /// An async block: `async { ... }`. 266 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 267 pub struct ExprAsync #full { 268 pub attrs: Vec<Attribute>, 269 pub async_token: Token![async], 270 pub capture: Option<Token![move]>, 271 pub block: Block, 272 } 273 } 274 275 ast_struct! { 276 /// An await expression: `fut.await`. 277 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 278 pub struct ExprAwait #full { 279 pub attrs: Vec<Attribute>, 280 pub base: Box<Expr>, 281 pub dot_token: Token![.], 282 pub await_token: Token![await], 283 } 284 } 285 286 ast_struct! { 287 /// A binary operation: `a + b`, `a += b`. 288 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 289 pub struct ExprBinary { 290 pub attrs: Vec<Attribute>, 291 pub left: Box<Expr>, 292 pub op: BinOp, 293 pub right: Box<Expr>, 294 } 295 } 296 297 ast_struct! { 298 /// A blocked scope: `{ ... }`. 299 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 300 pub struct ExprBlock #full { 301 pub attrs: Vec<Attribute>, 302 pub label: Option<Label>, 303 pub block: Block, 304 } 305 } 306 307 ast_struct! { 308 /// A `break`, with an optional label to break and an optional 309 /// expression. 310 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 311 pub struct ExprBreak #full { 312 pub attrs: Vec<Attribute>, 313 pub break_token: Token![break], 314 pub label: Option<Lifetime>, 315 pub expr: Option<Box<Expr>>, 316 } 317 } 318 319 ast_struct! { 320 /// A function call expression: `invoke(a, b)`. 321 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 322 pub struct ExprCall { 323 pub attrs: Vec<Attribute>, 324 pub func: Box<Expr>, 325 pub paren_token: token::Paren, 326 pub args: Punctuated<Expr, Token![,]>, 327 } 328 } 329 330 ast_struct! { 331 /// A cast expression: `foo as f64`. 332 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 333 pub struct ExprCast { 334 pub attrs: Vec<Attribute>, 335 pub expr: Box<Expr>, 336 pub as_token: Token![as], 337 pub ty: Box<Type>, 338 } 339 } 340 341 ast_struct! { 342 /// A closure expression: `|a, b| a + b`. 343 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 344 pub struct ExprClosure #full { 345 pub attrs: Vec<Attribute>, 346 pub lifetimes: Option<BoundLifetimes>, 347 pub constness: Option<Token![const]>, 348 pub movability: Option<Token![static]>, 349 pub asyncness: Option<Token![async]>, 350 pub capture: Option<Token![move]>, 351 pub or1_token: Token![|], 352 pub inputs: Punctuated<Pat, Token![,]>, 353 pub or2_token: Token![|], 354 pub output: ReturnType, 355 pub body: Box<Expr>, 356 } 357 } 358 359 ast_struct! { 360 /// A const block: `const { ... }`. 361 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 362 pub struct ExprConst #full { 363 pub attrs: Vec<Attribute>, 364 pub const_token: Token![const], 365 pub block: Block, 366 } 367 } 368 369 ast_struct! { 370 /// A `continue`, with an optional label. 371 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 372 pub struct ExprContinue #full { 373 pub attrs: Vec<Attribute>, 374 pub continue_token: Token![continue], 375 pub label: Option<Lifetime>, 376 } 377 } 378 379 ast_struct! { 380 /// Access of a named struct field (`obj.k`) or unnamed tuple struct 381 /// field (`obj.0`). 382 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 383 pub struct ExprField { 384 pub attrs: Vec<Attribute>, 385 pub base: Box<Expr>, 386 pub dot_token: Token![.], 387 pub member: Member, 388 } 389 } 390 391 ast_struct! { 392 /// A for loop: `for pat in expr { ... }`. 393 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 394 pub struct ExprForLoop #full { 395 pub attrs: Vec<Attribute>, 396 pub label: Option<Label>, 397 pub for_token: Token![for], 398 pub pat: Box<Pat>, 399 pub in_token: Token![in], 400 pub expr: Box<Expr>, 401 pub body: Block, 402 } 403 } 404 405 ast_struct! { 406 /// An expression contained within invisible delimiters. 407 /// 408 /// This variant is important for faithfully representing the precedence 409 /// of expressions and is related to `None`-delimited spans in a 410 /// `TokenStream`. 411 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 412 pub struct ExprGroup { 413 pub attrs: Vec<Attribute>, 414 pub group_token: token::Group, 415 pub expr: Box<Expr>, 416 } 417 } 418 419 ast_struct! { 420 /// An `if` expression with an optional `else` block: `if expr { ... } 421 /// else { ... }`. 422 /// 423 /// The `else` branch expression may only be an `If` or `Block` 424 /// expression, not any of the other types of expression. 425 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 426 pub struct ExprIf #full { 427 pub attrs: Vec<Attribute>, 428 pub if_token: Token![if], 429 pub cond: Box<Expr>, 430 pub then_branch: Block, 431 pub else_branch: Option<(Token![else], Box<Expr>)>, 432 } 433 } 434 435 ast_struct! { 436 /// A square bracketed indexing expression: `vector[2]`. 437 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 438 pub struct ExprIndex { 439 pub attrs: Vec<Attribute>, 440 pub expr: Box<Expr>, 441 pub bracket_token: token::Bracket, 442 pub index: Box<Expr>, 443 } 444 } 445 446 ast_struct! { 447 /// The inferred value of a const generic argument, denoted `_`. 448 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 449 pub struct ExprInfer #full { 450 pub attrs: Vec<Attribute>, 451 pub underscore_token: Token![_], 452 } 453 } 454 455 ast_struct! { 456 /// A `let` guard: `let Some(x) = opt`. 457 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 458 pub struct ExprLet #full { 459 pub attrs: Vec<Attribute>, 460 pub let_token: Token![let], 461 pub pat: Box<Pat>, 462 pub eq_token: Token![=], 463 pub expr: Box<Expr>, 464 } 465 } 466 467 ast_struct! { 468 /// A literal in place of an expression: `1`, `"foo"`. 469 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 470 pub struct ExprLit { 471 pub attrs: Vec<Attribute>, 472 pub lit: Lit, 473 } 474 } 475 476 ast_struct! { 477 /// Conditionless loop: `loop { ... }`. 478 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 479 pub struct ExprLoop #full { 480 pub attrs: Vec<Attribute>, 481 pub label: Option<Label>, 482 pub loop_token: Token![loop], 483 pub body: Block, 484 } 485 } 486 487 ast_struct! { 488 /// A macro invocation expression: `format!("{}", q)`. 489 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 490 pub struct ExprMacro { 491 pub attrs: Vec<Attribute>, 492 pub mac: Macro, 493 } 494 } 495 496 ast_struct! { 497 /// A `match` expression: `match n { Some(n) => {}, None => {} }`. 498 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 499 pub struct ExprMatch #full { 500 pub attrs: Vec<Attribute>, 501 pub match_token: Token![match], 502 pub expr: Box<Expr>, 503 pub brace_token: token::Brace, 504 pub arms: Vec<Arm>, 505 } 506 } 507 508 ast_struct! { 509 /// A method call expression: `x.foo::<T>(a, b)`. 510 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 511 pub struct ExprMethodCall { 512 pub attrs: Vec<Attribute>, 513 pub receiver: Box<Expr>, 514 pub dot_token: Token![.], 515 pub method: Ident, 516 pub turbofish: Option<AngleBracketedGenericArguments>, 517 pub paren_token: token::Paren, 518 pub args: Punctuated<Expr, Token![,]>, 519 } 520 } 521 522 ast_struct! { 523 /// A parenthesized expression: `(a + b)`. 524 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 525 pub struct ExprParen { 526 pub attrs: Vec<Attribute>, 527 pub paren_token: token::Paren, 528 pub expr: Box<Expr>, 529 } 530 } 531 532 ast_struct! { 533 /// A path like `std::mem::replace` possibly containing generic 534 /// parameters and a qualified self-type. 535 /// 536 /// A plain identifier like `x` is a path of length 1. 537 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 538 pub struct ExprPath { 539 pub attrs: Vec<Attribute>, 540 pub qself: Option<QSelf>, 541 pub path: Path, 542 } 543 } 544 545 ast_struct! { 546 /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`. 547 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 548 pub struct ExprRange #full { 549 pub attrs: Vec<Attribute>, 550 pub start: Option<Box<Expr>>, 551 pub limits: RangeLimits, 552 pub end: Option<Box<Expr>>, 553 } 554 } 555 556 ast_struct! { 557 /// A referencing operation: `&a` or `&mut a`. 558 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 559 pub struct ExprReference { 560 pub attrs: Vec<Attribute>, 561 pub and_token: Token![&], 562 pub mutability: Option<Token![mut]>, 563 pub expr: Box<Expr>, 564 } 565 } 566 567 ast_struct! { 568 /// An array literal constructed from one repeated element: `[0u8; N]`. 569 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 570 pub struct ExprRepeat #full { 571 pub attrs: Vec<Attribute>, 572 pub bracket_token: token::Bracket, 573 pub expr: Box<Expr>, 574 pub semi_token: Token![;], 575 pub len: Box<Expr>, 576 } 577 } 578 579 ast_struct! { 580 /// A `return`, with an optional value to be returned. 581 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 582 pub struct ExprReturn #full { 583 pub attrs: Vec<Attribute>, 584 pub return_token: Token![return], 585 pub expr: Option<Box<Expr>>, 586 } 587 } 588 589 ast_struct! { 590 /// A struct literal expression: `Point { x: 1, y: 1 }`. 591 /// 592 /// The `rest` provides the value of the remaining fields as in `S { a: 593 /// 1, b: 1, ..rest }`. 594 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 595 pub struct ExprStruct { 596 pub attrs: Vec<Attribute>, 597 pub qself: Option<QSelf>, 598 pub path: Path, 599 pub brace_token: token::Brace, 600 pub fields: Punctuated<FieldValue, Token![,]>, 601 pub dot2_token: Option<Token![..]>, 602 pub rest: Option<Box<Expr>>, 603 } 604 } 605 606 ast_struct! { 607 /// A try-expression: `expr?`. 608 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 609 pub struct ExprTry #full { 610 pub attrs: Vec<Attribute>, 611 pub expr: Box<Expr>, 612 pub question_token: Token![?], 613 } 614 } 615 616 ast_struct! { 617 /// A try block: `try { ... }`. 618 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 619 pub struct ExprTryBlock #full { 620 pub attrs: Vec<Attribute>, 621 pub try_token: Token![try], 622 pub block: Block, 623 } 624 } 625 626 ast_struct! { 627 /// A tuple expression: `(a, b, c, d)`. 628 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 629 pub struct ExprTuple #full { 630 pub attrs: Vec<Attribute>, 631 pub paren_token: token::Paren, 632 pub elems: Punctuated<Expr, Token![,]>, 633 } 634 } 635 636 ast_struct! { 637 /// A unary operation: `!x`, `*x`. 638 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 639 pub struct ExprUnary { 640 pub attrs: Vec<Attribute>, 641 pub op: UnOp, 642 pub expr: Box<Expr>, 643 } 644 } 645 646 ast_struct! { 647 /// An unsafe block: `unsafe { ... }`. 648 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 649 pub struct ExprUnsafe #full { 650 pub attrs: Vec<Attribute>, 651 pub unsafe_token: Token![unsafe], 652 pub block: Block, 653 } 654 } 655 656 ast_struct! { 657 /// A while loop: `while expr { ... }`. 658 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 659 pub struct ExprWhile #full { 660 pub attrs: Vec<Attribute>, 661 pub label: Option<Label>, 662 pub while_token: Token![while], 663 pub cond: Box<Expr>, 664 pub body: Block, 665 } 666 } 667 668 ast_struct! { 669 /// A yield expression: `yield expr`. 670 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 671 pub struct ExprYield #full { 672 pub attrs: Vec<Attribute>, 673 pub yield_token: Token![yield], 674 pub expr: Option<Box<Expr>>, 675 } 676 } 677 678 impl Expr { 679 #[cfg(feature = "parsing")] 680 const DUMMY: Self = Expr::Path(ExprPath { 681 attrs: Vec::new(), 682 qself: None, 683 path: Path { 684 leading_colon: None, 685 segments: Punctuated::new(), 686 }, 687 }); 688 689 #[cfg(all(feature = "parsing", feature = "full"))] 690 pub(crate) fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> { 691 match self { 692 Expr::Array(ExprArray { attrs, .. }) 693 | Expr::Assign(ExprAssign { attrs, .. }) 694 | Expr::Async(ExprAsync { attrs, .. }) 695 | Expr::Await(ExprAwait { attrs, .. }) 696 | Expr::Binary(ExprBinary { attrs, .. }) 697 | Expr::Block(ExprBlock { attrs, .. }) 698 | Expr::Break(ExprBreak { attrs, .. }) 699 | Expr::Call(ExprCall { attrs, .. }) 700 | Expr::Cast(ExprCast { attrs, .. }) 701 | Expr::Closure(ExprClosure { attrs, .. }) 702 | Expr::Const(ExprConst { attrs, .. }) 703 | Expr::Continue(ExprContinue { attrs, .. }) 704 | Expr::Field(ExprField { attrs, .. }) 705 | Expr::ForLoop(ExprForLoop { attrs, .. }) 706 | Expr::Group(ExprGroup { attrs, .. }) 707 | Expr::If(ExprIf { attrs, .. }) 708 | Expr::Index(ExprIndex { attrs, .. }) 709 | Expr::Infer(ExprInfer { attrs, .. }) 710 | Expr::Let(ExprLet { attrs, .. }) 711 | Expr::Lit(ExprLit { attrs, .. }) 712 | Expr::Loop(ExprLoop { attrs, .. }) 713 | Expr::Macro(ExprMacro { attrs, .. }) 714 | Expr::Match(ExprMatch { attrs, .. }) 715 | Expr::MethodCall(ExprMethodCall { attrs, .. }) 716 | Expr::Paren(ExprParen { attrs, .. }) 717 | Expr::Path(ExprPath { attrs, .. }) 718 | Expr::Range(ExprRange { attrs, .. }) 719 | Expr::Reference(ExprReference { attrs, .. }) 720 | Expr::Repeat(ExprRepeat { attrs, .. }) 721 | Expr::Return(ExprReturn { attrs, .. }) 722 | Expr::Struct(ExprStruct { attrs, .. }) 723 | Expr::Try(ExprTry { attrs, .. }) 724 | Expr::TryBlock(ExprTryBlock { attrs, .. }) 725 | Expr::Tuple(ExprTuple { attrs, .. }) 726 | Expr::Unary(ExprUnary { attrs, .. }) 727 | Expr::Unsafe(ExprUnsafe { attrs, .. }) 728 | Expr::While(ExprWhile { attrs, .. }) 729 | Expr::Yield(ExprYield { attrs, .. }) => mem::replace(attrs, new), 730 Expr::Verbatim(_) => Vec::new(), 731 } 732 } 733 } 734 735 ast_enum! { 736 /// A struct or tuple struct field accessed in a struct literal or field 737 /// expression. 738 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 739 pub enum Member { 740 /// A named field like `self.x`. 741 Named(Ident), 742 /// An unnamed field like `self.0`. 743 Unnamed(Index), 744 } 745 } 746 747 impl From<Ident> for Member { fromnull748 fn from(ident: Ident) -> Member { 749 Member::Named(ident) 750 } 751 } 752 753 impl From<Index> for Member { fromnull754 fn from(index: Index) -> Member { 755 Member::Unnamed(index) 756 } 757 } 758 759 impl From<usize> for Member { fromnull760 fn from(index: usize) -> Member { 761 Member::Unnamed(Index::from(index)) 762 } 763 } 764 765 impl Eq for Member {} 766 767 impl PartialEq for Member { eqnull768 fn eq(&self, other: &Self) -> bool { 769 match (self, other) { 770 (Member::Named(this), Member::Named(other)) => this == other, 771 (Member::Unnamed(this), Member::Unnamed(other)) => this == other, 772 _ => false, 773 } 774 } 775 } 776 777 impl Hash for Member { hashnull778 fn hash<H: Hasher>(&self, state: &mut H) { 779 match self { 780 Member::Named(m) => m.hash(state), 781 Member::Unnamed(m) => m.hash(state), 782 } 783 } 784 } 785 786 #[cfg(feature = "printing")] 787 impl IdentFragment for Member { fmtnull788 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 789 match self { 790 Member::Named(m) => Display::fmt(m, formatter), 791 Member::Unnamed(m) => Display::fmt(&m.index, formatter), 792 } 793 } 794 spannull795 fn span(&self) -> Option<Span> { 796 match self { 797 Member::Named(m) => Some(m.span()), 798 Member::Unnamed(m) => Some(m.span), 799 } 800 } 801 } 802 803 ast_struct! { 804 /// The index of an unnamed tuple struct field. 805 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 806 pub struct Index { 807 pub index: u32, 808 pub span: Span, 809 } 810 } 811 812 impl From<usize> for Index { fromnull813 fn from(index: usize) -> Index { 814 assert!(index < u32::max_value() as usize); 815 Index { 816 index: index as u32, 817 span: Span::call_site(), 818 } 819 } 820 } 821 822 impl Eq for Index {} 823 824 impl PartialEq for Index { eqnull825 fn eq(&self, other: &Self) -> bool { 826 self.index == other.index 827 } 828 } 829 830 impl Hash for Index { hashnull831 fn hash<H: Hasher>(&self, state: &mut H) { 832 self.index.hash(state); 833 } 834 } 835 836 #[cfg(feature = "printing")] 837 impl IdentFragment for Index { fmtnull838 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 839 Display::fmt(&self.index, formatter) 840 } 841 spannull842 fn span(&self) -> Option<Span> { 843 Some(self.span) 844 } 845 } 846 847 ast_struct! { 848 /// A field-value pair in a struct literal. 849 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 850 pub struct FieldValue { 851 pub attrs: Vec<Attribute>, 852 pub member: Member, 853 854 /// The colon in `Struct { x: x }`. If written in shorthand like 855 /// `Struct { x }`, there is no colon. 856 pub colon_token: Option<Token![:]>, 857 858 pub expr: Expr, 859 } 860 } 861 862 #[cfg(feature = "full")] 863 ast_struct! { 864 /// A lifetime labeling a `for`, `while`, or `loop`. 865 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 866 pub struct Label { 867 pub name: Lifetime, 868 pub colon_token: Token![:], 869 } 870 } 871 872 #[cfg(feature = "full")] 873 ast_struct! { 874 /// One arm of a `match` expression: `0..=10 => { return true; }`. 875 /// 876 /// As in: 877 /// 878 /// ``` 879 /// # fn f() -> bool { 880 /// # let n = 0; 881 /// match n { 882 /// 0..=10 => { 883 /// return true; 884 /// } 885 /// // ... 886 /// # _ => {} 887 /// } 888 /// # false 889 /// # } 890 /// ``` 891 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 892 pub struct Arm { 893 pub attrs: Vec<Attribute>, 894 pub pat: Pat, 895 pub guard: Option<(Token![if], Box<Expr>)>, 896 pub fat_arrow_token: Token![=>], 897 pub body: Box<Expr>, 898 pub comma: Option<Token![,]>, 899 } 900 } 901 902 #[cfg(feature = "full")] 903 ast_enum! { 904 /// Limit types of a range, inclusive or exclusive. 905 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))] 906 pub enum RangeLimits { 907 /// Inclusive at the beginning, exclusive at the end. 908 HalfOpen(Token![..]), 909 /// Inclusive at the beginning and end. 910 Closed(Token![..=]), 911 } 912 } 913 914 #[cfg(any(feature = "parsing", feature = "printing"))] 915 #[cfg(feature = "full")] 916 pub(crate) fn requires_terminator(expr: &Expr) -> bool { 917 // see https://github.com/rust-lang/rust/blob/9a19e7604/compiler/rustc_ast/src/util/classify.rs#L7-L26 918 match expr { 919 Expr::If(_) 920 | Expr::Match(_) 921 | Expr::Block(_) | Expr::Unsafe(_) // both under ExprKind::Block in rustc 922 | Expr::While(_) 923 | Expr::Loop(_) 924 | Expr::ForLoop(_) 925 | Expr::TryBlock(_) 926 | Expr::Const(_) => false, 927 Expr::Array(_) 928 | Expr::Assign(_) 929 | Expr::Async(_) 930 | Expr::Await(_) 931 | Expr::Binary(_) 932 | Expr::Break(_) 933 | Expr::Call(_) 934 | Expr::Cast(_) 935 | Expr::Closure(_) 936 | Expr::Continue(_) 937 | Expr::Field(_) 938 | Expr::Group(_) 939 | Expr::Index(_) 940 | Expr::Infer(_) 941 | Expr::Let(_) 942 | Expr::Lit(_) 943 | Expr::Macro(_) 944 | Expr::MethodCall(_) 945 | Expr::Paren(_) 946 | Expr::Path(_) 947 | Expr::Range(_) 948 | Expr::Reference(_) 949 | Expr::Repeat(_) 950 | Expr::Return(_) 951 | Expr::Struct(_) 952 | Expr::Try(_) 953 | Expr::Tuple(_) 954 | Expr::Unary(_) 955 | Expr::Yield(_) 956 | Expr::Verbatim(_) => true 957 } 958 } 959 960 #[cfg(feature = "parsing")] 961 mod precedence { 962 use super::BinOp; 963 964 pub(crate) enum Precedence { 965 Any, 966 Assign, 967 Range, 968 Or, 969 And, 970 Compare, 971 BitOr, 972 BitXor, 973 BitAnd, 974 Shift, 975 Arithmetic, 976 Term, 977 Cast, 978 } 979 980 impl Precedence { 981 pub(crate) fn of(op: &BinOp) -> Self { 982 match op { 983 BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic, 984 BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term, 985 BinOp::And(_) => Precedence::And, 986 BinOp::Or(_) => Precedence::Or, 987 BinOp::BitXor(_) => Precedence::BitXor, 988 BinOp::BitAnd(_) => Precedence::BitAnd, 989 BinOp::BitOr(_) => Precedence::BitOr, 990 BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift, 991 BinOp::Eq(_) 992 | BinOp::Lt(_) 993 | BinOp::Le(_) 994 | BinOp::Ne(_) 995 | BinOp::Ge(_) 996 | BinOp::Gt(_) => Precedence::Compare, 997 BinOp::AddAssign(_) 998 | BinOp::SubAssign(_) 999 | BinOp::MulAssign(_) 1000 | BinOp::DivAssign(_) 1001 | BinOp::RemAssign(_) 1002 | BinOp::BitXorAssign(_) 1003 | BinOp::BitAndAssign(_) 1004 | BinOp::BitOrAssign(_) 1005 | BinOp::ShlAssign(_) 1006 | BinOp::ShrAssign(_) => Precedence::Assign, 1007 } 1008 } 1009 } 1010 } 1011 1012 #[cfg(feature = "parsing")] 1013 pub(crate) mod parsing { 1014 use super::precedence::Precedence; 1015 use super::*; 1016 #[cfg(feature = "full")] 1017 use crate::ext::IdentExt as _; 1018 use crate::parse::discouraged::Speculative as _; 1019 #[cfg(feature = "full")] 1020 use crate::parse::ParseBuffer; 1021 use crate::parse::{Parse, ParseStream, Result}; 1022 use crate::path; 1023 use std::cmp::Ordering; 1024 1025 mod kw { 1026 crate::custom_keyword!(builtin); 1027 crate::custom_keyword!(raw); 1028 } 1029 1030 // When we're parsing expressions which occur before blocks, like in an if 1031 // statement's condition, we cannot parse a struct literal. 1032 // 1033 // Struct literals are ambiguous in certain positions 1034 // https://github.com/rust-lang/rfcs/pull/92 1035 #[cfg(feature = "full")] 1036 pub(crate) struct AllowStruct(bool); 1037 1038 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 1039 impl Parse for Expr { parsenull1040 fn parse(input: ParseStream) -> Result<Self> { 1041 ambiguous_expr( 1042 input, 1043 #[cfg(feature = "full")] 1044 AllowStruct(true), 1045 ) 1046 } 1047 } 1048 1049 impl Expr { 1050 /// An alternative to the primary `Expr::parse` parser (from the 1051 /// [`Parse`] trait) for ambiguous syntactic positions in which a 1052 /// trailing brace should not be taken as part of the expression. 1053 /// 1054 /// Rust grammar has an ambiguity where braces sometimes turn a path 1055 /// expression into a struct initialization and sometimes do not. In the 1056 /// following code, the expression `S {}` is one expression. Presumably 1057 /// there is an empty struct `struct S {}` defined somewhere which it is 1058 /// instantiating. 1059 /// 1060 /// ``` 1061 /// # struct S; 1062 /// # impl std::ops::Deref for S { 1063 /// # type Target = bool; 1064 /// # fn deref(&self) -> &Self::Target { 1065 /// # &true 1066 /// # } 1067 /// # } 1068 /// let _ = *S {}; 1069 /// 1070 /// // parsed by rustc as: `*(S {})` 1071 /// ``` 1072 /// 1073 /// We would want to parse the above using `Expr::parse` after the `=` 1074 /// token. 1075 /// 1076 /// But in the following, `S {}` is *not* a struct init expression. 1077 /// 1078 /// ``` 1079 /// # const S: &bool = &true; 1080 /// if *S {} {} 1081 /// 1082 /// // parsed by rustc as: 1083 /// // 1084 /// // if (*S) { 1085 /// // /* empty block */ 1086 /// // } 1087 /// // { 1088 /// // /* another empty block */ 1089 /// // } 1090 /// ``` 1091 /// 1092 /// For that reason we would want to parse if-conditions using 1093 /// `Expr::parse_without_eager_brace` after the `if` token. Same for 1094 /// similar syntactic positions such as the condition expr after a 1095 /// `while` token or the expr at the top of a `match`. 1096 /// 1097 /// The Rust grammar's choices around which way this ambiguity is 1098 /// resolved at various syntactic positions is fairly arbitrary. Really 1099 /// either parse behavior could work in most positions, and language 1100 /// designers just decide each case based on which is more likely to be 1101 /// what the programmer had in mind most of the time. 1102 /// 1103 /// ``` 1104 /// # struct S; 1105 /// # fn doc() -> S { 1106 /// if return S {} {} 1107 /// # unreachable!() 1108 /// # } 1109 /// 1110 /// // parsed by rustc as: 1111 /// // 1112 /// // if (return (S {})) { 1113 /// // } 1114 /// // 1115 /// // but could equally well have been this other arbitrary choice: 1116 /// // 1117 /// // if (return S) { 1118 /// // } 1119 /// // {} 1120 /// ``` 1121 /// 1122 /// Note the grammar ambiguity on trailing braces is distinct from 1123 /// precedence and is not captured by assigning a precedence level to 1124 /// the braced struct init expr in relation to other operators. This can 1125 /// be illustrated by `return 0..S {}` vs `match 0..S {}`. The former 1126 /// parses as `return (0..(S {}))` implying tighter precedence for 1127 /// struct init than `..`, while the latter parses as `match (0..S) {}` 1128 /// implying tighter precedence for `..` than struct init, a 1129 /// contradiction. 1130 #[cfg(feature = "full")] 1131 #[cfg_attr(doc_cfg, doc(cfg(all(feature = "full", feature = "parsing"))))] parse_without_eager_bracenull1132 pub fn parse_without_eager_brace(input: ParseStream) -> Result<Expr> { 1133 ambiguous_expr(input, AllowStruct(false)) 1134 } 1135 } 1136 1137 #[cfg(feature = "full")] 1138 impl Copy for AllowStruct {} 1139 1140 #[cfg(feature = "full")] 1141 impl Clone for AllowStruct { clonenull1142 fn clone(&self) -> Self { 1143 *self 1144 } 1145 } 1146 1147 impl Copy for Precedence {} 1148 1149 impl Clone for Precedence { clonenull1150 fn clone(&self) -> Self { 1151 *self 1152 } 1153 } 1154 1155 impl PartialEq for Precedence { eqnull1156 fn eq(&self, other: &Self) -> bool { 1157 *self as u8 == *other as u8 1158 } 1159 } 1160 1161 impl PartialOrd for Precedence { partial_cmpnull1162 fn partial_cmp(&self, other: &Self) -> Option<Ordering> { 1163 let this = *self as u8; 1164 let other = *other as u8; 1165 Some(this.cmp(&other)) 1166 } 1167 } 1168 1169 #[cfg(feature = "full")] can_begin_exprnull1170 fn can_begin_expr(input: ParseStream) -> bool { 1171 input.peek(Ident::peek_any) // value name or keyword 1172 || input.peek(token::Paren) // tuple 1173 || input.peek(token::Bracket) // array 1174 || input.peek(token::Brace) // block 1175 || input.peek(Lit) // literal 1176 || input.peek(Token![!]) && !input.peek(Token![!=]) // operator not 1177 || input.peek(Token![-]) && !input.peek(Token![-=]) && !input.peek(Token![->]) // unary minus 1178 || input.peek(Token![*]) && !input.peek(Token![*=]) // dereference 1179 || input.peek(Token![|]) && !input.peek(Token![|=]) // closure 1180 || input.peek(Token![&]) && !input.peek(Token![&=]) // reference 1181 || input.peek(Token![..]) // range notation 1182 || input.peek(Token![<]) && !input.peek(Token![<=]) && !input.peek(Token![<<=]) // associated path 1183 || input.peek(Token![::]) // global path 1184 || input.peek(Lifetime) // labeled loop 1185 || input.peek(Token![#]) // expression attributes 1186 } 1187 1188 #[cfg(feature = "full")] parse_exprnull1189 fn parse_expr( 1190 input: ParseStream, 1191 mut lhs: Expr, 1192 allow_struct: AllowStruct, 1193 base: Precedence, 1194 ) -> Result<Expr> { 1195 loop { 1196 let ahead = input.fork(); 1197 if let Some(op) = match ahead.parse::<BinOp>() { 1198 Ok(op) if Precedence::of(&op) >= base => Some(op), 1199 _ => None, 1200 } { 1201 input.advance_to(&ahead); 1202 let precedence = Precedence::of(&op); 1203 let mut rhs = unary_expr(input, allow_struct)?; 1204 loop { 1205 let next = peek_precedence(input); 1206 if next > precedence || next == precedence && precedence == Precedence::Assign { 1207 rhs = parse_expr(input, rhs, allow_struct, next)?; 1208 } else { 1209 break; 1210 } 1211 } 1212 lhs = Expr::Binary(ExprBinary { 1213 attrs: Vec::new(), 1214 left: Box::new(lhs), 1215 op, 1216 right: Box::new(rhs), 1217 }); 1218 } else if Precedence::Assign >= base 1219 && input.peek(Token![=]) 1220 && !input.peek(Token![==]) 1221 && !input.peek(Token![=>]) 1222 { 1223 let eq_token: Token![=] = input.parse()?; 1224 let mut rhs = unary_expr(input, allow_struct)?; 1225 loop { 1226 let next = peek_precedence(input); 1227 if next >= Precedence::Assign { 1228 rhs = parse_expr(input, rhs, allow_struct, next)?; 1229 } else { 1230 break; 1231 } 1232 } 1233 lhs = Expr::Assign(ExprAssign { 1234 attrs: Vec::new(), 1235 left: Box::new(lhs), 1236 eq_token, 1237 right: Box::new(rhs), 1238 }); 1239 } else if Precedence::Range >= base && input.peek(Token![..]) { 1240 let limits: RangeLimits = input.parse()?; 1241 let rhs = if matches!(limits, RangeLimits::HalfOpen(_)) 1242 && (input.is_empty() 1243 || input.peek(Token![,]) 1244 || input.peek(Token![;]) 1245 || input.peek(Token![.]) && !input.peek(Token![..]) 1246 || !allow_struct.0 && input.peek(token::Brace)) 1247 { 1248 None 1249 } else { 1250 let mut rhs = unary_expr(input, allow_struct)?; 1251 loop { 1252 let next = peek_precedence(input); 1253 if next > Precedence::Range { 1254 rhs = parse_expr(input, rhs, allow_struct, next)?; 1255 } else { 1256 break; 1257 } 1258 } 1259 Some(rhs) 1260 }; 1261 lhs = Expr::Range(ExprRange { 1262 attrs: Vec::new(), 1263 start: Some(Box::new(lhs)), 1264 limits, 1265 end: rhs.map(Box::new), 1266 }); 1267 } else if Precedence::Cast >= base && input.peek(Token![as]) { 1268 let as_token: Token![as] = input.parse()?; 1269 let allow_plus = false; 1270 let allow_group_generic = false; 1271 let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?; 1272 check_cast(input)?; 1273 lhs = Expr::Cast(ExprCast { 1274 attrs: Vec::new(), 1275 expr: Box::new(lhs), 1276 as_token, 1277 ty: Box::new(ty), 1278 }); 1279 } else { 1280 break; 1281 } 1282 } 1283 Ok(lhs) 1284 } 1285 1286 #[cfg(not(feature = "full"))] parse_exprnull1287 fn parse_expr(input: ParseStream, mut lhs: Expr, base: Precedence) -> Result<Expr> { 1288 loop { 1289 let ahead = input.fork(); 1290 if let Some(op) = match ahead.parse::<BinOp>() { 1291 Ok(op) if Precedence::of(&op) >= base => Some(op), 1292 _ => None, 1293 } { 1294 input.advance_to(&ahead); 1295 let precedence = Precedence::of(&op); 1296 let mut rhs = unary_expr(input)?; 1297 loop { 1298 let next = peek_precedence(input); 1299 if next > precedence || next == precedence && precedence == Precedence::Assign { 1300 rhs = parse_expr(input, rhs, next)?; 1301 } else { 1302 break; 1303 } 1304 } 1305 lhs = Expr::Binary(ExprBinary { 1306 attrs: Vec::new(), 1307 left: Box::new(lhs), 1308 op, 1309 right: Box::new(rhs), 1310 }); 1311 } else if Precedence::Cast >= base && input.peek(Token![as]) { 1312 let as_token: Token![as] = input.parse()?; 1313 let allow_plus = false; 1314 let allow_group_generic = false; 1315 let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?; 1316 check_cast(input)?; 1317 lhs = Expr::Cast(ExprCast { 1318 attrs: Vec::new(), 1319 expr: Box::new(lhs), 1320 as_token, 1321 ty: Box::new(ty), 1322 }); 1323 } else { 1324 break; 1325 } 1326 } 1327 Ok(lhs) 1328 } 1329 peek_precedencenull1330 fn peek_precedence(input: ParseStream) -> Precedence { 1331 if let Ok(op) = input.fork().parse() { 1332 Precedence::of(&op) 1333 } else if input.peek(Token![=]) && !input.peek(Token![=>]) { 1334 Precedence::Assign 1335 } else if input.peek(Token![..]) { 1336 Precedence::Range 1337 } else if input.peek(Token![as]) { 1338 Precedence::Cast 1339 } else { 1340 Precedence::Any 1341 } 1342 } 1343 1344 // Parse an arbitrary expression. ambiguous_exprnull1345 fn ambiguous_expr( 1346 input: ParseStream, 1347 #[cfg(feature = "full")] allow_struct: AllowStruct, 1348 ) -> Result<Expr> { 1349 let lhs = unary_expr( 1350 input, 1351 #[cfg(feature = "full")] 1352 allow_struct, 1353 )?; 1354 parse_expr( 1355 input, 1356 lhs, 1357 #[cfg(feature = "full")] 1358 allow_struct, 1359 Precedence::Any, 1360 ) 1361 } 1362 1363 #[cfg(feature = "full")] expr_attrsnull1364 fn expr_attrs(input: ParseStream) -> Result<Vec<Attribute>> { 1365 let mut attrs = Vec::new(); 1366 while !input.peek(token::Group) && input.peek(Token![#]) { 1367 attrs.push(input.call(attr::parsing::single_parse_outer)?); 1368 } 1369 Ok(attrs) 1370 } 1371 1372 // <UnOp> <trailer> 1373 // & <trailer> 1374 // &mut <trailer> 1375 // box <trailer> 1376 #[cfg(feature = "full")] unary_exprnull1377 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> { 1378 let begin = input.fork(); 1379 let attrs = input.call(expr_attrs)?; 1380 if input.peek(token::Group) { 1381 return trailer_expr(begin, attrs, input, allow_struct); 1382 } 1383 1384 if input.peek(Token![&]) { 1385 let and_token: Token![&] = input.parse()?; 1386 let raw: Option<kw::raw> = if input.peek(kw::raw) 1387 && (input.peek2(Token![mut]) || input.peek2(Token![const])) 1388 { 1389 Some(input.parse()?) 1390 } else { 1391 None 1392 }; 1393 let mutability: Option<Token![mut]> = input.parse()?; 1394 if raw.is_some() && mutability.is_none() { 1395 input.parse::<Token![const]>()?; 1396 } 1397 let expr = Box::new(unary_expr(input, allow_struct)?); 1398 if raw.is_some() { 1399 Ok(Expr::Verbatim(verbatim::between(&begin, input))) 1400 } else { 1401 Ok(Expr::Reference(ExprReference { 1402 attrs, 1403 and_token, 1404 mutability, 1405 expr, 1406 })) 1407 } 1408 } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) { 1409 expr_unary(input, attrs, allow_struct).map(Expr::Unary) 1410 } else { 1411 trailer_expr(begin, attrs, input, allow_struct) 1412 } 1413 } 1414 1415 #[cfg(not(feature = "full"))] unary_exprnull1416 fn unary_expr(input: ParseStream) -> Result<Expr> { 1417 if input.peek(Token![&]) { 1418 Ok(Expr::Reference(ExprReference { 1419 attrs: Vec::new(), 1420 and_token: input.parse()?, 1421 mutability: input.parse()?, 1422 expr: Box::new(unary_expr(input)?), 1423 })) 1424 } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) { 1425 Ok(Expr::Unary(ExprUnary { 1426 attrs: Vec::new(), 1427 op: input.parse()?, 1428 expr: Box::new(unary_expr(input)?), 1429 })) 1430 } else { 1431 trailer_expr(input) 1432 } 1433 } 1434 1435 // <atom> (..<args>) ... 1436 // <atom> . <ident> (..<args>) ... 1437 // <atom> . <ident> ... 1438 // <atom> . <lit> ... 1439 // <atom> [ <expr> ] ... 1440 // <atom> ? ... 1441 #[cfg(feature = "full")] trailer_exprnull1442 fn trailer_expr( 1443 begin: ParseBuffer, 1444 mut attrs: Vec<Attribute>, 1445 input: ParseStream, 1446 allow_struct: AllowStruct, 1447 ) -> Result<Expr> { 1448 let atom = atom_expr(input, allow_struct)?; 1449 let mut e = trailer_helper(input, atom)?; 1450 1451 if let Expr::Verbatim(tokens) = &mut e { 1452 *tokens = verbatim::between(&begin, input); 1453 } else { 1454 let inner_attrs = e.replace_attrs(Vec::new()); 1455 attrs.extend(inner_attrs); 1456 e.replace_attrs(attrs); 1457 } 1458 1459 Ok(e) 1460 } 1461 1462 #[cfg(feature = "full")] trailer_helpernull1463 fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> { 1464 loop { 1465 if input.peek(token::Paren) { 1466 let content; 1467 e = Expr::Call(ExprCall { 1468 attrs: Vec::new(), 1469 func: Box::new(e), 1470 paren_token: parenthesized!(content in input), 1471 args: content.parse_terminated(Expr::parse, Token![,])?, 1472 }); 1473 } else if input.peek(Token![.]) 1474 && !input.peek(Token![..]) 1475 && match e { 1476 Expr::Range(_) => false, 1477 _ => true, 1478 } 1479 { 1480 let mut dot_token: Token![.] = input.parse()?; 1481 1482 let float_token: Option<LitFloat> = input.parse()?; 1483 if let Some(float_token) = float_token { 1484 if multi_index(&mut e, &mut dot_token, float_token)? { 1485 continue; 1486 } 1487 } 1488 1489 let await_token: Option<Token![await]> = input.parse()?; 1490 if let Some(await_token) = await_token { 1491 e = Expr::Await(ExprAwait { 1492 attrs: Vec::new(), 1493 base: Box::new(e), 1494 dot_token, 1495 await_token, 1496 }); 1497 continue; 1498 } 1499 1500 let member: Member = input.parse()?; 1501 let turbofish = if member.is_named() && input.peek(Token![::]) { 1502 Some(AngleBracketedGenericArguments::parse_turbofish(input)?) 1503 } else { 1504 None 1505 }; 1506 1507 if turbofish.is_some() || input.peek(token::Paren) { 1508 if let Member::Named(method) = member { 1509 let content; 1510 e = Expr::MethodCall(ExprMethodCall { 1511 attrs: Vec::new(), 1512 receiver: Box::new(e), 1513 dot_token, 1514 method, 1515 turbofish, 1516 paren_token: parenthesized!(content in input), 1517 args: content.parse_terminated(Expr::parse, Token![,])?, 1518 }); 1519 continue; 1520 } 1521 } 1522 1523 e = Expr::Field(ExprField { 1524 attrs: Vec::new(), 1525 base: Box::new(e), 1526 dot_token, 1527 member, 1528 }); 1529 } else if input.peek(token::Bracket) { 1530 let content; 1531 e = Expr::Index(ExprIndex { 1532 attrs: Vec::new(), 1533 expr: Box::new(e), 1534 bracket_token: bracketed!(content in input), 1535 index: content.parse()?, 1536 }); 1537 } else if input.peek(Token![?]) { 1538 e = Expr::Try(ExprTry { 1539 attrs: Vec::new(), 1540 expr: Box::new(e), 1541 question_token: input.parse()?, 1542 }); 1543 } else { 1544 break; 1545 } 1546 } 1547 Ok(e) 1548 } 1549 1550 #[cfg(not(feature = "full"))] trailer_exprnull1551 fn trailer_expr(input: ParseStream) -> Result<Expr> { 1552 let mut e = atom_expr(input)?; 1553 1554 loop { 1555 if input.peek(token::Paren) { 1556 let content; 1557 e = Expr::Call(ExprCall { 1558 attrs: Vec::new(), 1559 func: Box::new(e), 1560 paren_token: parenthesized!(content in input), 1561 args: content.parse_terminated(Expr::parse, Token![,])?, 1562 }); 1563 } else if input.peek(Token![.]) 1564 && !input.peek(Token![..]) 1565 && !input.peek2(Token![await]) 1566 { 1567 let mut dot_token: Token![.] = input.parse()?; 1568 1569 let float_token: Option<LitFloat> = input.parse()?; 1570 if let Some(float_token) = float_token { 1571 if multi_index(&mut e, &mut dot_token, float_token)? { 1572 continue; 1573 } 1574 } 1575 1576 let member: Member = input.parse()?; 1577 let turbofish = if member.is_named() && input.peek(Token![::]) { 1578 let colon2_token: Token![::] = input.parse()?; 1579 let turbofish = 1580 AngleBracketedGenericArguments::do_parse(Some(colon2_token), input)?; 1581 Some(turbofish) 1582 } else { 1583 None 1584 }; 1585 1586 if turbofish.is_some() || input.peek(token::Paren) { 1587 if let Member::Named(method) = member { 1588 let content; 1589 e = Expr::MethodCall(ExprMethodCall { 1590 attrs: Vec::new(), 1591 receiver: Box::new(e), 1592 dot_token, 1593 method, 1594 turbofish, 1595 paren_token: parenthesized!(content in input), 1596 args: content.parse_terminated(Expr::parse, Token![,])?, 1597 }); 1598 continue; 1599 } 1600 } 1601 1602 e = Expr::Field(ExprField { 1603 attrs: Vec::new(), 1604 base: Box::new(e), 1605 dot_token, 1606 member, 1607 }); 1608 } else if input.peek(token::Bracket) { 1609 let content; 1610 e = Expr::Index(ExprIndex { 1611 attrs: Vec::new(), 1612 expr: Box::new(e), 1613 bracket_token: bracketed!(content in input), 1614 index: content.parse()?, 1615 }); 1616 } else { 1617 break; 1618 } 1619 } 1620 1621 Ok(e) 1622 } 1623 1624 // Parse all atomic expressions which don't have to worry about precedence 1625 // interactions, as they are fully contained. 1626 #[cfg(feature = "full")] atom_exprnull1627 fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> { 1628 if input.peek(token::Group) { 1629 expr_group(input, allow_struct) 1630 } else if input.peek(Lit) { 1631 input.parse().map(Expr::Lit) 1632 } else if input.peek(Token![async]) 1633 && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace)) 1634 { 1635 input.parse().map(Expr::Async) 1636 } else if input.peek(Token![try]) && input.peek2(token::Brace) { 1637 input.parse().map(Expr::TryBlock) 1638 } else if input.peek(Token![|]) 1639 || input.peek(Token![move]) 1640 || input.peek(Token![for]) 1641 && input.peek2(Token![<]) 1642 && (input.peek3(Lifetime) || input.peek3(Token![>])) 1643 || input.peek(Token![const]) && !input.peek2(token::Brace) 1644 || input.peek(Token![static]) 1645 || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move])) 1646 { 1647 expr_closure(input, allow_struct).map(Expr::Closure) 1648 } else if input.peek(kw::builtin) && input.peek2(Token![#]) { 1649 expr_builtin(input) 1650 } else if input.peek(Ident) 1651 || input.peek(Token![::]) 1652 || input.peek(Token![<]) 1653 || input.peek(Token![self]) 1654 || input.peek(Token![Self]) 1655 || input.peek(Token![super]) 1656 || input.peek(Token![crate]) 1657 || input.peek(Token![try]) && (input.peek2(Token![!]) || input.peek2(Token![::])) 1658 { 1659 path_or_macro_or_struct(input, allow_struct) 1660 } else if input.peek(token::Paren) { 1661 paren_or_tuple(input) 1662 } else if input.peek(Token![break]) { 1663 expr_break(input, allow_struct).map(Expr::Break) 1664 } else if input.peek(Token![continue]) { 1665 input.parse().map(Expr::Continue) 1666 } else if input.peek(Token![return]) { 1667 expr_return(input, allow_struct).map(Expr::Return) 1668 } else if input.peek(token::Bracket) { 1669 array_or_repeat(input) 1670 } else if input.peek(Token![let]) { 1671 input.parse().map(Expr::Let) 1672 } else if input.peek(Token![if]) { 1673 input.parse().map(Expr::If) 1674 } else if input.peek(Token![while]) { 1675 input.parse().map(Expr::While) 1676 } else if input.peek(Token![for]) { 1677 input.parse().map(Expr::ForLoop) 1678 } else if input.peek(Token![loop]) { 1679 input.parse().map(Expr::Loop) 1680 } else if input.peek(Token![match]) { 1681 input.parse().map(Expr::Match) 1682 } else if input.peek(Token![yield]) { 1683 input.parse().map(Expr::Yield) 1684 } else if input.peek(Token![unsafe]) { 1685 input.parse().map(Expr::Unsafe) 1686 } else if input.peek(Token![const]) { 1687 input.parse().map(Expr::Const) 1688 } else if input.peek(token::Brace) { 1689 input.parse().map(Expr::Block) 1690 } else if input.peek(Token![..]) { 1691 expr_range(input, allow_struct).map(Expr::Range) 1692 } else if input.peek(Token![_]) { 1693 input.parse().map(Expr::Infer) 1694 } else if input.peek(Lifetime) { 1695 atom_labeled(input) 1696 } else { 1697 Err(input.error("expected an expression")) 1698 } 1699 } 1700 1701 #[cfg(feature = "full")] atom_labelednull1702 fn atom_labeled(input: ParseStream) -> Result<Expr> { 1703 let the_label: Label = input.parse()?; 1704 let mut expr = if input.peek(Token![while]) { 1705 Expr::While(input.parse()?) 1706 } else if input.peek(Token![for]) { 1707 Expr::ForLoop(input.parse()?) 1708 } else if input.peek(Token![loop]) { 1709 Expr::Loop(input.parse()?) 1710 } else if input.peek(token::Brace) { 1711 Expr::Block(input.parse()?) 1712 } else { 1713 return Err(input.error("expected loop or block expression")); 1714 }; 1715 match &mut expr { 1716 Expr::While(ExprWhile { label, .. }) 1717 | Expr::ForLoop(ExprForLoop { label, .. }) 1718 | Expr::Loop(ExprLoop { label, .. }) 1719 | Expr::Block(ExprBlock { label, .. }) => *label = Some(the_label), 1720 _ => unreachable!(), 1721 } 1722 Ok(expr) 1723 } 1724 1725 #[cfg(not(feature = "full"))] atom_exprnull1726 fn atom_expr(input: ParseStream) -> Result<Expr> { 1727 if input.peek(token::Group) { 1728 expr_group(input) 1729 } else if input.peek(Lit) { 1730 input.parse().map(Expr::Lit) 1731 } else if input.peek(token::Paren) { 1732 input.call(expr_paren).map(Expr::Paren) 1733 } else if input.peek(Ident) 1734 || input.peek(Token![::]) 1735 || input.peek(Token![<]) 1736 || input.peek(Token![self]) 1737 || input.peek(Token![Self]) 1738 || input.peek(Token![super]) 1739 || input.peek(Token![crate]) 1740 { 1741 path_or_macro_or_struct(input) 1742 } else if input.is_empty() { 1743 Err(input.error("expected an expression")) 1744 } else { 1745 if input.peek(token::Brace) { 1746 let scan = input.fork(); 1747 let content; 1748 braced!(content in scan); 1749 if content.parse::<Expr>().is_ok() && content.is_empty() { 1750 let expr_block = verbatim::between(input, &scan); 1751 input.advance_to(&scan); 1752 return Ok(Expr::Verbatim(expr_block)); 1753 } 1754 } 1755 Err(input.error("unsupported expression; enable syn's features=[\"full\"]")) 1756 } 1757 } 1758 1759 #[cfg(feature = "full")] expr_builtinnull1760 fn expr_builtin(input: ParseStream) -> Result<Expr> { 1761 let begin = input.fork(); 1762 1763 input.parse::<kw::builtin>()?; 1764 input.parse::<Token![#]>()?; 1765 input.parse::<Ident>()?; 1766 1767 let args; 1768 parenthesized!(args in input); 1769 args.parse::<TokenStream>()?; 1770 1771 Ok(Expr::Verbatim(verbatim::between(&begin, input))) 1772 } 1773 path_or_macro_or_structnull1774 fn path_or_macro_or_struct( 1775 input: ParseStream, 1776 #[cfg(feature = "full")] allow_struct: AllowStruct, 1777 ) -> Result<Expr> { 1778 let (qself, path) = path::parsing::qpath(input, true)?; 1779 rest_of_path_or_macro_or_struct( 1780 qself, 1781 path, 1782 input, 1783 #[cfg(feature = "full")] 1784 allow_struct, 1785 ) 1786 } 1787 rest_of_path_or_macro_or_structnull1788 fn rest_of_path_or_macro_or_struct( 1789 qself: Option<QSelf>, 1790 path: Path, 1791 input: ParseStream, 1792 #[cfg(feature = "full")] allow_struct: AllowStruct, 1793 ) -> Result<Expr> { 1794 if qself.is_none() 1795 && input.peek(Token![!]) 1796 && !input.peek(Token![!=]) 1797 && path.is_mod_style() 1798 { 1799 let bang_token: Token![!] = input.parse()?; 1800 let (delimiter, tokens) = mac::parse_delimiter(input)?; 1801 return Ok(Expr::Macro(ExprMacro { 1802 attrs: Vec::new(), 1803 mac: Macro { 1804 path, 1805 bang_token, 1806 delimiter, 1807 tokens, 1808 }, 1809 })); 1810 } 1811 1812 #[cfg(not(feature = "full"))] 1813 let allow_struct = (true,); 1814 if allow_struct.0 && input.peek(token::Brace) { 1815 return expr_struct_helper(input, qself, path).map(Expr::Struct); 1816 } 1817 1818 Ok(Expr::Path(ExprPath { 1819 attrs: Vec::new(), 1820 qself, 1821 path, 1822 })) 1823 } 1824 1825 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 1826 impl Parse for ExprMacro { parsenull1827 fn parse(input: ParseStream) -> Result<Self> { 1828 Ok(ExprMacro { 1829 attrs: Vec::new(), 1830 mac: input.parse()?, 1831 }) 1832 } 1833 } 1834 1835 #[cfg(feature = "full")] paren_or_tuplenull1836 fn paren_or_tuple(input: ParseStream) -> Result<Expr> { 1837 let content; 1838 let paren_token = parenthesized!(content in input); 1839 if content.is_empty() { 1840 return Ok(Expr::Tuple(ExprTuple { 1841 attrs: Vec::new(), 1842 paren_token, 1843 elems: Punctuated::new(), 1844 })); 1845 } 1846 1847 let first: Expr = content.parse()?; 1848 if content.is_empty() { 1849 return Ok(Expr::Paren(ExprParen { 1850 attrs: Vec::new(), 1851 paren_token, 1852 expr: Box::new(first), 1853 })); 1854 } 1855 1856 let mut elems = Punctuated::new(); 1857 elems.push_value(first); 1858 while !content.is_empty() { 1859 let punct = content.parse()?; 1860 elems.push_punct(punct); 1861 if content.is_empty() { 1862 break; 1863 } 1864 let value = content.parse()?; 1865 elems.push_value(value); 1866 } 1867 Ok(Expr::Tuple(ExprTuple { 1868 attrs: Vec::new(), 1869 paren_token, 1870 elems, 1871 })) 1872 } 1873 1874 #[cfg(feature = "full")] array_or_repeatnull1875 fn array_or_repeat(input: ParseStream) -> Result<Expr> { 1876 let content; 1877 let bracket_token = bracketed!(content in input); 1878 if content.is_empty() { 1879 return Ok(Expr::Array(ExprArray { 1880 attrs: Vec::new(), 1881 bracket_token, 1882 elems: Punctuated::new(), 1883 })); 1884 } 1885 1886 let first: Expr = content.parse()?; 1887 if content.is_empty() || content.peek(Token![,]) { 1888 let mut elems = Punctuated::new(); 1889 elems.push_value(first); 1890 while !content.is_empty() { 1891 let punct = content.parse()?; 1892 elems.push_punct(punct); 1893 if content.is_empty() { 1894 break; 1895 } 1896 let value = content.parse()?; 1897 elems.push_value(value); 1898 } 1899 Ok(Expr::Array(ExprArray { 1900 attrs: Vec::new(), 1901 bracket_token, 1902 elems, 1903 })) 1904 } else if content.peek(Token![;]) { 1905 let semi_token: Token![;] = content.parse()?; 1906 let len: Expr = content.parse()?; 1907 Ok(Expr::Repeat(ExprRepeat { 1908 attrs: Vec::new(), 1909 bracket_token, 1910 expr: Box::new(first), 1911 semi_token, 1912 len: Box::new(len), 1913 })) 1914 } else { 1915 Err(content.error("expected `,` or `;`")) 1916 } 1917 } 1918 1919 #[cfg(feature = "full")] 1920 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 1921 impl Parse for ExprArray { parsenull1922 fn parse(input: ParseStream) -> Result<Self> { 1923 let content; 1924 let bracket_token = bracketed!(content in input); 1925 let mut elems = Punctuated::new(); 1926 1927 while !content.is_empty() { 1928 let first: Expr = content.parse()?; 1929 elems.push_value(first); 1930 if content.is_empty() { 1931 break; 1932 } 1933 let punct = content.parse()?; 1934 elems.push_punct(punct); 1935 } 1936 1937 Ok(ExprArray { 1938 attrs: Vec::new(), 1939 bracket_token, 1940 elems, 1941 }) 1942 } 1943 } 1944 1945 #[cfg(feature = "full")] 1946 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 1947 impl Parse for ExprRepeat { parsenull1948 fn parse(input: ParseStream) -> Result<Self> { 1949 let content; 1950 Ok(ExprRepeat { 1951 bracket_token: bracketed!(content in input), 1952 attrs: Vec::new(), 1953 expr: content.parse()?, 1954 semi_token: content.parse()?, 1955 len: content.parse()?, 1956 }) 1957 } 1958 } 1959 1960 #[cfg(feature = "full")] 1961 pub(crate) fn expr_early(input: ParseStream) -> Result<Expr> { 1962 let mut attrs = input.call(expr_attrs)?; 1963 let mut expr = if input.peek(token::Group) { 1964 let allow_struct = AllowStruct(true); 1965 let atom = expr_group(input, allow_struct)?; 1966 if continue_parsing_early(&atom) { 1967 trailer_helper(input, atom)? 1968 } else { 1969 atom 1970 } 1971 } else if input.peek(Token![if]) { 1972 Expr::If(input.parse()?) 1973 } else if input.peek(Token![while]) { 1974 Expr::While(input.parse()?) 1975 } else if input.peek(Token![for]) 1976 && !(input.peek2(Token![<]) && (input.peek3(Lifetime) || input.peek3(Token![>]))) 1977 { 1978 Expr::ForLoop(input.parse()?) 1979 } else if input.peek(Token![loop]) { 1980 Expr::Loop(input.parse()?) 1981 } else if input.peek(Token![match]) { 1982 Expr::Match(input.parse()?) 1983 } else if input.peek(Token![try]) && input.peek2(token::Brace) { 1984 Expr::TryBlock(input.parse()?) 1985 } else if input.peek(Token![unsafe]) { 1986 Expr::Unsafe(input.parse()?) 1987 } else if input.peek(Token![const]) && input.peek2(token::Brace) { 1988 Expr::Const(input.parse()?) 1989 } else if input.peek(token::Brace) { 1990 Expr::Block(input.parse()?) 1991 } else if input.peek(Lifetime) { 1992 atom_labeled(input)? 1993 } else { 1994 let allow_struct = AllowStruct(true); 1995 unary_expr(input, allow_struct)? 1996 }; 1997 1998 if continue_parsing_early(&expr) { 1999 attrs.extend(expr.replace_attrs(Vec::new())); 2000 expr.replace_attrs(attrs); 2001 2002 let allow_struct = AllowStruct(true); 2003 return parse_expr(input, expr, allow_struct, Precedence::Any); 2004 } 2005 2006 if input.peek(Token![.]) && !input.peek(Token![..]) || input.peek(Token![?]) { 2007 expr = trailer_helper(input, expr)?; 2008 2009 attrs.extend(expr.replace_attrs(Vec::new())); 2010 expr.replace_attrs(attrs); 2011 2012 let allow_struct = AllowStruct(true); 2013 return parse_expr(input, expr, allow_struct, Precedence::Any); 2014 } 2015 2016 attrs.extend(expr.replace_attrs(Vec::new())); 2017 expr.replace_attrs(attrs); 2018 Ok(expr) 2019 } 2020 2021 #[cfg(feature = "full")] continue_parsing_earlynull2022 fn continue_parsing_early(mut expr: &Expr) -> bool { 2023 while let Expr::Group(group) = expr { 2024 expr = &group.expr; 2025 } 2026 match expr { 2027 Expr::If(_) 2028 | Expr::While(_) 2029 | Expr::ForLoop(_) 2030 | Expr::Loop(_) 2031 | Expr::Match(_) 2032 | Expr::TryBlock(_) 2033 | Expr::Unsafe(_) 2034 | Expr::Const(_) 2035 | Expr::Block(_) => false, 2036 _ => true, 2037 } 2038 } 2039 2040 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2041 impl Parse for ExprLit { parsenull2042 fn parse(input: ParseStream) -> Result<Self> { 2043 Ok(ExprLit { 2044 attrs: Vec::new(), 2045 lit: input.parse()?, 2046 }) 2047 } 2048 } 2049 expr_groupnull2050 fn expr_group( 2051 input: ParseStream, 2052 #[cfg(feature = "full")] allow_struct: AllowStruct, 2053 ) -> Result<Expr> { 2054 let group = crate::group::parse_group(input)?; 2055 let mut inner: Expr = group.content.parse()?; 2056 2057 match inner { 2058 Expr::Path(mut expr) if expr.attrs.is_empty() => { 2059 let grouped_len = expr.path.segments.len(); 2060 Path::parse_rest(input, &mut expr.path, true)?; 2061 match rest_of_path_or_macro_or_struct( 2062 expr.qself, 2063 expr.path, 2064 input, 2065 #[cfg(feature = "full")] 2066 allow_struct, 2067 )? { 2068 Expr::Path(expr) if expr.path.segments.len() == grouped_len => { 2069 inner = Expr::Path(expr); 2070 } 2071 extended => return Ok(extended), 2072 } 2073 } 2074 _ => {} 2075 } 2076 2077 Ok(Expr::Group(ExprGroup { 2078 attrs: Vec::new(), 2079 group_token: group.token, 2080 expr: Box::new(inner), 2081 })) 2082 } 2083 2084 #[cfg(feature = "full")] 2085 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2086 impl Parse for ExprParen { parsenull2087 fn parse(input: ParseStream) -> Result<Self> { 2088 expr_paren(input) 2089 } 2090 } 2091 expr_parennull2092 fn expr_paren(input: ParseStream) -> Result<ExprParen> { 2093 let content; 2094 Ok(ExprParen { 2095 attrs: Vec::new(), 2096 paren_token: parenthesized!(content in input), 2097 expr: content.parse()?, 2098 }) 2099 } 2100 2101 #[cfg(feature = "full")] 2102 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2103 impl Parse for ExprLet { parsenull2104 fn parse(input: ParseStream) -> Result<Self> { 2105 Ok(ExprLet { 2106 attrs: Vec::new(), 2107 let_token: input.parse()?, 2108 pat: Box::new(Pat::parse_multi_with_leading_vert(input)?), 2109 eq_token: input.parse()?, 2110 expr: Box::new({ 2111 let allow_struct = AllowStruct(false); 2112 let lhs = unary_expr(input, allow_struct)?; 2113 parse_expr(input, lhs, allow_struct, Precedence::Compare)? 2114 }), 2115 }) 2116 } 2117 } 2118 2119 #[cfg(feature = "full")] 2120 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2121 impl Parse for ExprIf { parsenull2122 fn parse(input: ParseStream) -> Result<Self> { 2123 let attrs = input.call(Attribute::parse_outer)?; 2124 Ok(ExprIf { 2125 attrs, 2126 if_token: input.parse()?, 2127 cond: Box::new(input.call(Expr::parse_without_eager_brace)?), 2128 then_branch: input.parse()?, 2129 else_branch: { 2130 if input.peek(Token![else]) { 2131 Some(input.call(else_block)?) 2132 } else { 2133 None 2134 } 2135 }, 2136 }) 2137 } 2138 } 2139 2140 #[cfg(feature = "full")] else_blocknull2141 fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> { 2142 let else_token: Token![else] = input.parse()?; 2143 2144 let lookahead = input.lookahead1(); 2145 let else_branch = if lookahead.peek(Token![if]) { 2146 input.parse().map(Expr::If)? 2147 } else if lookahead.peek(token::Brace) { 2148 Expr::Block(ExprBlock { 2149 attrs: Vec::new(), 2150 label: None, 2151 block: input.parse()?, 2152 }) 2153 } else { 2154 return Err(lookahead.error()); 2155 }; 2156 2157 Ok((else_token, Box::new(else_branch))) 2158 } 2159 2160 #[cfg(feature = "full")] 2161 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2162 impl Parse for ExprInfer { parsenull2163 fn parse(input: ParseStream) -> Result<Self> { 2164 Ok(ExprInfer { 2165 attrs: input.call(Attribute::parse_outer)?, 2166 underscore_token: input.parse()?, 2167 }) 2168 } 2169 } 2170 2171 #[cfg(feature = "full")] 2172 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2173 impl Parse for ExprForLoop { parsenull2174 fn parse(input: ParseStream) -> Result<Self> { 2175 let mut attrs = input.call(Attribute::parse_outer)?; 2176 let label: Option<Label> = input.parse()?; 2177 let for_token: Token![for] = input.parse()?; 2178 2179 let pat = Pat::parse_multi_with_leading_vert(input)?; 2180 2181 let in_token: Token![in] = input.parse()?; 2182 let expr: Expr = input.call(Expr::parse_without_eager_brace)?; 2183 2184 let content; 2185 let brace_token = braced!(content in input); 2186 attr::parsing::parse_inner(&content, &mut attrs)?; 2187 let stmts = content.call(Block::parse_within)?; 2188 2189 Ok(ExprForLoop { 2190 attrs, 2191 label, 2192 for_token, 2193 pat: Box::new(pat), 2194 in_token, 2195 expr: Box::new(expr), 2196 body: Block { brace_token, stmts }, 2197 }) 2198 } 2199 } 2200 2201 #[cfg(feature = "full")] 2202 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2203 impl Parse for ExprLoop { parsenull2204 fn parse(input: ParseStream) -> Result<Self> { 2205 let mut attrs = input.call(Attribute::parse_outer)?; 2206 let label: Option<Label> = input.parse()?; 2207 let loop_token: Token![loop] = input.parse()?; 2208 2209 let content; 2210 let brace_token = braced!(content in input); 2211 attr::parsing::parse_inner(&content, &mut attrs)?; 2212 let stmts = content.call(Block::parse_within)?; 2213 2214 Ok(ExprLoop { 2215 attrs, 2216 label, 2217 loop_token, 2218 body: Block { brace_token, stmts }, 2219 }) 2220 } 2221 } 2222 2223 #[cfg(feature = "full")] 2224 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2225 impl Parse for ExprMatch { parsenull2226 fn parse(input: ParseStream) -> Result<Self> { 2227 let mut attrs = input.call(Attribute::parse_outer)?; 2228 let match_token: Token![match] = input.parse()?; 2229 let expr = Expr::parse_without_eager_brace(input)?; 2230 2231 let content; 2232 let brace_token = braced!(content in input); 2233 attr::parsing::parse_inner(&content, &mut attrs)?; 2234 2235 let mut arms = Vec::new(); 2236 while !content.is_empty() { 2237 arms.push(content.call(Arm::parse)?); 2238 } 2239 2240 Ok(ExprMatch { 2241 attrs, 2242 match_token, 2243 expr: Box::new(expr), 2244 brace_token, 2245 arms, 2246 }) 2247 } 2248 } 2249 2250 macro_rules! impl_by_parsing_expr { 2251 ( 2252 $( 2253 $expr_type:ty, $variant:ident, $msg:expr, 2254 )* 2255 ) => { 2256 $( 2257 #[cfg(all(feature = "full", feature = "printing"))] 2258 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2259 impl Parse for $expr_type { parsenull2260 fn parse(input: ParseStream) -> Result<Self> { 2261 let mut expr: Expr = input.parse()?; 2262 loop { 2263 match expr { 2264 Expr::$variant(inner) => return Ok(inner), 2265 Expr::Group(next) => expr = *next.expr, 2266 _ => return Err(Error::new_spanned(expr, $msg)), 2267 } 2268 } 2269 } 2270 } 2271 )* 2272 }; 2273 } 2274 2275 impl_by_parsing_expr! { 2276 ExprAssign, Assign, "expected assignment expression", 2277 ExprAwait, Await, "expected await expression", 2278 ExprBinary, Binary, "expected binary operation", 2279 ExprCall, Call, "expected function call expression", 2280 ExprCast, Cast, "expected cast expression", 2281 ExprField, Field, "expected struct field access", 2282 ExprIndex, Index, "expected indexing expression", 2283 ExprMethodCall, MethodCall, "expected method call expression", 2284 ExprRange, Range, "expected range expression", 2285 ExprTry, Try, "expected try expression", 2286 ExprTuple, Tuple, "expected tuple expression", 2287 } 2288 2289 #[cfg(feature = "full")] 2290 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2291 impl Parse for ExprUnary { parsenull2292 fn parse(input: ParseStream) -> Result<Self> { 2293 let attrs = Vec::new(); 2294 let allow_struct = AllowStruct(true); 2295 expr_unary(input, attrs, allow_struct) 2296 } 2297 } 2298 2299 #[cfg(feature = "full")] expr_unarynull2300 fn expr_unary( 2301 input: ParseStream, 2302 attrs: Vec<Attribute>, 2303 allow_struct: AllowStruct, 2304 ) -> Result<ExprUnary> { 2305 Ok(ExprUnary { 2306 attrs, 2307 op: input.parse()?, 2308 expr: Box::new(unary_expr(input, allow_struct)?), 2309 }) 2310 } 2311 2312 #[cfg(feature = "full")] 2313 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2314 impl Parse for ExprClosure { parsenull2315 fn parse(input: ParseStream) -> Result<Self> { 2316 let allow_struct = AllowStruct(true); 2317 expr_closure(input, allow_struct) 2318 } 2319 } 2320 2321 #[cfg(feature = "full")] 2322 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2323 impl Parse for ExprReference { parsenull2324 fn parse(input: ParseStream) -> Result<Self> { 2325 let allow_struct = AllowStruct(true); 2326 Ok(ExprReference { 2327 attrs: Vec::new(), 2328 and_token: input.parse()?, 2329 mutability: input.parse()?, 2330 expr: Box::new(unary_expr(input, allow_struct)?), 2331 }) 2332 } 2333 } 2334 2335 #[cfg(feature = "full")] 2336 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2337 impl Parse for ExprBreak { parsenull2338 fn parse(input: ParseStream) -> Result<Self> { 2339 let allow_struct = AllowStruct(true); 2340 expr_break(input, allow_struct) 2341 } 2342 } 2343 2344 #[cfg(feature = "full")] 2345 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2346 impl Parse for ExprReturn { parsenull2347 fn parse(input: ParseStream) -> Result<Self> { 2348 let allow_struct = AllowStruct(true); 2349 expr_return(input, allow_struct) 2350 } 2351 } 2352 2353 #[cfg(feature = "full")] 2354 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2355 impl Parse for ExprTryBlock { parsenull2356 fn parse(input: ParseStream) -> Result<Self> { 2357 Ok(ExprTryBlock { 2358 attrs: Vec::new(), 2359 try_token: input.parse()?, 2360 block: input.parse()?, 2361 }) 2362 } 2363 } 2364 2365 #[cfg(feature = "full")] 2366 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2367 impl Parse for ExprYield { parsenull2368 fn parse(input: ParseStream) -> Result<Self> { 2369 Ok(ExprYield { 2370 attrs: Vec::new(), 2371 yield_token: input.parse()?, 2372 expr: { 2373 if can_begin_expr(input) { 2374 Some(input.parse()?) 2375 } else { 2376 None 2377 } 2378 }, 2379 }) 2380 } 2381 } 2382 2383 #[cfg(feature = "full")] expr_closurenull2384 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> { 2385 let lifetimes: Option<BoundLifetimes> = input.parse()?; 2386 let constness: Option<Token![const]> = input.parse()?; 2387 let movability: Option<Token![static]> = input.parse()?; 2388 let asyncness: Option<Token![async]> = input.parse()?; 2389 let capture: Option<Token![move]> = input.parse()?; 2390 let or1_token: Token![|] = input.parse()?; 2391 2392 let mut inputs = Punctuated::new(); 2393 loop { 2394 if input.peek(Token![|]) { 2395 break; 2396 } 2397 let value = closure_arg(input)?; 2398 inputs.push_value(value); 2399 if input.peek(Token![|]) { 2400 break; 2401 } 2402 let punct: Token![,] = input.parse()?; 2403 inputs.push_punct(punct); 2404 } 2405 2406 let or2_token: Token![|] = input.parse()?; 2407 2408 let (output, body) = if input.peek(Token![->]) { 2409 let arrow_token: Token![->] = input.parse()?; 2410 let ty: Type = input.parse()?; 2411 let body: Block = input.parse()?; 2412 let output = ReturnType::Type(arrow_token, Box::new(ty)); 2413 let block = Expr::Block(ExprBlock { 2414 attrs: Vec::new(), 2415 label: None, 2416 block: body, 2417 }); 2418 (output, block) 2419 } else { 2420 let body = ambiguous_expr(input, allow_struct)?; 2421 (ReturnType::Default, body) 2422 }; 2423 2424 Ok(ExprClosure { 2425 attrs: Vec::new(), 2426 lifetimes, 2427 constness, 2428 movability, 2429 asyncness, 2430 capture, 2431 or1_token, 2432 inputs, 2433 or2_token, 2434 output, 2435 body: Box::new(body), 2436 }) 2437 } 2438 2439 #[cfg(feature = "full")] 2440 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2441 impl Parse for ExprAsync { parsenull2442 fn parse(input: ParseStream) -> Result<Self> { 2443 Ok(ExprAsync { 2444 attrs: Vec::new(), 2445 async_token: input.parse()?, 2446 capture: input.parse()?, 2447 block: input.parse()?, 2448 }) 2449 } 2450 } 2451 2452 #[cfg(feature = "full")] closure_argnull2453 fn closure_arg(input: ParseStream) -> Result<Pat> { 2454 let attrs = input.call(Attribute::parse_outer)?; 2455 let mut pat = Pat::parse_single(input)?; 2456 2457 if input.peek(Token![:]) { 2458 Ok(Pat::Type(PatType { 2459 attrs, 2460 pat: Box::new(pat), 2461 colon_token: input.parse()?, 2462 ty: input.parse()?, 2463 })) 2464 } else { 2465 match &mut pat { 2466 Pat::Const(pat) => pat.attrs = attrs, 2467 Pat::Ident(pat) => pat.attrs = attrs, 2468 Pat::Lit(pat) => pat.attrs = attrs, 2469 Pat::Macro(pat) => pat.attrs = attrs, 2470 Pat::Or(pat) => pat.attrs = attrs, 2471 Pat::Paren(pat) => pat.attrs = attrs, 2472 Pat::Path(pat) => pat.attrs = attrs, 2473 Pat::Range(pat) => pat.attrs = attrs, 2474 Pat::Reference(pat) => pat.attrs = attrs, 2475 Pat::Rest(pat) => pat.attrs = attrs, 2476 Pat::Slice(pat) => pat.attrs = attrs, 2477 Pat::Struct(pat) => pat.attrs = attrs, 2478 Pat::Tuple(pat) => pat.attrs = attrs, 2479 Pat::TupleStruct(pat) => pat.attrs = attrs, 2480 Pat::Type(_) => unreachable!(), 2481 Pat::Verbatim(_) => {} 2482 Pat::Wild(pat) => pat.attrs = attrs, 2483 } 2484 Ok(pat) 2485 } 2486 } 2487 2488 #[cfg(feature = "full")] 2489 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2490 impl Parse for ExprWhile { parsenull2491 fn parse(input: ParseStream) -> Result<Self> { 2492 let mut attrs = input.call(Attribute::parse_outer)?; 2493 let label: Option<Label> = input.parse()?; 2494 let while_token: Token![while] = input.parse()?; 2495 let cond = Expr::parse_without_eager_brace(input)?; 2496 2497 let content; 2498 let brace_token = braced!(content in input); 2499 attr::parsing::parse_inner(&content, &mut attrs)?; 2500 let stmts = content.call(Block::parse_within)?; 2501 2502 Ok(ExprWhile { 2503 attrs, 2504 label, 2505 while_token, 2506 cond: Box::new(cond), 2507 body: Block { brace_token, stmts }, 2508 }) 2509 } 2510 } 2511 2512 #[cfg(feature = "full")] 2513 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2514 impl Parse for ExprConst { parsenull2515 fn parse(input: ParseStream) -> Result<Self> { 2516 let const_token: Token![const] = input.parse()?; 2517 2518 let content; 2519 let brace_token = braced!(content in input); 2520 let inner_attrs = content.call(Attribute::parse_inner)?; 2521 let stmts = content.call(Block::parse_within)?; 2522 2523 Ok(ExprConst { 2524 attrs: inner_attrs, 2525 const_token, 2526 block: Block { brace_token, stmts }, 2527 }) 2528 } 2529 } 2530 2531 #[cfg(feature = "full")] 2532 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2533 impl Parse for Label { parsenull2534 fn parse(input: ParseStream) -> Result<Self> { 2535 Ok(Label { 2536 name: input.parse()?, 2537 colon_token: input.parse()?, 2538 }) 2539 } 2540 } 2541 2542 #[cfg(feature = "full")] 2543 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2544 impl Parse for Option<Label> { parsenull2545 fn parse(input: ParseStream) -> Result<Self> { 2546 if input.peek(Lifetime) { 2547 input.parse().map(Some) 2548 } else { 2549 Ok(None) 2550 } 2551 } 2552 } 2553 2554 #[cfg(feature = "full")] 2555 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2556 impl Parse for ExprContinue { parsenull2557 fn parse(input: ParseStream) -> Result<Self> { 2558 Ok(ExprContinue { 2559 attrs: Vec::new(), 2560 continue_token: input.parse()?, 2561 label: input.parse()?, 2562 }) 2563 } 2564 } 2565 2566 #[cfg(feature = "full")] expr_breaknull2567 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> { 2568 let break_token: Token![break] = input.parse()?; 2569 2570 let ahead = input.fork(); 2571 let label: Option<Lifetime> = ahead.parse()?; 2572 if label.is_some() && ahead.peek(Token![:]) { 2573 // Not allowed: `break 'label: loop {...}` 2574 // Parentheses are required. `break ('label: loop {...})` 2575 let _ = ambiguous_expr(input, allow_struct)?; 2576 let start_span = label.unwrap().apostrophe; 2577 let end_span = input.cursor().prev_span(); 2578 return Err(crate::error::new2( 2579 start_span, 2580 end_span, 2581 "parentheses required", 2582 )); 2583 } 2584 2585 input.advance_to(&ahead); 2586 let expr = if can_begin_expr(input) && (allow_struct.0 || !input.peek(token::Brace)) { 2587 let expr = ambiguous_expr(input, allow_struct)?; 2588 Some(Box::new(expr)) 2589 } else { 2590 None 2591 }; 2592 2593 Ok(ExprBreak { 2594 attrs: Vec::new(), 2595 break_token, 2596 label, 2597 expr, 2598 }) 2599 } 2600 2601 #[cfg(feature = "full")] expr_returnnull2602 fn expr_return(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> { 2603 Ok(ExprReturn { 2604 attrs: Vec::new(), 2605 return_token: input.parse()?, 2606 expr: { 2607 if can_begin_expr(input) { 2608 // NOTE: return is greedy and eats blocks after it even when in a 2609 // position where structs are not allowed, such as in if statement 2610 // conditions. For example: 2611 // 2612 // if return { println!("A") } {} // Prints "A" 2613 let expr = ambiguous_expr(input, allow_struct)?; 2614 Some(Box::new(expr)) 2615 } else { 2616 None 2617 } 2618 }, 2619 }) 2620 } 2621 2622 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2623 impl Parse for FieldValue { parsenull2624 fn parse(input: ParseStream) -> Result<Self> { 2625 let attrs = input.call(Attribute::parse_outer)?; 2626 let member: Member = input.parse()?; 2627 let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() { 2628 let colon_token: Token![:] = input.parse()?; 2629 let value: Expr = input.parse()?; 2630 (Some(colon_token), value) 2631 } else if let Member::Named(ident) = &member { 2632 let value = Expr::Path(ExprPath { 2633 attrs: Vec::new(), 2634 qself: None, 2635 path: Path::from(ident.clone()), 2636 }); 2637 (None, value) 2638 } else { 2639 unreachable!() 2640 }; 2641 2642 Ok(FieldValue { 2643 attrs, 2644 member, 2645 colon_token, 2646 expr: value, 2647 }) 2648 } 2649 } 2650 2651 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2652 impl Parse for ExprStruct { parsenull2653 fn parse(input: ParseStream) -> Result<Self> { 2654 let (qself, path) = path::parsing::qpath(input, true)?; 2655 expr_struct_helper(input, qself, path) 2656 } 2657 } 2658 expr_struct_helpernull2659 fn expr_struct_helper( 2660 input: ParseStream, 2661 qself: Option<QSelf>, 2662 path: Path, 2663 ) -> Result<ExprStruct> { 2664 let content; 2665 let brace_token = braced!(content in input); 2666 2667 let mut fields = Punctuated::new(); 2668 while !content.is_empty() { 2669 if content.peek(Token![..]) { 2670 return Ok(ExprStruct { 2671 attrs: Vec::new(), 2672 qself, 2673 path, 2674 brace_token, 2675 fields, 2676 dot2_token: Some(content.parse()?), 2677 rest: if content.is_empty() { 2678 None 2679 } else { 2680 Some(Box::new(content.parse()?)) 2681 }, 2682 }); 2683 } 2684 2685 fields.push(content.parse()?); 2686 if content.is_empty() { 2687 break; 2688 } 2689 let punct: Token![,] = content.parse()?; 2690 fields.push_punct(punct); 2691 } 2692 2693 Ok(ExprStruct { 2694 attrs: Vec::new(), 2695 qself, 2696 path, 2697 brace_token, 2698 fields, 2699 dot2_token: None, 2700 rest: None, 2701 }) 2702 } 2703 2704 #[cfg(feature = "full")] 2705 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2706 impl Parse for ExprUnsafe { parsenull2707 fn parse(input: ParseStream) -> Result<Self> { 2708 let unsafe_token: Token![unsafe] = input.parse()?; 2709 2710 let content; 2711 let brace_token = braced!(content in input); 2712 let inner_attrs = content.call(Attribute::parse_inner)?; 2713 let stmts = content.call(Block::parse_within)?; 2714 2715 Ok(ExprUnsafe { 2716 attrs: inner_attrs, 2717 unsafe_token, 2718 block: Block { brace_token, stmts }, 2719 }) 2720 } 2721 } 2722 2723 #[cfg(feature = "full")] 2724 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2725 impl Parse for ExprBlock { parsenull2726 fn parse(input: ParseStream) -> Result<Self> { 2727 let mut attrs = input.call(Attribute::parse_outer)?; 2728 let label: Option<Label> = input.parse()?; 2729 2730 let content; 2731 let brace_token = braced!(content in input); 2732 attr::parsing::parse_inner(&content, &mut attrs)?; 2733 let stmts = content.call(Block::parse_within)?; 2734 2735 Ok(ExprBlock { 2736 attrs, 2737 label, 2738 block: Block { brace_token, stmts }, 2739 }) 2740 } 2741 } 2742 2743 #[cfg(feature = "full")] expr_rangenull2744 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> { 2745 let limits: RangeLimits = input.parse()?; 2746 let end = if matches!(limits, RangeLimits::HalfOpen(_)) 2747 && (input.is_empty() 2748 || input.peek(Token![,]) 2749 || input.peek(Token![;]) 2750 || input.peek(Token![.]) && !input.peek(Token![..]) 2751 || !allow_struct.0 && input.peek(token::Brace)) 2752 { 2753 None 2754 } else { 2755 let to = ambiguous_expr(input, allow_struct)?; 2756 Some(Box::new(to)) 2757 }; 2758 Ok(ExprRange { 2759 attrs: Vec::new(), 2760 start: None, 2761 limits, 2762 end, 2763 }) 2764 } 2765 2766 #[cfg(feature = "full")] 2767 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2768 impl Parse for RangeLimits { parsenull2769 fn parse(input: ParseStream) -> Result<Self> { 2770 let lookahead = input.lookahead1(); 2771 let dot_dot = lookahead.peek(Token![..]); 2772 let dot_dot_eq = dot_dot && lookahead.peek(Token![..=]); 2773 let dot_dot_dot = dot_dot && input.peek(Token![...]); 2774 if dot_dot_eq { 2775 input.parse().map(RangeLimits::Closed) 2776 } else if dot_dot && !dot_dot_dot { 2777 input.parse().map(RangeLimits::HalfOpen) 2778 } else { 2779 Err(lookahead.error()) 2780 } 2781 } 2782 } 2783 2784 #[cfg(feature = "full")] 2785 impl RangeLimits { 2786 pub(crate) fn parse_obsolete(input: ParseStream) -> Result<Self> { 2787 let lookahead = input.lookahead1(); 2788 let dot_dot = lookahead.peek(Token![..]); 2789 let dot_dot_eq = dot_dot && lookahead.peek(Token![..=]); 2790 let dot_dot_dot = dot_dot && input.peek(Token![...]); 2791 if dot_dot_eq { 2792 input.parse().map(RangeLimits::Closed) 2793 } else if dot_dot_dot { 2794 let dot3: Token![...] = input.parse()?; 2795 Ok(RangeLimits::Closed(Token)) 2796 } else if dot_dot { 2797 input.parse().map(RangeLimits::HalfOpen) 2798 } else { 2799 Err(lookahead.error()) 2800 } 2801 } 2802 } 2803 2804 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2805 impl Parse for ExprPath { parsenull2806 fn parse(input: ParseStream) -> Result<Self> { 2807 #[cfg(not(feature = "full"))] 2808 let attrs = Vec::new(); 2809 #[cfg(feature = "full")] 2810 let attrs = input.call(Attribute::parse_outer)?; 2811 2812 let (qself, path) = path::parsing::qpath(input, true)?; 2813 2814 Ok(ExprPath { attrs, qself, path }) 2815 } 2816 } 2817 2818 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2819 impl Parse for Member { parsenull2820 fn parse(input: ParseStream) -> Result<Self> { 2821 if input.peek(Ident) { 2822 input.parse().map(Member::Named) 2823 } else if input.peek(LitInt) { 2824 input.parse().map(Member::Unnamed) 2825 } else { 2826 Err(input.error("expected identifier or integer")) 2827 } 2828 } 2829 } 2830 2831 #[cfg(feature = "full")] 2832 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2833 impl Parse for Arm { parsenull2834 fn parse(input: ParseStream) -> Result<Arm> { 2835 let requires_comma; 2836 Ok(Arm { 2837 attrs: input.call(Attribute::parse_outer)?, 2838 pat: Pat::parse_multi_with_leading_vert(input)?, 2839 guard: { 2840 if input.peek(Token![if]) { 2841 let if_token: Token![if] = input.parse()?; 2842 let guard: Expr = input.parse()?; 2843 Some((if_token, Box::new(guard))) 2844 } else { 2845 None 2846 } 2847 }, 2848 fat_arrow_token: input.parse()?, 2849 body: { 2850 let body = input.call(expr_early)?; 2851 requires_comma = requires_terminator(&body); 2852 Box::new(body) 2853 }, 2854 comma: { 2855 if requires_comma && !input.is_empty() { 2856 Some(input.parse()?) 2857 } else { 2858 input.parse()? 2859 } 2860 }, 2861 }) 2862 } 2863 } 2864 2865 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 2866 impl Parse for Index { parsenull2867 fn parse(input: ParseStream) -> Result<Self> { 2868 let lit: LitInt = input.parse()?; 2869 if lit.suffix().is_empty() { 2870 Ok(Index { 2871 index: lit 2872 .base10_digits() 2873 .parse() 2874 .map_err(|err| Error::new(lit.span(), err))?, 2875 span: lit.span(), 2876 }) 2877 } else { 2878 Err(Error::new(lit.span(), "expected unsuffixed integer")) 2879 } 2880 } 2881 } 2882 multi_indexnull2883 fn multi_index(e: &mut Expr, dot_token: &mut Token![.], float: LitFloat) -> Result<bool> { 2884 let float_token = float.token(); 2885 let float_span = float_token.span(); 2886 let mut float_repr = float_token.to_string(); 2887 let trailing_dot = float_repr.ends_with('.'); 2888 if trailing_dot { 2889 float_repr.truncate(float_repr.len() - 1); 2890 } 2891 2892 let mut offset = 0; 2893 for part in float_repr.split('.') { 2894 let mut index: Index = 2895 crate::parse_str(part).map_err(|err| Error::new(float_span, err))?; 2896 let part_end = offset + part.len(); 2897 index.span = float_token.subspan(offset..part_end).unwrap_or(float_span); 2898 2899 let base = mem::replace(e, Expr::DUMMY); 2900 *e = Expr::Field(ExprField { 2901 attrs: Vec::new(), 2902 base: Box::new(base), 2903 dot_token: Token, 2904 member: Member::Unnamed(index), 2905 }); 2906 2907 let dot_span = float_token 2908 .subspan(part_end..part_end + 1) 2909 .unwrap_or(float_span); 2910 *dot_token = Token; 2911 offset = part_end + 1; 2912 } 2913 2914 Ok(!trailing_dot) 2915 } 2916 2917 impl Member { 2918 pub(crate) fn is_named(&self) -> bool { 2919 match self { 2920 Member::Named(_) => true, 2921 Member::Unnamed(_) => false, 2922 } 2923 } 2924 } 2925 check_castnull2926 fn check_cast(input: ParseStream) -> Result<()> { 2927 let kind = if input.peek(Token![.]) && !input.peek(Token![..]) { 2928 if input.peek2(Token![await]) { 2929 "`.await`" 2930 } else if input.peek2(Ident) && (input.peek3(token::Paren) || input.peek3(Token![::])) { 2931 "a method call" 2932 } else { 2933 "a field access" 2934 } 2935 } else if input.peek(Token![?]) { 2936 "`?`" 2937 } else if input.peek(token::Bracket) { 2938 "indexing" 2939 } else if input.peek(token::Paren) { 2940 "a function call" 2941 } else { 2942 return Ok(()); 2943 }; 2944 let msg = format!("casts cannot be followed by {}", kind); 2945 Err(input.error(msg)) 2946 } 2947 } 2948 2949 #[cfg(feature = "printing")] 2950 pub(crate) mod printing { 2951 use super::*; 2952 #[cfg(feature = "full")] 2953 use crate::attr::FilterAttrs; 2954 use proc_macro2::{Literal, TokenStream}; 2955 use quote::{ToTokens, TokenStreamExt}; 2956 2957 // If the given expression is a bare `ExprStruct`, wraps it in parenthesis 2958 // before appending it to `TokenStream`. 2959 #[cfg(feature = "full")] wrap_bare_structnull2960 fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) { 2961 if let Expr::Struct(_) = *e { 2962 token::Paren::default().surround(tokens, |tokens| { 2963 e.to_tokens(tokens); 2964 }); 2965 } else { 2966 e.to_tokens(tokens); 2967 } 2968 } 2969 2970 #[cfg(feature = "full")] 2971 pub(crate) fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) { 2972 tokens.append_all(attrs.outer()); 2973 } 2974 2975 #[cfg(feature = "full")] inner_attrs_to_tokensnull2976 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) { 2977 tokens.append_all(attrs.inner()); 2978 } 2979 2980 #[cfg(not(feature = "full"))] 2981 pub(crate) fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {} 2982 2983 #[cfg(feature = "full")] 2984 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 2985 impl ToTokens for ExprArray { to_tokensnull2986 fn to_tokens(&self, tokens: &mut TokenStream) { 2987 outer_attrs_to_tokens(&self.attrs, tokens); 2988 self.bracket_token.surround(tokens, |tokens| { 2989 self.elems.to_tokens(tokens); 2990 }); 2991 } 2992 } 2993 2994 #[cfg(feature = "full")] 2995 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 2996 impl ToTokens for ExprAssign { to_tokensnull2997 fn to_tokens(&self, tokens: &mut TokenStream) { 2998 outer_attrs_to_tokens(&self.attrs, tokens); 2999 self.left.to_tokens(tokens); 3000 self.eq_token.to_tokens(tokens); 3001 self.right.to_tokens(tokens); 3002 } 3003 } 3004 3005 #[cfg(feature = "full")] 3006 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3007 impl ToTokens for ExprAsync { to_tokensnull3008 fn to_tokens(&self, tokens: &mut TokenStream) { 3009 outer_attrs_to_tokens(&self.attrs, tokens); 3010 self.async_token.to_tokens(tokens); 3011 self.capture.to_tokens(tokens); 3012 self.block.to_tokens(tokens); 3013 } 3014 } 3015 3016 #[cfg(feature = "full")] 3017 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3018 impl ToTokens for ExprAwait { to_tokensnull3019 fn to_tokens(&self, tokens: &mut TokenStream) { 3020 outer_attrs_to_tokens(&self.attrs, tokens); 3021 self.base.to_tokens(tokens); 3022 self.dot_token.to_tokens(tokens); 3023 self.await_token.to_tokens(tokens); 3024 } 3025 } 3026 3027 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3028 impl ToTokens for ExprBinary { to_tokensnull3029 fn to_tokens(&self, tokens: &mut TokenStream) { 3030 outer_attrs_to_tokens(&self.attrs, tokens); 3031 self.left.to_tokens(tokens); 3032 self.op.to_tokens(tokens); 3033 self.right.to_tokens(tokens); 3034 } 3035 } 3036 3037 #[cfg(feature = "full")] 3038 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3039 impl ToTokens for ExprBlock { to_tokensnull3040 fn to_tokens(&self, tokens: &mut TokenStream) { 3041 outer_attrs_to_tokens(&self.attrs, tokens); 3042 self.label.to_tokens(tokens); 3043 self.block.brace_token.surround(tokens, |tokens| { 3044 inner_attrs_to_tokens(&self.attrs, tokens); 3045 tokens.append_all(&self.block.stmts); 3046 }); 3047 } 3048 } 3049 3050 #[cfg(feature = "full")] 3051 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3052 impl ToTokens for ExprBreak { to_tokensnull3053 fn to_tokens(&self, tokens: &mut TokenStream) { 3054 outer_attrs_to_tokens(&self.attrs, tokens); 3055 self.break_token.to_tokens(tokens); 3056 self.label.to_tokens(tokens); 3057 self.expr.to_tokens(tokens); 3058 } 3059 } 3060 3061 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3062 impl ToTokens for ExprCall { to_tokensnull3063 fn to_tokens(&self, tokens: &mut TokenStream) { 3064 outer_attrs_to_tokens(&self.attrs, tokens); 3065 self.func.to_tokens(tokens); 3066 self.paren_token.surround(tokens, |tokens| { 3067 self.args.to_tokens(tokens); 3068 }); 3069 } 3070 } 3071 3072 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3073 impl ToTokens for ExprCast { to_tokensnull3074 fn to_tokens(&self, tokens: &mut TokenStream) { 3075 outer_attrs_to_tokens(&self.attrs, tokens); 3076 self.expr.to_tokens(tokens); 3077 self.as_token.to_tokens(tokens); 3078 self.ty.to_tokens(tokens); 3079 } 3080 } 3081 3082 #[cfg(feature = "full")] 3083 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3084 impl ToTokens for ExprClosure { to_tokensnull3085 fn to_tokens(&self, tokens: &mut TokenStream) { 3086 outer_attrs_to_tokens(&self.attrs, tokens); 3087 self.lifetimes.to_tokens(tokens); 3088 self.constness.to_tokens(tokens); 3089 self.movability.to_tokens(tokens); 3090 self.asyncness.to_tokens(tokens); 3091 self.capture.to_tokens(tokens); 3092 self.or1_token.to_tokens(tokens); 3093 self.inputs.to_tokens(tokens); 3094 self.or2_token.to_tokens(tokens); 3095 self.output.to_tokens(tokens); 3096 self.body.to_tokens(tokens); 3097 } 3098 } 3099 3100 #[cfg(feature = "full")] 3101 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3102 impl ToTokens for ExprConst { to_tokensnull3103 fn to_tokens(&self, tokens: &mut TokenStream) { 3104 outer_attrs_to_tokens(&self.attrs, tokens); 3105 self.const_token.to_tokens(tokens); 3106 self.block.brace_token.surround(tokens, |tokens| { 3107 inner_attrs_to_tokens(&self.attrs, tokens); 3108 tokens.append_all(&self.block.stmts); 3109 }); 3110 } 3111 } 3112 3113 #[cfg(feature = "full")] 3114 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3115 impl ToTokens for ExprContinue { to_tokensnull3116 fn to_tokens(&self, tokens: &mut TokenStream) { 3117 outer_attrs_to_tokens(&self.attrs, tokens); 3118 self.continue_token.to_tokens(tokens); 3119 self.label.to_tokens(tokens); 3120 } 3121 } 3122 3123 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3124 impl ToTokens for ExprField { to_tokensnull3125 fn to_tokens(&self, tokens: &mut TokenStream) { 3126 outer_attrs_to_tokens(&self.attrs, tokens); 3127 self.base.to_tokens(tokens); 3128 self.dot_token.to_tokens(tokens); 3129 self.member.to_tokens(tokens); 3130 } 3131 } 3132 3133 #[cfg(feature = "full")] 3134 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3135 impl ToTokens for ExprForLoop { to_tokensnull3136 fn to_tokens(&self, tokens: &mut TokenStream) { 3137 outer_attrs_to_tokens(&self.attrs, tokens); 3138 self.label.to_tokens(tokens); 3139 self.for_token.to_tokens(tokens); 3140 self.pat.to_tokens(tokens); 3141 self.in_token.to_tokens(tokens); 3142 wrap_bare_struct(tokens, &self.expr); 3143 self.body.brace_token.surround(tokens, |tokens| { 3144 inner_attrs_to_tokens(&self.attrs, tokens); 3145 tokens.append_all(&self.body.stmts); 3146 }); 3147 } 3148 } 3149 3150 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3151 impl ToTokens for ExprGroup { to_tokensnull3152 fn to_tokens(&self, tokens: &mut TokenStream) { 3153 outer_attrs_to_tokens(&self.attrs, tokens); 3154 self.group_token.surround(tokens, |tokens| { 3155 self.expr.to_tokens(tokens); 3156 }); 3157 } 3158 } 3159 3160 #[cfg(feature = "full")] 3161 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3162 impl ToTokens for ExprIf { to_tokensnull3163 fn to_tokens(&self, tokens: &mut TokenStream) { 3164 outer_attrs_to_tokens(&self.attrs, tokens); 3165 self.if_token.to_tokens(tokens); 3166 wrap_bare_struct(tokens, &self.cond); 3167 self.then_branch.to_tokens(tokens); 3168 if let Some((else_token, else_)) = &self.else_branch { 3169 else_token.to_tokens(tokens); 3170 // If we are not one of the valid expressions to exist in an else 3171 // clause, wrap ourselves in a block. 3172 match **else_ { 3173 Expr::If(_) | Expr::Block(_) => else_.to_tokens(tokens), 3174 _ => token::Brace::default().surround(tokens, |tokens| else_.to_tokens(tokens)), 3175 } 3176 } 3177 } 3178 } 3179 3180 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3181 impl ToTokens for ExprIndex { to_tokensnull3182 fn to_tokens(&self, tokens: &mut TokenStream) { 3183 outer_attrs_to_tokens(&self.attrs, tokens); 3184 self.expr.to_tokens(tokens); 3185 self.bracket_token.surround(tokens, |tokens| { 3186 self.index.to_tokens(tokens); 3187 }); 3188 } 3189 } 3190 3191 #[cfg(feature = "full")] 3192 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3193 impl ToTokens for ExprInfer { to_tokensnull3194 fn to_tokens(&self, tokens: &mut TokenStream) { 3195 outer_attrs_to_tokens(&self.attrs, tokens); 3196 self.underscore_token.to_tokens(tokens); 3197 } 3198 } 3199 3200 #[cfg(feature = "full")] 3201 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3202 impl ToTokens for ExprLet { to_tokensnull3203 fn to_tokens(&self, tokens: &mut TokenStream) { 3204 outer_attrs_to_tokens(&self.attrs, tokens); 3205 self.let_token.to_tokens(tokens); 3206 self.pat.to_tokens(tokens); 3207 self.eq_token.to_tokens(tokens); 3208 wrap_bare_struct(tokens, &self.expr); 3209 } 3210 } 3211 3212 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3213 impl ToTokens for ExprLit { to_tokensnull3214 fn to_tokens(&self, tokens: &mut TokenStream) { 3215 outer_attrs_to_tokens(&self.attrs, tokens); 3216 self.lit.to_tokens(tokens); 3217 } 3218 } 3219 3220 #[cfg(feature = "full")] 3221 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3222 impl ToTokens for ExprLoop { to_tokensnull3223 fn to_tokens(&self, tokens: &mut TokenStream) { 3224 outer_attrs_to_tokens(&self.attrs, tokens); 3225 self.label.to_tokens(tokens); 3226 self.loop_token.to_tokens(tokens); 3227 self.body.brace_token.surround(tokens, |tokens| { 3228 inner_attrs_to_tokens(&self.attrs, tokens); 3229 tokens.append_all(&self.body.stmts); 3230 }); 3231 } 3232 } 3233 3234 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3235 impl ToTokens for ExprMacro { to_tokensnull3236 fn to_tokens(&self, tokens: &mut TokenStream) { 3237 outer_attrs_to_tokens(&self.attrs, tokens); 3238 self.mac.to_tokens(tokens); 3239 } 3240 } 3241 3242 #[cfg(feature = "full")] 3243 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3244 impl ToTokens for ExprMatch { to_tokensnull3245 fn to_tokens(&self, tokens: &mut TokenStream) { 3246 outer_attrs_to_tokens(&self.attrs, tokens); 3247 self.match_token.to_tokens(tokens); 3248 wrap_bare_struct(tokens, &self.expr); 3249 self.brace_token.surround(tokens, |tokens| { 3250 inner_attrs_to_tokens(&self.attrs, tokens); 3251 for (i, arm) in self.arms.iter().enumerate() { 3252 arm.to_tokens(tokens); 3253 // Ensure that we have a comma after a non-block arm, except 3254 // for the last one. 3255 let is_last = i == self.arms.len() - 1; 3256 if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() { 3257 <Token![,]>::default().to_tokens(tokens); 3258 } 3259 } 3260 }); 3261 } 3262 } 3263 3264 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3265 impl ToTokens for ExprMethodCall { to_tokensnull3266 fn to_tokens(&self, tokens: &mut TokenStream) { 3267 outer_attrs_to_tokens(&self.attrs, tokens); 3268 self.receiver.to_tokens(tokens); 3269 self.dot_token.to_tokens(tokens); 3270 self.method.to_tokens(tokens); 3271 self.turbofish.to_tokens(tokens); 3272 self.paren_token.surround(tokens, |tokens| { 3273 self.args.to_tokens(tokens); 3274 }); 3275 } 3276 } 3277 3278 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3279 impl ToTokens for ExprParen { to_tokensnull3280 fn to_tokens(&self, tokens: &mut TokenStream) { 3281 outer_attrs_to_tokens(&self.attrs, tokens); 3282 self.paren_token.surround(tokens, |tokens| { 3283 self.expr.to_tokens(tokens); 3284 }); 3285 } 3286 } 3287 3288 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3289 impl ToTokens for ExprPath { to_tokensnull3290 fn to_tokens(&self, tokens: &mut TokenStream) { 3291 outer_attrs_to_tokens(&self.attrs, tokens); 3292 path::printing::print_path(tokens, &self.qself, &self.path); 3293 } 3294 } 3295 3296 #[cfg(feature = "full")] 3297 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3298 impl ToTokens for ExprRange { to_tokensnull3299 fn to_tokens(&self, tokens: &mut TokenStream) { 3300 outer_attrs_to_tokens(&self.attrs, tokens); 3301 self.start.to_tokens(tokens); 3302 self.limits.to_tokens(tokens); 3303 self.end.to_tokens(tokens); 3304 } 3305 } 3306 3307 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3308 impl ToTokens for ExprReference { to_tokensnull3309 fn to_tokens(&self, tokens: &mut TokenStream) { 3310 outer_attrs_to_tokens(&self.attrs, tokens); 3311 self.and_token.to_tokens(tokens); 3312 self.mutability.to_tokens(tokens); 3313 self.expr.to_tokens(tokens); 3314 } 3315 } 3316 3317 #[cfg(feature = "full")] 3318 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3319 impl ToTokens for ExprRepeat { to_tokensnull3320 fn to_tokens(&self, tokens: &mut TokenStream) { 3321 outer_attrs_to_tokens(&self.attrs, tokens); 3322 self.bracket_token.surround(tokens, |tokens| { 3323 self.expr.to_tokens(tokens); 3324 self.semi_token.to_tokens(tokens); 3325 self.len.to_tokens(tokens); 3326 }); 3327 } 3328 } 3329 3330 #[cfg(feature = "full")] 3331 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3332 impl ToTokens for ExprReturn { to_tokensnull3333 fn to_tokens(&self, tokens: &mut TokenStream) { 3334 outer_attrs_to_tokens(&self.attrs, tokens); 3335 self.return_token.to_tokens(tokens); 3336 self.expr.to_tokens(tokens); 3337 } 3338 } 3339 3340 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3341 impl ToTokens for ExprStruct { to_tokensnull3342 fn to_tokens(&self, tokens: &mut TokenStream) { 3343 outer_attrs_to_tokens(&self.attrs, tokens); 3344 path::printing::print_path(tokens, &self.qself, &self.path); 3345 self.brace_token.surround(tokens, |tokens| { 3346 self.fields.to_tokens(tokens); 3347 if let Some(dot2_token) = &self.dot2_token { 3348 dot2_token.to_tokens(tokens); 3349 } else if self.rest.is_some() { 3350 Token).to_tokens(tokens); 3351 } 3352 self.rest.to_tokens(tokens); 3353 }); 3354 } 3355 } 3356 3357 #[cfg(feature = "full")] 3358 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3359 impl ToTokens for ExprTry { to_tokensnull3360 fn to_tokens(&self, tokens: &mut TokenStream) { 3361 outer_attrs_to_tokens(&self.attrs, tokens); 3362 self.expr.to_tokens(tokens); 3363 self.question_token.to_tokens(tokens); 3364 } 3365 } 3366 3367 #[cfg(feature = "full")] 3368 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3369 impl ToTokens for ExprTryBlock { to_tokensnull3370 fn to_tokens(&self, tokens: &mut TokenStream) { 3371 outer_attrs_to_tokens(&self.attrs, tokens); 3372 self.try_token.to_tokens(tokens); 3373 self.block.to_tokens(tokens); 3374 } 3375 } 3376 3377 #[cfg(feature = "full")] 3378 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3379 impl ToTokens for ExprTuple { to_tokensnull3380 fn to_tokens(&self, tokens: &mut TokenStream) { 3381 outer_attrs_to_tokens(&self.attrs, tokens); 3382 self.paren_token.surround(tokens, |tokens| { 3383 self.elems.to_tokens(tokens); 3384 // If we only have one argument, we need a trailing comma to 3385 // distinguish ExprTuple from ExprParen. 3386 if self.elems.len() == 1 && !self.elems.trailing_punct() { 3387 <Token![,]>::default().to_tokens(tokens); 3388 } 3389 }); 3390 } 3391 } 3392 3393 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3394 impl ToTokens for ExprUnary { to_tokensnull3395 fn to_tokens(&self, tokens: &mut TokenStream) { 3396 outer_attrs_to_tokens(&self.attrs, tokens); 3397 self.op.to_tokens(tokens); 3398 self.expr.to_tokens(tokens); 3399 } 3400 } 3401 3402 #[cfg(feature = "full")] 3403 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3404 impl ToTokens for ExprUnsafe { to_tokensnull3405 fn to_tokens(&self, tokens: &mut TokenStream) { 3406 outer_attrs_to_tokens(&self.attrs, tokens); 3407 self.unsafe_token.to_tokens(tokens); 3408 self.block.brace_token.surround(tokens, |tokens| { 3409 inner_attrs_to_tokens(&self.attrs, tokens); 3410 tokens.append_all(&self.block.stmts); 3411 }); 3412 } 3413 } 3414 3415 #[cfg(feature = "full")] 3416 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3417 impl ToTokens for ExprWhile { to_tokensnull3418 fn to_tokens(&self, tokens: &mut TokenStream) { 3419 outer_attrs_to_tokens(&self.attrs, tokens); 3420 self.label.to_tokens(tokens); 3421 self.while_token.to_tokens(tokens); 3422 wrap_bare_struct(tokens, &self.cond); 3423 self.body.brace_token.surround(tokens, |tokens| { 3424 inner_attrs_to_tokens(&self.attrs, tokens); 3425 tokens.append_all(&self.body.stmts); 3426 }); 3427 } 3428 } 3429 3430 #[cfg(feature = "full")] 3431 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3432 impl ToTokens for ExprYield { to_tokensnull3433 fn to_tokens(&self, tokens: &mut TokenStream) { 3434 outer_attrs_to_tokens(&self.attrs, tokens); 3435 self.yield_token.to_tokens(tokens); 3436 self.expr.to_tokens(tokens); 3437 } 3438 } 3439 3440 #[cfg(feature = "full")] 3441 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3442 impl ToTokens for Arm { to_tokensnull3443 fn to_tokens(&self, tokens: &mut TokenStream) { 3444 tokens.append_all(&self.attrs); 3445 self.pat.to_tokens(tokens); 3446 if let Some((if_token, guard)) = &self.guard { 3447 if_token.to_tokens(tokens); 3448 guard.to_tokens(tokens); 3449 } 3450 self.fat_arrow_token.to_tokens(tokens); 3451 self.body.to_tokens(tokens); 3452 self.comma.to_tokens(tokens); 3453 } 3454 } 3455 3456 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3457 impl ToTokens for FieldValue { to_tokensnull3458 fn to_tokens(&self, tokens: &mut TokenStream) { 3459 outer_attrs_to_tokens(&self.attrs, tokens); 3460 self.member.to_tokens(tokens); 3461 if let Some(colon_token) = &self.colon_token { 3462 colon_token.to_tokens(tokens); 3463 self.expr.to_tokens(tokens); 3464 } 3465 } 3466 } 3467 3468 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3469 impl ToTokens for Index { to_tokensnull3470 fn to_tokens(&self, tokens: &mut TokenStream) { 3471 let mut lit = Literal::i64_unsuffixed(i64::from(self.index)); 3472 lit.set_span(self.span); 3473 tokens.append(lit); 3474 } 3475 } 3476 3477 #[cfg(feature = "full")] 3478 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3479 impl ToTokens for Label { to_tokensnull3480 fn to_tokens(&self, tokens: &mut TokenStream) { 3481 self.name.to_tokens(tokens); 3482 self.colon_token.to_tokens(tokens); 3483 } 3484 } 3485 3486 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3487 impl ToTokens for Member { to_tokensnull3488 fn to_tokens(&self, tokens: &mut TokenStream) { 3489 match self { 3490 Member::Named(ident) => ident.to_tokens(tokens), 3491 Member::Unnamed(index) => index.to_tokens(tokens), 3492 } 3493 } 3494 } 3495 3496 #[cfg(feature = "full")] 3497 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 3498 impl ToTokens for RangeLimits { to_tokensnull3499 fn to_tokens(&self, tokens: &mut TokenStream) { 3500 match self { 3501 RangeLimits::HalfOpen(t) => t.to_tokens(tokens), 3502 RangeLimits::Closed(t) => t.to_tokens(tokens), 3503 } 3504 } 3505 } 3506 } 3507