1 use crate::attr::Attribute; 2 #[cfg(all(feature = "parsing", feature = "full"))] 3 use crate::error::Result; 4 #[cfg(feature = "parsing")] 5 use crate::ext::IdentExt as _; 6 #[cfg(feature = "full")] 7 use crate::generics::BoundLifetimes; 8 use crate::ident::Ident; 9 #[cfg(any(feature = "parsing", feature = "full"))] 10 use crate::lifetime::Lifetime; 11 use crate::lit::Lit; 12 use crate::mac::Macro; 13 use crate::op::{BinOp, UnOp}; 14 #[cfg(feature = "parsing")] 15 use crate::parse::ParseStream; 16 #[cfg(feature = "full")] 17 use crate::pat::Pat; 18 use crate::path::{AngleBracketedGenericArguments, Path, QSelf}; 19 use crate::punctuated::Punctuated; 20 #[cfg(feature = "full")] 21 use crate::stmt::Block; 22 use crate::token; 23 #[cfg(feature = "full")] 24 use crate::ty::ReturnType; 25 use crate::ty::Type; 26 use proc_macro2::{Span, TokenStream}; 27 #[cfg(feature = "printing")] 28 use quote::IdentFragment; 29 #[cfg(feature = "printing")] 30 use std::fmt::{self, Display}; 31 use std::hash::{Hash, Hasher}; 32 #[cfg(all(feature = "parsing", feature = "full"))] 33 use std::mem; 34 35 ast_enum_of_structs! { 36 /// A Rust expression. 37 /// 38 /// *This type is available only if Syn is built with the `"derive"` or `"full"` 39 /// feature, but most of the variants are not available unless "full" is enabled.* 40 /// 41 /// # Syntax tree enums 42 /// 43 /// This type is a syntax tree enum. In Syn this and other syntax tree enums 44 /// are designed to be traversed using the following rebinding idiom. 45 /// 46 /// ``` 47 /// # use syn::Expr; 48 /// # 49 /// # fn example(expr: Expr) { 50 /// # const IGNORE: &str = stringify! { 51 /// let expr: Expr = /* ... */; 52 /// # }; 53 /// match expr { 54 /// Expr::MethodCall(expr) => { 55 /// /* ... */ 56 /// } 57 /// Expr::Cast(expr) => { 58 /// /* ... */ 59 /// } 60 /// Expr::If(expr) => { 61 /// /* ... */ 62 /// } 63 /// 64 /// /* ... */ 65 /// # _ => {} 66 /// # } 67 /// # } 68 /// ``` 69 /// 70 /// We begin with a variable `expr` of type `Expr` that has no fields 71 /// (because it is an enum), and by matching on it and rebinding a variable 72 /// with the same name `expr` we effectively imbue our variable with all of 73 /// the data fields provided by the variant that it turned out to be. So for 74 /// example above if we ended up in the `MethodCall` case then we get to use 75 /// `expr.receiver`, `expr.args` etc; if we ended up in the `If` case we get 76 /// to use `expr.cond`, `expr.then_branch`, `expr.else_branch`. 77 /// 78 /// This approach avoids repeating the variant names twice on every line. 79 /// 80 /// ``` 81 /// # use syn::{Expr, ExprMethodCall}; 82 /// # 83 /// # fn example(expr: Expr) { 84 /// // Repetitive; recommend not doing this. 85 /// match expr { 86 /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => { 87 /// # } 88 /// # _ => {} 89 /// # } 90 /// # } 91 /// ``` 92 /// 93 /// In general, the name to which a syntax tree enum variant is bound should 94 /// be a suitable name for the complete syntax tree enum type. 95 /// 96 /// ``` 97 /// # use syn::{Expr, ExprField}; 98 /// # 99 /// # fn example(discriminant: ExprField) { 100 /// // Binding is called `base` which is the name I would use if I were 101 /// // assigning `*discriminant.base` without an `if let`. 102 /// if let Expr::Tuple(base) = *discriminant.base { 103 /// # } 104 /// # } 105 /// ``` 106 /// 107 /// A sign that you may not be choosing the right variable names is if you 108 /// see names getting repeated in your code, like accessing 109 /// `receiver.receiver` or `pat.pat` or `cond.cond`. 110 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 111 #[non_exhaustive] 112 pub enum Expr { 113 /// A slice literal expression: `[a, b, c, d]`. 114 Array(ExprArray), 115 116 /// An assignment expression: `a = compute()`. 117 Assign(ExprAssign), 118 119 /// An async block: `async { ... }`. 120 Async(ExprAsync), 121 122 /// An await expression: `fut.await`. 123 Await(ExprAwait), 124 125 /// A binary operation: `a + b`, `a += b`. 126 Binary(ExprBinary), 127 128 /// A blocked scope: `{ ... }`. 129 Block(ExprBlock), 130 131 /// A `break`, with an optional label to break and an optional 132 /// expression. 133 Break(ExprBreak), 134 135 /// A function call expression: `invoke(a, b)`. 136 Call(ExprCall), 137 138 /// A cast expression: `foo as f64`. 139 Cast(ExprCast), 140 141 /// A closure expression: `|a, b| a + b`. 142 Closure(ExprClosure), 143 144 /// A const block: `const { ... }`. 145 Const(ExprConst), 146 147 /// A `continue`, with an optional label. 148 Continue(ExprContinue), 149 150 /// Access of a named struct field (`obj.k`) or unnamed tuple struct 151 /// field (`obj.0`). 152 Field(ExprField), 153 154 /// A for loop: `for pat in expr { ... }`. 155 ForLoop(ExprForLoop), 156 157 /// An expression contained within invisible delimiters. 158 /// 159 /// This variant is important for faithfully representing the precedence 160 /// of expressions and is related to `None`-delimited spans in a 161 /// `TokenStream`. 162 Group(ExprGroup), 163 164 /// An `if` expression with an optional `else` block: `if expr { ... } 165 /// else { ... }`. 166 /// 167 /// The `else` branch expression may only be an `If` or `Block` 168 /// expression, not any of the other types of expression. 169 If(ExprIf), 170 171 /// A square bracketed indexing expression: `vector[2]`. 172 Index(ExprIndex), 173 174 /// The inferred value of a const generic argument, denoted `_`. 175 Infer(ExprInfer), 176 177 /// A `let` guard: `let Some(x) = opt`. 178 Let(ExprLet), 179 180 /// A literal in place of an expression: `1`, `"foo"`. 181 Lit(ExprLit), 182 183 /// Conditionless loop: `loop { ... }`. 184 Loop(ExprLoop), 185 186 /// A macro invocation expression: `format!("{}", q)`. 187 Macro(ExprMacro), 188 189 /// A `match` expression: `match n { Some(n) => {}, None => {} }`. 190 Match(ExprMatch), 191 192 /// A method call expression: `x.foo::<T>(a, b)`. 193 MethodCall(ExprMethodCall), 194 195 /// A parenthesized expression: `(a + b)`. 196 Paren(ExprParen), 197 198 /// A path like `std::mem::replace` possibly containing generic 199 /// parameters and a qualified self-type. 200 /// 201 /// A plain identifier like `x` is a path of length 1. 202 Path(ExprPath), 203 204 /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`. 205 Range(ExprRange), 206 207 /// Address-of operation: `&raw const place` or `&raw mut place`. 208 RawAddr(ExprRawAddr), 209 210 /// A referencing operation: `&a` or `&mut a`. 211 Reference(ExprReference), 212 213 /// An array literal constructed from one repeated element: `[0u8; N]`. 214 Repeat(ExprRepeat), 215 216 /// A `return`, with an optional value to be returned. 217 Return(ExprReturn), 218 219 /// A struct literal expression: `Point { x: 1, y: 1 }`. 220 /// 221 /// The `rest` provides the value of the remaining fields as in `S { a: 222 /// 1, b: 1, ..rest }`. 223 Struct(ExprStruct), 224 225 /// A try-expression: `expr?`. 226 Try(ExprTry), 227 228 /// A try block: `try { ... }`. 229 TryBlock(ExprTryBlock), 230 231 /// A tuple expression: `(a, b, c, d)`. 232 Tuple(ExprTuple), 233 234 /// A unary operation: `!x`, `*x`. 235 Unary(ExprUnary), 236 237 /// An unsafe block: `unsafe { ... }`. 238 Unsafe(ExprUnsafe), 239 240 /// Tokens in expression position not interpreted by Syn. 241 Verbatim(TokenStream), 242 243 /// A while loop: `while expr { ... }`. 244 While(ExprWhile), 245 246 /// A yield expression: `yield expr`. 247 Yield(ExprYield), 248 249 // For testing exhaustiveness in downstream code, use the following idiom: 250 // 251 // match expr { 252 // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))] 253 // 254 // Expr::Array(expr) => {...} 255 // Expr::Assign(expr) => {...} 256 // ... 257 // Expr::Yield(expr) => {...} 258 // 259 // _ => { /* some sane fallback */ } 260 // } 261 // 262 // This way we fail your tests but don't break your library when adding 263 // a variant. You will be notified by a test failure when a variant is 264 // added, so that you can add code to handle it, but your library will 265 // continue to compile and work for downstream users in the interim. 266 } 267 } 268 269 ast_struct! { 270 /// A slice literal expression: `[a, b, c, d]`. 271 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 272 pub struct ExprArray #full { 273 pub attrs: Vec<Attribute>, 274 pub bracket_token: token::Bracket, 275 pub elems: Punctuated<Expr, Token![,]>, 276 } 277 } 278 279 ast_struct! { 280 /// An assignment expression: `a = compute()`. 281 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 282 pub struct ExprAssign #full { 283 pub attrs: Vec<Attribute>, 284 pub left: Box<Expr>, 285 pub eq_token: Token![=], 286 pub right: Box<Expr>, 287 } 288 } 289 290 ast_struct! { 291 /// An async block: `async { ... }`. 292 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 293 pub struct ExprAsync #full { 294 pub attrs: Vec<Attribute>, 295 pub async_token: Token![async], 296 pub capture: Option<Token![move]>, 297 pub block: Block, 298 } 299 } 300 301 ast_struct! { 302 /// An await expression: `fut.await`. 303 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 304 pub struct ExprAwait #full { 305 pub attrs: Vec<Attribute>, 306 pub base: Box<Expr>, 307 pub dot_token: Token![.], 308 pub await_token: Token![await], 309 } 310 } 311 312 ast_struct! { 313 /// A binary operation: `a + b`, `a += b`. 314 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 315 pub struct ExprBinary { 316 pub attrs: Vec<Attribute>, 317 pub left: Box<Expr>, 318 pub op: BinOp, 319 pub right: Box<Expr>, 320 } 321 } 322 323 ast_struct! { 324 /// A blocked scope: `{ ... }`. 325 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 326 pub struct ExprBlock #full { 327 pub attrs: Vec<Attribute>, 328 pub label: Option<Label>, 329 pub block: Block, 330 } 331 } 332 333 ast_struct! { 334 /// A `break`, with an optional label to break and an optional 335 /// expression. 336 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 337 pub struct ExprBreak #full { 338 pub attrs: Vec<Attribute>, 339 pub break_token: Token![break], 340 pub label: Option<Lifetime>, 341 pub expr: Option<Box<Expr>>, 342 } 343 } 344 345 ast_struct! { 346 /// A function call expression: `invoke(a, b)`. 347 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 348 pub struct ExprCall { 349 pub attrs: Vec<Attribute>, 350 pub func: Box<Expr>, 351 pub paren_token: token::Paren, 352 pub args: Punctuated<Expr, Token![,]>, 353 } 354 } 355 356 ast_struct! { 357 /// A cast expression: `foo as f64`. 358 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 359 pub struct ExprCast { 360 pub attrs: Vec<Attribute>, 361 pub expr: Box<Expr>, 362 pub as_token: Token![as], 363 pub ty: Box<Type>, 364 } 365 } 366 367 ast_struct! { 368 /// A closure expression: `|a, b| a + b`. 369 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 370 pub struct ExprClosure #full { 371 pub attrs: Vec<Attribute>, 372 pub lifetimes: Option<BoundLifetimes>, 373 pub constness: Option<Token![const]>, 374 pub movability: Option<Token![static]>, 375 pub asyncness: Option<Token![async]>, 376 pub capture: Option<Token![move]>, 377 pub or1_token: Token![|], 378 pub inputs: Punctuated<Pat, Token![,]>, 379 pub or2_token: Token![|], 380 pub output: ReturnType, 381 pub body: Box<Expr>, 382 } 383 } 384 385 ast_struct! { 386 /// A const block: `const { ... }`. 387 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 388 pub struct ExprConst #full { 389 pub attrs: Vec<Attribute>, 390 pub const_token: Token![const], 391 pub block: Block, 392 } 393 } 394 395 ast_struct! { 396 /// A `continue`, with an optional label. 397 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 398 pub struct ExprContinue #full { 399 pub attrs: Vec<Attribute>, 400 pub continue_token: Token![continue], 401 pub label: Option<Lifetime>, 402 } 403 } 404 405 ast_struct! { 406 /// Access of a named struct field (`obj.k`) or unnamed tuple struct 407 /// field (`obj.0`). 408 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 409 pub struct ExprField { 410 pub attrs: Vec<Attribute>, 411 pub base: Box<Expr>, 412 pub dot_token: Token![.], 413 pub member: Member, 414 } 415 } 416 417 ast_struct! { 418 /// A for loop: `for pat in expr { ... }`. 419 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 420 pub struct ExprForLoop #full { 421 pub attrs: Vec<Attribute>, 422 pub label: Option<Label>, 423 pub for_token: Token![for], 424 pub pat: Box<Pat>, 425 pub in_token: Token![in], 426 pub expr: Box<Expr>, 427 pub body: Block, 428 } 429 } 430 431 ast_struct! { 432 /// An expression contained within invisible delimiters. 433 /// 434 /// This variant is important for faithfully representing the precedence 435 /// of expressions and is related to `None`-delimited spans in a 436 /// `TokenStream`. 437 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 438 pub struct ExprGroup { 439 pub attrs: Vec<Attribute>, 440 pub group_token: token::Group, 441 pub expr: Box<Expr>, 442 } 443 } 444 445 ast_struct! { 446 /// An `if` expression with an optional `else` block: `if expr { ... } 447 /// else { ... }`. 448 /// 449 /// The `else` branch expression may only be an `If` or `Block` 450 /// expression, not any of the other types of expression. 451 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 452 pub struct ExprIf #full { 453 pub attrs: Vec<Attribute>, 454 pub if_token: Token![if], 455 pub cond: Box<Expr>, 456 pub then_branch: Block, 457 pub else_branch: Option<(Token![else], Box<Expr>)>, 458 } 459 } 460 461 ast_struct! { 462 /// A square bracketed indexing expression: `vector[2]`. 463 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 464 pub struct ExprIndex { 465 pub attrs: Vec<Attribute>, 466 pub expr: Box<Expr>, 467 pub bracket_token: token::Bracket, 468 pub index: Box<Expr>, 469 } 470 } 471 472 ast_struct! { 473 /// The inferred value of a const generic argument, denoted `_`. 474 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 475 pub struct ExprInfer #full { 476 pub attrs: Vec<Attribute>, 477 pub underscore_token: Token![_], 478 } 479 } 480 481 ast_struct! { 482 /// A `let` guard: `let Some(x) = opt`. 483 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 484 pub struct ExprLet #full { 485 pub attrs: Vec<Attribute>, 486 pub let_token: Token![let], 487 pub pat: Box<Pat>, 488 pub eq_token: Token![=], 489 pub expr: Box<Expr>, 490 } 491 } 492 493 ast_struct! { 494 /// A literal in place of an expression: `1`, `"foo"`. 495 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 496 pub struct ExprLit { 497 pub attrs: Vec<Attribute>, 498 pub lit: Lit, 499 } 500 } 501 502 ast_struct! { 503 /// Conditionless loop: `loop { ... }`. 504 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 505 pub struct ExprLoop #full { 506 pub attrs: Vec<Attribute>, 507 pub label: Option<Label>, 508 pub loop_token: Token![loop], 509 pub body: Block, 510 } 511 } 512 513 ast_struct! { 514 /// A macro invocation expression: `format!("{}", q)`. 515 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 516 pub struct ExprMacro { 517 pub attrs: Vec<Attribute>, 518 pub mac: Macro, 519 } 520 } 521 522 ast_struct! { 523 /// A `match` expression: `match n { Some(n) => {}, None => {} }`. 524 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 525 pub struct ExprMatch #full { 526 pub attrs: Vec<Attribute>, 527 pub match_token: Token![match], 528 pub expr: Box<Expr>, 529 pub brace_token: token::Brace, 530 pub arms: Vec<Arm>, 531 } 532 } 533 534 ast_struct! { 535 /// A method call expression: `x.foo::<T>(a, b)`. 536 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 537 pub struct ExprMethodCall { 538 pub attrs: Vec<Attribute>, 539 pub receiver: Box<Expr>, 540 pub dot_token: Token![.], 541 pub method: Ident, 542 pub turbofish: Option<AngleBracketedGenericArguments>, 543 pub paren_token: token::Paren, 544 pub args: Punctuated<Expr, Token![,]>, 545 } 546 } 547 548 ast_struct! { 549 /// A parenthesized expression: `(a + b)`. 550 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 551 pub struct ExprParen { 552 pub attrs: Vec<Attribute>, 553 pub paren_token: token::Paren, 554 pub expr: Box<Expr>, 555 } 556 } 557 558 ast_struct! { 559 /// A path like `std::mem::replace` possibly containing generic 560 /// parameters and a qualified self-type. 561 /// 562 /// A plain identifier like `x` is a path of length 1. 563 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 564 pub struct ExprPath { 565 pub attrs: Vec<Attribute>, 566 pub qself: Option<QSelf>, 567 pub path: Path, 568 } 569 } 570 571 ast_struct! { 572 /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`. 573 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 574 pub struct ExprRange #full { 575 pub attrs: Vec<Attribute>, 576 pub start: Option<Box<Expr>>, 577 pub limits: RangeLimits, 578 pub end: Option<Box<Expr>>, 579 } 580 } 581 582 ast_struct! { 583 /// Address-of operation: `&raw const place` or `&raw mut place`. 584 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 585 pub struct ExprRawAddr #full { 586 pub attrs: Vec<Attribute>, 587 pub and_token: Token![&], 588 pub raw: Token![raw], 589 pub mutability: PointerMutability, 590 pub expr: Box<Expr>, 591 } 592 } 593 594 ast_struct! { 595 /// A referencing operation: `&a` or `&mut a`. 596 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 597 pub struct ExprReference { 598 pub attrs: Vec<Attribute>, 599 pub and_token: Token![&], 600 pub mutability: Option<Token![mut]>, 601 pub expr: Box<Expr>, 602 } 603 } 604 605 ast_struct! { 606 /// An array literal constructed from one repeated element: `[0u8; N]`. 607 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 608 pub struct ExprRepeat #full { 609 pub attrs: Vec<Attribute>, 610 pub bracket_token: token::Bracket, 611 pub expr: Box<Expr>, 612 pub semi_token: Token![;], 613 pub len: Box<Expr>, 614 } 615 } 616 617 ast_struct! { 618 /// A `return`, with an optional value to be returned. 619 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 620 pub struct ExprReturn #full { 621 pub attrs: Vec<Attribute>, 622 pub return_token: Token![return], 623 pub expr: Option<Box<Expr>>, 624 } 625 } 626 627 ast_struct! { 628 /// A struct literal expression: `Point { x: 1, y: 1 }`. 629 /// 630 /// The `rest` provides the value of the remaining fields as in `S { a: 631 /// 1, b: 1, ..rest }`. 632 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 633 pub struct ExprStruct { 634 pub attrs: Vec<Attribute>, 635 pub qself: Option<QSelf>, 636 pub path: Path, 637 pub brace_token: token::Brace, 638 pub fields: Punctuated<FieldValue, Token![,]>, 639 pub dot2_token: Option<Token![..]>, 640 pub rest: Option<Box<Expr>>, 641 } 642 } 643 644 ast_struct! { 645 /// A try-expression: `expr?`. 646 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 647 pub struct ExprTry #full { 648 pub attrs: Vec<Attribute>, 649 pub expr: Box<Expr>, 650 pub question_token: Token![?], 651 } 652 } 653 654 ast_struct! { 655 /// A try block: `try { ... }`. 656 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 657 pub struct ExprTryBlock #full { 658 pub attrs: Vec<Attribute>, 659 pub try_token: Token![try], 660 pub block: Block, 661 } 662 } 663 664 ast_struct! { 665 /// A tuple expression: `(a, b, c, d)`. 666 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 667 pub struct ExprTuple { 668 pub attrs: Vec<Attribute>, 669 pub paren_token: token::Paren, 670 pub elems: Punctuated<Expr, Token![,]>, 671 } 672 } 673 674 ast_struct! { 675 /// A unary operation: `!x`, `*x`. 676 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 677 pub struct ExprUnary { 678 pub attrs: Vec<Attribute>, 679 pub op: UnOp, 680 pub expr: Box<Expr>, 681 } 682 } 683 684 ast_struct! { 685 /// An unsafe block: `unsafe { ... }`. 686 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 687 pub struct ExprUnsafe #full { 688 pub attrs: Vec<Attribute>, 689 pub unsafe_token: Token![unsafe], 690 pub block: Block, 691 } 692 } 693 694 ast_struct! { 695 /// A while loop: `while expr { ... }`. 696 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 697 pub struct ExprWhile #full { 698 pub attrs: Vec<Attribute>, 699 pub label: Option<Label>, 700 pub while_token: Token![while], 701 pub cond: Box<Expr>, 702 pub body: Block, 703 } 704 } 705 706 ast_struct! { 707 /// A yield expression: `yield expr`. 708 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 709 pub struct ExprYield #full { 710 pub attrs: Vec<Attribute>, 711 pub yield_token: Token![yield], 712 pub expr: Option<Box<Expr>>, 713 } 714 } 715 716 impl Expr { 717 /// An unspecified invalid expression. 718 /// 719 /// ``` 720 /// use quote::ToTokens; 721 /// use std::mem; 722 /// use syn::{parse_quote, Expr}; 723 /// 724 /// fn unparenthesize(e: &mut Expr) { 725 /// while let Expr::Paren(paren) = e { 726 /// *e = mem::replace(&mut *paren.expr, Expr::PLACEHOLDER); 727 /// } 728 /// } 729 /// 730 /// fn main() { 731 /// let mut e: Expr = parse_quote! { ((1 + 1)) }; 732 /// unparenthesize(&mut e); 733 /// assert_eq!("1 + 1", e.to_token_stream().to_string()); 734 /// } 735 /// ``` 736 pub const PLACEHOLDER: Self = Expr::Path(ExprPath { 737 attrs: Vec::new(), 738 qself: None, 739 path: Path { 740 leading_colon: None, 741 segments: Punctuated::new(), 742 }, 743 }); 744 745 /// An alternative to the primary `Expr::parse` parser (from the [`Parse`] 746 /// trait) for ambiguous syntactic positions in which a trailing brace 747 /// should not be taken as part of the expression. 748 /// 749 /// [`Parse`]: crate::parse::Parse 750 /// 751 /// Rust grammar has an ambiguity where braces sometimes turn a path 752 /// expression into a struct initialization and sometimes do not. In the 753 /// following code, the expression `S {}` is one expression. Presumably 754 /// there is an empty struct `struct S {}` defined somewhere which it is 755 /// instantiating. 756 /// 757 /// ``` 758 /// # struct S; 759 /// # impl std::ops::Deref for S { 760 /// # type Target = bool; 761 /// # fn deref(&self) -> &Self::Target { 762 /// # &true 763 /// # } 764 /// # } 765 /// let _ = *S {}; 766 /// 767 /// // parsed by rustc as: `*(S {})` 768 /// ``` 769 /// 770 /// We would want to parse the above using `Expr::parse` after the `=` 771 /// token. 772 /// 773 /// But in the following, `S {}` is *not* a struct init expression. 774 /// 775 /// ``` 776 /// # const S: &bool = &true; 777 /// if *S {} {} 778 /// 779 /// // parsed by rustc as: 780 /// // 781 /// // if (*S) { 782 /// // /* empty block */ 783 /// // } 784 /// // { 785 /// // /* another empty block */ 786 /// // } 787 /// ``` 788 /// 789 /// For that reason we would want to parse if-conditions using 790 /// `Expr::parse_without_eager_brace` after the `if` token. Same for similar 791 /// syntactic positions such as the condition expr after a `while` token or 792 /// the expr at the top of a `match`. 793 /// 794 /// The Rust grammar's choices around which way this ambiguity is resolved 795 /// at various syntactic positions is fairly arbitrary. Really either parse 796 /// behavior could work in most positions, and language designers just 797 /// decide each case based on which is more likely to be what the programmer 798 /// had in mind most of the time. 799 /// 800 /// ``` 801 /// # struct S; 802 /// # fn doc() -> S { 803 /// if return S {} {} 804 /// # unreachable!() 805 /// # } 806 /// 807 /// // parsed by rustc as: 808 /// // 809 /// // if (return (S {})) { 810 /// // } 811 /// // 812 /// // but could equally well have been this other arbitrary choice: 813 /// // 814 /// // if (return S) { 815 /// // } 816 /// // {} 817 /// ``` 818 /// 819 /// Note the grammar ambiguity on trailing braces is distinct from 820 /// precedence and is not captured by assigning a precedence level to the 821 /// braced struct init expr in relation to other operators. This can be 822 /// illustrated by `return 0..S {}` vs `match 0..S {}`. The former parses as 823 /// `return (0..(S {}))` implying tighter precedence for struct init than 824 /// `..`, while the latter parses as `match (0..S) {}` implying tighter 825 /// precedence for `..` than struct init, a contradiction. 826 #[cfg(all(feature = "full", feature = "parsing"))] 827 #[cfg_attr(docsrs, doc(cfg(all(feature = "full", feature = "parsing"))))] 828 pub fn parse_without_eager_brace(input: ParseStream) -> Result<Expr> { 829 parsing::ambiguous_expr(input, parsing::AllowStruct(false)) 830 } 831 832 /// An alternative to the primary `Expr::parse` parser (from the [`Parse`] 833 /// trait) for syntactic positions in which expression boundaries are placed 834 /// more eagerly than done by the typical expression grammar. This includes 835 /// expressions at the head of a statement or in the right-hand side of a 836 /// `match` arm. 837 /// 838 /// [`Parse`]: crate::parse::Parse 839 /// 840 /// Compare the following cases: 841 /// 842 /// 1. 843 /// ``` 844 /// # let result = (); 845 /// # let guard = false; 846 /// # let cond = true; 847 /// # let f = true; 848 /// # let g = f; 849 /// # 850 /// let _ = match result { 851 /// () if guard => if cond { f } else { g } 852 /// () => false, 853 /// }; 854 /// ``` 855 /// 856 /// 2. 857 /// ``` 858 /// # let cond = true; 859 /// # let f = (); 860 /// # let g = f; 861 /// # 862 /// let _ = || { 863 /// if cond { f } else { g } 864 /// () 865 /// }; 866 /// ``` 867 /// 868 /// 3. 869 /// ``` 870 /// # let cond = true; 871 /// # let f = || (); 872 /// # let g = f; 873 /// # 874 /// let _ = [if cond { f } else { g } ()]; 875 /// ``` 876 /// 877 /// The same sequence of tokens `if cond { f } else { g } ()` appears in 878 /// expression position 3 times. The first two syntactic positions use eager 879 /// placement of expression boundaries, and parse as `Expr::If`, with the 880 /// adjacent `()` becoming `Pat::Tuple` or `Expr::Tuple`. In contrast, the 881 /// third case uses standard expression boundaries and parses as 882 /// `Expr::Call`. 883 /// 884 /// As with [`parse_without_eager_brace`], this ambiguity in the Rust 885 /// grammar is independent of precedence. 886 /// 887 /// [`parse_without_eager_brace`]: Self::parse_without_eager_brace 888 #[cfg(all(feature = "full", feature = "parsing"))] 889 #[cfg_attr(docsrs, doc(cfg(all(feature = "full", feature = "parsing"))))] 890 pub fn parse_with_earlier_boundary_rule(input: ParseStream) -> Result<Expr> { 891 parsing::parse_with_earlier_boundary_rule(input) 892 } 893 894 /// Returns whether the next token in the parse stream is one that might 895 /// possibly form the beginning of an expr. 896 /// 897 /// This classification is a load-bearing part of the grammar of some Rust 898 /// expressions, notably `return` and `break`. For example `return < …` will 899 /// never parse `<` as a binary operator regardless of what comes after, 900 /// because `<` is a legal starting token for an expression and so it's 901 /// required to be continued as a return value, such as `return <Struct as 902 /// Trait>::CONST`. Meanwhile `return > …` treats the `>` as a binary 903 /// operator because it cannot be a starting token for any Rust expression. 904 #[cfg(feature = "parsing")] 905 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 906 pub fn peek(input: ParseStream) -> bool { 907 input.peek(Ident::peek_any) && !input.peek(Token![as]) // value name or keyword 908 || input.peek(token::Paren) // tuple 909 || input.peek(token::Bracket) // array 910 || input.peek(token::Brace) // block 911 || input.peek(Lit) // literal 912 || input.peek(Token![!]) && !input.peek(Token![!=]) // operator not 913 || input.peek(Token![-]) && !input.peek(Token![-=]) && !input.peek(Token![->]) // unary minus 914 || input.peek(Token![*]) && !input.peek(Token![*=]) // dereference 915 || input.peek(Token![|]) && !input.peek(Token![|=]) // closure 916 || input.peek(Token![&]) && !input.peek(Token![&=]) // reference 917 || input.peek(Token![..]) // range 918 || input.peek(Token![<]) && !input.peek(Token![<=]) && !input.peek(Token![<<=]) // associated path 919 || input.peek(Token![::]) // absolute path 920 || input.peek(Lifetime) // labeled loop 921 || input.peek(Token![#]) // expression attributes 922 } 923 924 #[cfg(all(feature = "parsing", feature = "full"))] 925 pub(crate) fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> { 926 match self { 927 Expr::Array(ExprArray { attrs, .. }) 928 | Expr::Assign(ExprAssign { attrs, .. }) 929 | Expr::Async(ExprAsync { attrs, .. }) 930 | Expr::Await(ExprAwait { attrs, .. }) 931 | Expr::Binary(ExprBinary { attrs, .. }) 932 | Expr::Block(ExprBlock { attrs, .. }) 933 | Expr::Break(ExprBreak { attrs, .. }) 934 | Expr::Call(ExprCall { attrs, .. }) 935 | Expr::Cast(ExprCast { attrs, .. }) 936 | Expr::Closure(ExprClosure { attrs, .. }) 937 | Expr::Const(ExprConst { attrs, .. }) 938 | Expr::Continue(ExprContinue { attrs, .. }) 939 | Expr::Field(ExprField { attrs, .. }) 940 | Expr::ForLoop(ExprForLoop { attrs, .. }) 941 | Expr::Group(ExprGroup { attrs, .. }) 942 | Expr::If(ExprIf { attrs, .. }) 943 | Expr::Index(ExprIndex { attrs, .. }) 944 | Expr::Infer(ExprInfer { attrs, .. }) 945 | Expr::Let(ExprLet { attrs, .. }) 946 | Expr::Lit(ExprLit { attrs, .. }) 947 | Expr::Loop(ExprLoop { attrs, .. }) 948 | Expr::Macro(ExprMacro { attrs, .. }) 949 | Expr::Match(ExprMatch { attrs, .. }) 950 | Expr::MethodCall(ExprMethodCall { attrs, .. }) 951 | Expr::Paren(ExprParen { attrs, .. }) 952 | Expr::Path(ExprPath { attrs, .. }) 953 | Expr::Range(ExprRange { attrs, .. }) 954 | Expr::RawAddr(ExprRawAddr { attrs, .. }) 955 | Expr::Reference(ExprReference { attrs, .. }) 956 | Expr::Repeat(ExprRepeat { attrs, .. }) 957 | Expr::Return(ExprReturn { attrs, .. }) 958 | Expr::Struct(ExprStruct { attrs, .. }) 959 | Expr::Try(ExprTry { attrs, .. }) 960 | Expr::TryBlock(ExprTryBlock { attrs, .. }) 961 | Expr::Tuple(ExprTuple { attrs, .. }) 962 | Expr::Unary(ExprUnary { attrs, .. }) 963 | Expr::Unsafe(ExprUnsafe { attrs, .. }) 964 | Expr::While(ExprWhile { attrs, .. }) 965 | Expr::Yield(ExprYield { attrs, .. }) => mem::replace(attrs, new), 966 Expr::Verbatim(_) => Vec::new(), 967 } 968 } 969 } 970 971 ast_enum! { 972 /// A struct or tuple struct field accessed in a struct literal or field 973 /// expression. 974 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 975 pub enum Member { 976 /// A named field like `self.x`. 977 Named(Ident), 978 /// An unnamed field like `self.0`. 979 Unnamed(Index), 980 } 981 } 982 983 impl From<Ident> for Member { 984 fn from(ident: Ident) -> Member { 985 Member::Named(ident) 986 } 987 } 988 989 impl From<Index> for Member { 990 fn from(index: Index) -> Member { 991 Member::Unnamed(index) 992 } 993 } 994 995 impl From<usize> for Member { 996 fn from(index: usize) -> Member { 997 Member::Unnamed(Index::from(index)) 998 } 999 } 1000 1001 impl Eq for Member {} 1002 1003 impl PartialEq for Member { 1004 fn eq(&self, other: &Self) -> bool { 1005 match (self, other) { 1006 (Member::Named(this), Member::Named(other)) => this == other, 1007 (Member::Unnamed(this), Member::Unnamed(other)) => this == other, 1008 _ => false, 1009 } 1010 } 1011 } 1012 1013 impl Hash for Member { 1014 fn hash<H: Hasher>(&self, state: &mut H) { 1015 match self { 1016 Member::Named(m) => m.hash(state), 1017 Member::Unnamed(m) => m.hash(state), 1018 } 1019 } 1020 } 1021 1022 #[cfg(feature = "printing")] 1023 impl IdentFragment for Member { 1024 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 1025 match self { 1026 Member::Named(m) => Display::fmt(m, formatter), 1027 Member::Unnamed(m) => Display::fmt(&m.index, formatter), 1028 } 1029 } 1030 1031 fn span(&self) -> Option<Span> { 1032 match self { 1033 Member::Named(m) => Some(m.span()), 1034 Member::Unnamed(m) => Some(m.span), 1035 } 1036 } 1037 } 1038 1039 #[cfg(any(feature = "parsing", feature = "printing"))] 1040 impl Member { 1041 pub(crate) fn is_named(&self) -> bool { 1042 match self { 1043 Member::Named(_) => true, 1044 Member::Unnamed(_) => false, 1045 } 1046 } 1047 } 1048 1049 ast_struct! { 1050 /// The index of an unnamed tuple struct field. 1051 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 1052 pub struct Index { 1053 pub index: u32, 1054 pub span: Span, 1055 } 1056 } 1057 1058 impl From<usize> for Index { 1059 fn from(index: usize) -> Index { 1060 assert!(index < u32::MAX as usize); 1061 Index { 1062 index: index as u32, 1063 span: Span::call_site(), 1064 } 1065 } 1066 } 1067 1068 impl Eq for Index {} 1069 1070 impl PartialEq for Index { 1071 fn eq(&self, other: &Self) -> bool { 1072 self.index == other.index 1073 } 1074 } 1075 1076 impl Hash for Index { 1077 fn hash<H: Hasher>(&self, state: &mut H) { 1078 self.index.hash(state); 1079 } 1080 } 1081 1082 #[cfg(feature = "printing")] 1083 impl IdentFragment for Index { 1084 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 1085 Display::fmt(&self.index, formatter) 1086 } 1087 1088 fn span(&self) -> Option<Span> { 1089 Some(self.span) 1090 } 1091 } 1092 1093 ast_struct! { 1094 /// A field-value pair in a struct literal. 1095 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 1096 pub struct FieldValue { 1097 pub attrs: Vec<Attribute>, 1098 pub member: Member, 1099 1100 /// The colon in `Struct { x: x }`. If written in shorthand like 1101 /// `Struct { x }`, there is no colon. 1102 pub colon_token: Option<Token![:]>, 1103 1104 pub expr: Expr, 1105 } 1106 } 1107 1108 #[cfg(feature = "full")] 1109 ast_struct! { 1110 /// A lifetime labeling a `for`, `while`, or `loop`. 1111 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 1112 pub struct Label { 1113 pub name: Lifetime, 1114 pub colon_token: Token![:], 1115 } 1116 } 1117 1118 #[cfg(feature = "full")] 1119 ast_struct! { 1120 /// One arm of a `match` expression: `0..=10 => { return true; }`. 1121 /// 1122 /// As in: 1123 /// 1124 /// ``` 1125 /// # fn f() -> bool { 1126 /// # let n = 0; 1127 /// match n { 1128 /// 0..=10 => { 1129 /// return true; 1130 /// } 1131 /// // ... 1132 /// # _ => {} 1133 /// } 1134 /// # false 1135 /// # } 1136 /// ``` 1137 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 1138 pub struct Arm { 1139 pub attrs: Vec<Attribute>, 1140 pub pat: Pat, 1141 pub guard: Option<(Token![if], Box<Expr>)>, 1142 pub fat_arrow_token: Token![=>], 1143 pub body: Box<Expr>, 1144 pub comma: Option<Token![,]>, 1145 } 1146 } 1147 1148 #[cfg(feature = "full")] 1149 ast_enum! { 1150 /// Limit types of a range, inclusive or exclusive. 1151 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 1152 pub enum RangeLimits { 1153 /// Inclusive at the beginning, exclusive at the end. 1154 HalfOpen(Token![..]), 1155 /// Inclusive at the beginning and end. 1156 Closed(Token![..=]), 1157 } 1158 } 1159 1160 #[cfg(feature = "full")] 1161 ast_enum! { 1162 /// Mutability of a raw pointer (`*const T`, `*mut T`), in which non-mutable 1163 /// isn't the implicit default. 1164 #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 1165 pub enum PointerMutability { 1166 Const(Token![const]), 1167 Mut(Token![mut]), 1168 } 1169 } 1170 1171 #[cfg(feature = "parsing")] 1172 pub(crate) mod parsing { 1173 #[cfg(feature = "full")] 1174 use crate::attr; 1175 use crate::attr::Attribute; 1176 #[cfg(feature = "full")] 1177 use crate::classify; 1178 use crate::error::{Error, Result}; 1179 #[cfg(feature = "full")] 1180 use crate::expr::{ 1181 Arm, ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure, 1182 ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch, 1183 ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprUnsafe, 1184 ExprWhile, ExprYield, Label, PointerMutability, RangeLimits, 1185 }; 1186 use crate::expr::{ 1187 Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro, 1188 ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprTuple, ExprUnary, 1189 FieldValue, Index, Member, 1190 }; 1191 #[cfg(feature = "full")] 1192 use crate::generics::{self, BoundLifetimes}; 1193 use crate::ident::Ident; 1194 #[cfg(feature = "full")] 1195 use crate::lifetime::Lifetime; 1196 use crate::lit::{Lit, LitFloat, LitInt}; 1197 use crate::mac::{self, Macro}; 1198 use crate::op::BinOp; 1199 use crate::parse::discouraged::Speculative as _; 1200 #[cfg(feature = "full")] 1201 use crate::parse::ParseBuffer; 1202 use crate::parse::{Parse, ParseStream}; 1203 #[cfg(feature = "full")] 1204 use crate::pat::{Pat, PatType}; 1205 use crate::path::{self, AngleBracketedGenericArguments, Path, QSelf}; 1206 use crate::precedence::Precedence; 1207 use crate::punctuated::Punctuated; 1208 #[cfg(feature = "full")] 1209 use crate::stmt::Block; 1210 use crate::token; 1211 use crate::ty; 1212 #[cfg(feature = "full")] 1213 use crate::ty::{ReturnType, Type}; 1214 use crate::verbatim; 1215 #[cfg(feature = "full")] 1216 use proc_macro2::{Span, TokenStream}; 1217 use std::mem; 1218 1219 // When we're parsing expressions which occur before blocks, like in an if 1220 // statement's condition, we cannot parse a struct literal. 1221 // 1222 // Struct literals are ambiguous in certain positions 1223 // https://github.com/rust-lang/rfcs/pull/92 1224 #[cfg(feature = "full")] 1225 pub(super) struct AllowStruct(pub bool); 1226 1227 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 1228 impl Parse for Expr { 1229 fn parse(input: ParseStream) -> Result<Self> { 1230 ambiguous_expr( 1231 input, 1232 #[cfg(feature = "full")] 1233 AllowStruct(true), 1234 ) 1235 } 1236 } 1237 1238 #[cfg(feature = "full")] 1239 pub(super) fn parse_with_earlier_boundary_rule(input: ParseStream) -> Result<Expr> { 1240 let mut attrs = input.call(expr_attrs)?; 1241 let mut expr = if input.peek(token::Group) { 1242 let allow_struct = AllowStruct(true); 1243 let atom = expr_group(input, allow_struct)?; 1244 if continue_parsing_early(&atom) { 1245 trailer_helper(input, atom)? 1246 } else { 1247 atom 1248 } 1249 } else if input.peek(Token![if]) { 1250 Expr::If(input.parse()?) 1251 } else if input.peek(Token![while]) { 1252 Expr::While(input.parse()?) 1253 } else if input.peek(Token![for]) 1254 && !generics::parsing::choose_generics_over_qpath_after_keyword(input) 1255 { 1256 Expr::ForLoop(input.parse()?) 1257 } else if input.peek(Token![loop]) { 1258 Expr::Loop(input.parse()?) 1259 } else if input.peek(Token![match]) { 1260 Expr::Match(input.parse()?) 1261 } else if input.peek(Token![try]) && input.peek2(token::Brace) { 1262 Expr::TryBlock(input.parse()?) 1263 } else if input.peek(Token![unsafe]) { 1264 Expr::Unsafe(input.parse()?) 1265 } else if input.peek(Token![const]) && input.peek2(token::Brace) { 1266 Expr::Const(input.parse()?) 1267 } else if input.peek(token::Brace) { 1268 Expr::Block(input.parse()?) 1269 } else if input.peek(Lifetime) { 1270 atom_labeled(input)? 1271 } else { 1272 let allow_struct = AllowStruct(true); 1273 unary_expr(input, allow_struct)? 1274 }; 1275 1276 if continue_parsing_early(&expr) { 1277 attrs.extend(expr.replace_attrs(Vec::new())); 1278 expr.replace_attrs(attrs); 1279 1280 let allow_struct = AllowStruct(true); 1281 return parse_expr(input, expr, allow_struct, Precedence::MIN); 1282 } 1283 1284 if input.peek(Token![.]) && !input.peek(Token![..]) || input.peek(Token![?]) { 1285 expr = trailer_helper(input, expr)?; 1286 1287 attrs.extend(expr.replace_attrs(Vec::new())); 1288 expr.replace_attrs(attrs); 1289 1290 let allow_struct = AllowStruct(true); 1291 return parse_expr(input, expr, allow_struct, Precedence::MIN); 1292 } 1293 1294 attrs.extend(expr.replace_attrs(Vec::new())); 1295 expr.replace_attrs(attrs); 1296 Ok(expr) 1297 } 1298 1299 #[cfg(feature = "full")] 1300 impl Copy for AllowStruct {} 1301 1302 #[cfg(feature = "full")] 1303 impl Clone for AllowStruct { 1304 fn clone(&self) -> Self { 1305 *self 1306 } 1307 } 1308 1309 #[cfg(feature = "full")] 1310 fn parse_expr( 1311 input: ParseStream, 1312 mut lhs: Expr, 1313 allow_struct: AllowStruct, 1314 base: Precedence, 1315 ) -> Result<Expr> { 1316 loop { 1317 let ahead = input.fork(); 1318 if let Expr::Range(_) = lhs { 1319 // A range cannot be the left-hand side of another binary operator. 1320 break; 1321 } else if let Ok(op) = ahead.parse::<BinOp>() { 1322 let precedence = Precedence::of_binop(&op); 1323 if precedence < base { 1324 break; 1325 } 1326 if precedence == Precedence::Assign { 1327 if let Expr::Range(_) = lhs { 1328 break; 1329 } 1330 } 1331 if precedence == Precedence::Compare { 1332 if let Expr::Binary(lhs) = &lhs { 1333 if Precedence::of_binop(&lhs.op) == Precedence::Compare { 1334 return Err(input.error("comparison operators cannot be chained")); 1335 } 1336 } 1337 } 1338 input.advance_to(&ahead); 1339 let right = parse_binop_rhs(input, allow_struct, precedence)?; 1340 lhs = Expr::Binary(ExprBinary { 1341 attrs: Vec::new(), 1342 left: Box::new(lhs), 1343 op, 1344 right, 1345 }); 1346 } else if Precedence::Assign >= base 1347 && input.peek(Token![=]) 1348 && !input.peek(Token![=>]) 1349 && match lhs { 1350 Expr::Range(_) => false, 1351 _ => true, 1352 } 1353 { 1354 let eq_token: Token![=] = input.parse()?; 1355 let right = parse_binop_rhs(input, allow_struct, Precedence::Assign)?; 1356 lhs = Expr::Assign(ExprAssign { 1357 attrs: Vec::new(), 1358 left: Box::new(lhs), 1359 eq_token, 1360 right, 1361 }); 1362 } else if Precedence::Range >= base && input.peek(Token![..]) { 1363 let limits: RangeLimits = input.parse()?; 1364 let end = parse_range_end(input, &limits, allow_struct)?; 1365 lhs = Expr::Range(ExprRange { 1366 attrs: Vec::new(), 1367 start: Some(Box::new(lhs)), 1368 limits, 1369 end, 1370 }); 1371 } else if Precedence::Cast >= base && input.peek(Token![as]) { 1372 let as_token: Token![as] = input.parse()?; 1373 let allow_plus = false; 1374 let allow_group_generic = false; 1375 let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?; 1376 check_cast(input)?; 1377 lhs = Expr::Cast(ExprCast { 1378 attrs: Vec::new(), 1379 expr: Box::new(lhs), 1380 as_token, 1381 ty: Box::new(ty), 1382 }); 1383 } else { 1384 break; 1385 } 1386 } 1387 Ok(lhs) 1388 } 1389 1390 #[cfg(not(feature = "full"))] 1391 fn parse_expr(input: ParseStream, mut lhs: Expr, base: Precedence) -> Result<Expr> { 1392 loop { 1393 let ahead = input.fork(); 1394 if let Ok(op) = ahead.parse::<BinOp>() { 1395 let precedence = Precedence::of_binop(&op); 1396 if precedence < base { 1397 break; 1398 } 1399 if precedence == Precedence::Compare { 1400 if let Expr::Binary(lhs) = &lhs { 1401 if Precedence::of_binop(&lhs.op) == Precedence::Compare { 1402 return Err(input.error("comparison operators cannot be chained")); 1403 } 1404 } 1405 } 1406 input.advance_to(&ahead); 1407 let right = parse_binop_rhs(input, precedence)?; 1408 lhs = Expr::Binary(ExprBinary { 1409 attrs: Vec::new(), 1410 left: Box::new(lhs), 1411 op, 1412 right, 1413 }); 1414 } else if Precedence::Cast >= base && input.peek(Token![as]) { 1415 let as_token: Token![as] = input.parse()?; 1416 let allow_plus = false; 1417 let allow_group_generic = false; 1418 let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?; 1419 check_cast(input)?; 1420 lhs = Expr::Cast(ExprCast { 1421 attrs: Vec::new(), 1422 expr: Box::new(lhs), 1423 as_token, 1424 ty: Box::new(ty), 1425 }); 1426 } else { 1427 break; 1428 } 1429 } 1430 Ok(lhs) 1431 } 1432 1433 fn parse_binop_rhs( 1434 input: ParseStream, 1435 #[cfg(feature = "full")] allow_struct: AllowStruct, 1436 precedence: Precedence, 1437 ) -> Result<Box<Expr>> { 1438 let mut rhs = unary_expr( 1439 input, 1440 #[cfg(feature = "full")] 1441 allow_struct, 1442 )?; 1443 loop { 1444 let next = peek_precedence(input); 1445 if next > precedence || next == precedence && precedence == Precedence::Assign { 1446 let cursor = input.cursor(); 1447 rhs = parse_expr( 1448 input, 1449 rhs, 1450 #[cfg(feature = "full")] 1451 allow_struct, 1452 next, 1453 )?; 1454 if cursor == input.cursor() { 1455 // Bespoke grammar restrictions separate from precedence can 1456 // cause parsing to not advance, such as `..a` being 1457 // disallowed in the left-hand side of binary operators, 1458 // even ones that have lower precedence than `..`. 1459 break; 1460 } 1461 } else { 1462 break; 1463 } 1464 } 1465 Ok(Box::new(rhs)) 1466 } 1467 1468 fn peek_precedence(input: ParseStream) -> Precedence { 1469 if let Ok(op) = input.fork().parse() { 1470 Precedence::of_binop(&op) 1471 } else if input.peek(Token![=]) && !input.peek(Token![=>]) { 1472 Precedence::Assign 1473 } else if input.peek(Token![..]) { 1474 Precedence::Range 1475 } else if input.peek(Token![as]) { 1476 Precedence::Cast 1477 } else { 1478 Precedence::MIN 1479 } 1480 } 1481 1482 // Parse an arbitrary expression. 1483 pub(super) fn ambiguous_expr( 1484 input: ParseStream, 1485 #[cfg(feature = "full")] allow_struct: AllowStruct, 1486 ) -> Result<Expr> { 1487 let lhs = unary_expr( 1488 input, 1489 #[cfg(feature = "full")] 1490 allow_struct, 1491 )?; 1492 parse_expr( 1493 input, 1494 lhs, 1495 #[cfg(feature = "full")] 1496 allow_struct, 1497 Precedence::MIN, 1498 ) 1499 } 1500 1501 #[cfg(feature = "full")] 1502 fn expr_attrs(input: ParseStream) -> Result<Vec<Attribute>> { 1503 let mut attrs = Vec::new(); 1504 while !input.peek(token::Group) && input.peek(Token![#]) { 1505 attrs.push(input.call(attr::parsing::single_parse_outer)?); 1506 } 1507 Ok(attrs) 1508 } 1509 1510 // <UnOp> <trailer> 1511 // & <trailer> 1512 // &mut <trailer> 1513 // box <trailer> 1514 #[cfg(feature = "full")] 1515 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> { 1516 let begin = input.fork(); 1517 let attrs = input.call(expr_attrs)?; 1518 if input.peek(token::Group) { 1519 return trailer_expr(begin, attrs, input, allow_struct); 1520 } 1521 1522 if input.peek(Token![&]) { 1523 let and_token: Token![&] = input.parse()?; 1524 let raw: Option<Token![raw]> = if input.peek(Token![raw]) 1525 && (input.peek2(Token![mut]) || input.peek2(Token![const])) 1526 { 1527 Some(input.parse()?) 1528 } else { 1529 None 1530 }; 1531 let mutability: Option<Token![mut]> = input.parse()?; 1532 let const_token: Option<Token![const]> = if raw.is_some() && mutability.is_none() { 1533 Some(input.parse()?) 1534 } else { 1535 None 1536 }; 1537 let expr = Box::new(unary_expr(input, allow_struct)?); 1538 if let Some(raw) = raw { 1539 Ok(Expr::RawAddr(ExprRawAddr { 1540 attrs, 1541 and_token, 1542 raw, 1543 mutability: match mutability { 1544 Some(mut_token) => PointerMutability::Mut(mut_token), 1545 None => PointerMutability::Const(const_token.unwrap()), 1546 }, 1547 expr, 1548 })) 1549 } else { 1550 Ok(Expr::Reference(ExprReference { 1551 attrs, 1552 and_token, 1553 mutability, 1554 expr, 1555 })) 1556 } 1557 } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) { 1558 expr_unary(input, attrs, allow_struct).map(Expr::Unary) 1559 } else { 1560 trailer_expr(begin, attrs, input, allow_struct) 1561 } 1562 } 1563 1564 #[cfg(not(feature = "full"))] 1565 fn unary_expr(input: ParseStream) -> Result<Expr> { 1566 if input.peek(Token![&]) { 1567 Ok(Expr::Reference(ExprReference { 1568 attrs: Vec::new(), 1569 and_token: input.parse()?, 1570 mutability: input.parse()?, 1571 expr: Box::new(unary_expr(input)?), 1572 })) 1573 } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) { 1574 Ok(Expr::Unary(ExprUnary { 1575 attrs: Vec::new(), 1576 op: input.parse()?, 1577 expr: Box::new(unary_expr(input)?), 1578 })) 1579 } else { 1580 trailer_expr(input) 1581 } 1582 } 1583 1584 // <atom> (..<args>) ... 1585 // <atom> . <ident> (..<args>) ... 1586 // <atom> . <ident> ... 1587 // <atom> . <lit> ... 1588 // <atom> [ <expr> ] ... 1589 // <atom> ? ... 1590 #[cfg(feature = "full")] 1591 fn trailer_expr( 1592 begin: ParseBuffer, 1593 mut attrs: Vec<Attribute>, 1594 input: ParseStream, 1595 allow_struct: AllowStruct, 1596 ) -> Result<Expr> { 1597 let atom = atom_expr(input, allow_struct)?; 1598 let mut e = trailer_helper(input, atom)?; 1599 1600 if let Expr::Verbatim(tokens) = &mut e { 1601 *tokens = verbatim::between(&begin, input); 1602 } else if !attrs.is_empty() { 1603 if let Expr::Range(range) = e { 1604 let spans: &[Span] = match &range.limits { 1605 RangeLimits::HalfOpen(limits) => &limits.spans, 1606 RangeLimits::Closed(limits) => &limits.spans, 1607 }; 1608 return Err(crate::error::new2( 1609 spans[0], 1610 *spans.last().unwrap(), 1611 "attributes are not allowed on range expressions starting with `..`", 1612 )); 1613 } 1614 let inner_attrs = e.replace_attrs(Vec::new()); 1615 attrs.extend(inner_attrs); 1616 e.replace_attrs(attrs); 1617 } 1618 1619 Ok(e) 1620 } 1621 1622 #[cfg(feature = "full")] 1623 fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> { 1624 loop { 1625 if input.peek(token::Paren) { 1626 let content; 1627 e = Expr::Call(ExprCall { 1628 attrs: Vec::new(), 1629 func: Box::new(e), 1630 paren_token: parenthesized!(content in input), 1631 args: content.parse_terminated(Expr::parse, Token![,])?, 1632 }); 1633 } else if input.peek(Token![.]) 1634 && !input.peek(Token![..]) 1635 && match e { 1636 Expr::Range(_) => false, 1637 _ => true, 1638 } 1639 { 1640 let mut dot_token: Token![.] = input.parse()?; 1641 1642 let float_token: Option<LitFloat> = input.parse()?; 1643 if let Some(float_token) = float_token { 1644 if multi_index(&mut e, &mut dot_token, float_token)? { 1645 continue; 1646 } 1647 } 1648 1649 let await_token: Option<Token![await]> = input.parse()?; 1650 if let Some(await_token) = await_token { 1651 e = Expr::Await(ExprAwait { 1652 attrs: Vec::new(), 1653 base: Box::new(e), 1654 dot_token, 1655 await_token, 1656 }); 1657 continue; 1658 } 1659 1660 let member: Member = input.parse()?; 1661 let turbofish = if member.is_named() && input.peek(Token![::]) { 1662 Some(AngleBracketedGenericArguments::parse_turbofish(input)?) 1663 } else { 1664 None 1665 }; 1666 1667 if turbofish.is_some() || input.peek(token::Paren) { 1668 if let Member::Named(method) = member { 1669 let content; 1670 e = Expr::MethodCall(ExprMethodCall { 1671 attrs: Vec::new(), 1672 receiver: Box::new(e), 1673 dot_token, 1674 method, 1675 turbofish, 1676 paren_token: parenthesized!(content in input), 1677 args: content.parse_terminated(Expr::parse, Token![,])?, 1678 }); 1679 continue; 1680 } 1681 } 1682 1683 e = Expr::Field(ExprField { 1684 attrs: Vec::new(), 1685 base: Box::new(e), 1686 dot_token, 1687 member, 1688 }); 1689 } else if input.peek(token::Bracket) { 1690 let content; 1691 e = Expr::Index(ExprIndex { 1692 attrs: Vec::new(), 1693 expr: Box::new(e), 1694 bracket_token: bracketed!(content in input), 1695 index: content.parse()?, 1696 }); 1697 } else if input.peek(Token![?]) 1698 && match e { 1699 Expr::Range(_) => false, 1700 _ => true, 1701 } 1702 { 1703 e = Expr::Try(ExprTry { 1704 attrs: Vec::new(), 1705 expr: Box::new(e), 1706 question_token: input.parse()?, 1707 }); 1708 } else { 1709 break; 1710 } 1711 } 1712 Ok(e) 1713 } 1714 1715 #[cfg(not(feature = "full"))] 1716 fn trailer_expr(input: ParseStream) -> Result<Expr> { 1717 let mut e = atom_expr(input)?; 1718 1719 loop { 1720 if input.peek(token::Paren) { 1721 let content; 1722 e = Expr::Call(ExprCall { 1723 attrs: Vec::new(), 1724 func: Box::new(e), 1725 paren_token: parenthesized!(content in input), 1726 args: content.parse_terminated(Expr::parse, Token![,])?, 1727 }); 1728 } else if input.peek(Token![.]) 1729 && !input.peek(Token![..]) 1730 && !input.peek2(Token![await]) 1731 { 1732 let mut dot_token: Token![.] = input.parse()?; 1733 1734 let float_token: Option<LitFloat> = input.parse()?; 1735 if let Some(float_token) = float_token { 1736 if multi_index(&mut e, &mut dot_token, float_token)? { 1737 continue; 1738 } 1739 } 1740 1741 let member: Member = input.parse()?; 1742 let turbofish = if member.is_named() && input.peek(Token![::]) { 1743 let colon2_token: Token![::] = input.parse()?; 1744 let turbofish = 1745 AngleBracketedGenericArguments::do_parse(Some(colon2_token), input)?; 1746 Some(turbofish) 1747 } else { 1748 None 1749 }; 1750 1751 if turbofish.is_some() || input.peek(token::Paren) { 1752 if let Member::Named(method) = member { 1753 let content; 1754 e = Expr::MethodCall(ExprMethodCall { 1755 attrs: Vec::new(), 1756 receiver: Box::new(e), 1757 dot_token, 1758 method, 1759 turbofish, 1760 paren_token: parenthesized!(content in input), 1761 args: content.parse_terminated(Expr::parse, Token![,])?, 1762 }); 1763 continue; 1764 } 1765 } 1766 1767 e = Expr::Field(ExprField { 1768 attrs: Vec::new(), 1769 base: Box::new(e), 1770 dot_token, 1771 member, 1772 }); 1773 } else if input.peek(token::Bracket) { 1774 let content; 1775 e = Expr::Index(ExprIndex { 1776 attrs: Vec::new(), 1777 expr: Box::new(e), 1778 bracket_token: bracketed!(content in input), 1779 index: content.parse()?, 1780 }); 1781 } else { 1782 break; 1783 } 1784 } 1785 1786 Ok(e) 1787 } 1788 1789 // Parse all atomic expressions which don't have to worry about precedence 1790 // interactions, as they are fully contained. 1791 #[cfg(feature = "full")] 1792 fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> { 1793 if input.peek(token::Group) { 1794 expr_group(input, allow_struct) 1795 } else if input.peek(Lit) { 1796 input.parse().map(Expr::Lit) 1797 } else if input.peek(Token![async]) 1798 && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace)) 1799 { 1800 input.parse().map(Expr::Async) 1801 } else if input.peek(Token![try]) && input.peek2(token::Brace) { 1802 input.parse().map(Expr::TryBlock) 1803 } else if input.peek(Token![|]) 1804 || input.peek(Token![move]) 1805 || input.peek(Token![for]) 1806 && generics::parsing::choose_generics_over_qpath_after_keyword(input) 1807 || input.peek(Token![const]) && !input.peek2(token::Brace) 1808 || input.peek(Token![static]) 1809 || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move])) 1810 { 1811 expr_closure(input, allow_struct).map(Expr::Closure) 1812 } else if token::parsing::peek_keyword(input.cursor(), "builtin") && input.peek2(Token![#]) 1813 { 1814 expr_builtin(input) 1815 } else if input.peek(Ident) 1816 || input.peek(Token![::]) 1817 || input.peek(Token![<]) 1818 || input.peek(Token![self]) 1819 || input.peek(Token![Self]) 1820 || input.peek(Token![super]) 1821 || input.peek(Token![crate]) 1822 || input.peek(Token![try]) && (input.peek2(Token![!]) || input.peek2(Token![::])) 1823 { 1824 path_or_macro_or_struct(input, allow_struct) 1825 } else if input.peek(token::Paren) { 1826 paren_or_tuple(input) 1827 } else if input.peek(Token![break]) { 1828 expr_break(input, allow_struct).map(Expr::Break) 1829 } else if input.peek(Token![continue]) { 1830 input.parse().map(Expr::Continue) 1831 } else if input.peek(Token![return]) { 1832 input.parse().map(Expr::Return) 1833 } else if input.peek(Token![become]) { 1834 expr_become(input) 1835 } else if input.peek(token::Bracket) { 1836 array_or_repeat(input) 1837 } else if input.peek(Token![let]) { 1838 expr_let(input, allow_struct).map(Expr::Let) 1839 } else if input.peek(Token![if]) { 1840 input.parse().map(Expr::If) 1841 } else if input.peek(Token![while]) { 1842 input.parse().map(Expr::While) 1843 } else if input.peek(Token![for]) { 1844 input.parse().map(Expr::ForLoop) 1845 } else if input.peek(Token![loop]) { 1846 input.parse().map(Expr::Loop) 1847 } else if input.peek(Token![match]) { 1848 input.parse().map(Expr::Match) 1849 } else if input.peek(Token![yield]) { 1850 input.parse().map(Expr::Yield) 1851 } else if input.peek(Token![unsafe]) { 1852 input.parse().map(Expr::Unsafe) 1853 } else if input.peek(Token![const]) { 1854 input.parse().map(Expr::Const) 1855 } else if input.peek(token::Brace) { 1856 input.parse().map(Expr::Block) 1857 } else if input.peek(Token![..]) { 1858 expr_range(input, allow_struct).map(Expr::Range) 1859 } else if input.peek(Token![_]) { 1860 input.parse().map(Expr::Infer) 1861 } else if input.peek(Lifetime) { 1862 atom_labeled(input) 1863 } else { 1864 Err(input.error("expected an expression")) 1865 } 1866 } 1867 1868 #[cfg(feature = "full")] 1869 fn atom_labeled(input: ParseStream) -> Result<Expr> { 1870 let the_label: Label = input.parse()?; 1871 let mut expr = if input.peek(Token![while]) { 1872 Expr::While(input.parse()?) 1873 } else if input.peek(Token![for]) { 1874 Expr::ForLoop(input.parse()?) 1875 } else if input.peek(Token![loop]) { 1876 Expr::Loop(input.parse()?) 1877 } else if input.peek(token::Brace) { 1878 Expr::Block(input.parse()?) 1879 } else { 1880 return Err(input.error("expected loop or block expression")); 1881 }; 1882 match &mut expr { 1883 Expr::While(ExprWhile { label, .. }) 1884 | Expr::ForLoop(ExprForLoop { label, .. }) 1885 | Expr::Loop(ExprLoop { label, .. }) 1886 | Expr::Block(ExprBlock { label, .. }) => *label = Some(the_label), 1887 _ => unreachable!(), 1888 } 1889 Ok(expr) 1890 } 1891 1892 #[cfg(not(feature = "full"))] 1893 fn atom_expr(input: ParseStream) -> Result<Expr> { 1894 if input.peek(token::Group) { 1895 expr_group(input) 1896 } else if input.peek(Lit) { 1897 input.parse().map(Expr::Lit) 1898 } else if input.peek(token::Paren) { 1899 paren_or_tuple(input) 1900 } else if input.peek(Ident) 1901 || input.peek(Token![::]) 1902 || input.peek(Token![<]) 1903 || input.peek(Token![self]) 1904 || input.peek(Token![Self]) 1905 || input.peek(Token![super]) 1906 || input.peek(Token![crate]) 1907 { 1908 path_or_macro_or_struct(input) 1909 } else if input.is_empty() { 1910 Err(input.error("expected an expression")) 1911 } else { 1912 if input.peek(token::Brace) { 1913 let scan = input.fork(); 1914 let content; 1915 braced!(content in scan); 1916 if content.parse::<Expr>().is_ok() && content.is_empty() { 1917 let expr_block = verbatim::between(input, &scan); 1918 input.advance_to(&scan); 1919 return Ok(Expr::Verbatim(expr_block)); 1920 } 1921 } 1922 Err(input.error("unsupported expression; enable syn's features=[\"full\"]")) 1923 } 1924 } 1925 1926 #[cfg(feature = "full")] 1927 fn expr_builtin(input: ParseStream) -> Result<Expr> { 1928 let begin = input.fork(); 1929 1930 token::parsing::keyword(input, "builtin")?; 1931 input.parse::<Token![#]>()?; 1932 input.parse::<Ident>()?; 1933 1934 let args; 1935 parenthesized!(args in input); 1936 args.parse::<TokenStream>()?; 1937 1938 Ok(Expr::Verbatim(verbatim::between(&begin, input))) 1939 } 1940 1941 fn path_or_macro_or_struct( 1942 input: ParseStream, 1943 #[cfg(feature = "full")] allow_struct: AllowStruct, 1944 ) -> Result<Expr> { 1945 let expr_style = true; 1946 let (qself, path) = path::parsing::qpath(input, expr_style)?; 1947 rest_of_path_or_macro_or_struct( 1948 qself, 1949 path, 1950 input, 1951 #[cfg(feature = "full")] 1952 allow_struct, 1953 ) 1954 } 1955 1956 fn rest_of_path_or_macro_or_struct( 1957 qself: Option<QSelf>, 1958 path: Path, 1959 input: ParseStream, 1960 #[cfg(feature = "full")] allow_struct: AllowStruct, 1961 ) -> Result<Expr> { 1962 if qself.is_none() 1963 && input.peek(Token![!]) 1964 && !input.peek(Token![!=]) 1965 && path.is_mod_style() 1966 { 1967 let bang_token: Token![!] = input.parse()?; 1968 let (delimiter, tokens) = mac::parse_delimiter(input)?; 1969 return Ok(Expr::Macro(ExprMacro { 1970 attrs: Vec::new(), 1971 mac: Macro { 1972 path, 1973 bang_token, 1974 delimiter, 1975 tokens, 1976 }, 1977 })); 1978 } 1979 1980 #[cfg(not(feature = "full"))] 1981 let allow_struct = (true,); 1982 if allow_struct.0 && input.peek(token::Brace) { 1983 return expr_struct_helper(input, qself, path).map(Expr::Struct); 1984 } 1985 1986 Ok(Expr::Path(ExprPath { 1987 attrs: Vec::new(), 1988 qself, 1989 path, 1990 })) 1991 } 1992 1993 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 1994 impl Parse for ExprMacro { 1995 fn parse(input: ParseStream) -> Result<Self> { 1996 Ok(ExprMacro { 1997 attrs: Vec::new(), 1998 mac: input.parse()?, 1999 }) 2000 } 2001 } 2002 2003 fn paren_or_tuple(input: ParseStream) -> Result<Expr> { 2004 let content; 2005 let paren_token = parenthesized!(content in input); 2006 if content.is_empty() { 2007 return Ok(Expr::Tuple(ExprTuple { 2008 attrs: Vec::new(), 2009 paren_token, 2010 elems: Punctuated::new(), 2011 })); 2012 } 2013 2014 let first: Expr = content.parse()?; 2015 if content.is_empty() { 2016 return Ok(Expr::Paren(ExprParen { 2017 attrs: Vec::new(), 2018 paren_token, 2019 expr: Box::new(first), 2020 })); 2021 } 2022 2023 let mut elems = Punctuated::new(); 2024 elems.push_value(first); 2025 while !content.is_empty() { 2026 let punct = content.parse()?; 2027 elems.push_punct(punct); 2028 if content.is_empty() { 2029 break; 2030 } 2031 let value = content.parse()?; 2032 elems.push_value(value); 2033 } 2034 Ok(Expr::Tuple(ExprTuple { 2035 attrs: Vec::new(), 2036 paren_token, 2037 elems, 2038 })) 2039 } 2040 2041 #[cfg(feature = "full")] 2042 fn array_or_repeat(input: ParseStream) -> Result<Expr> { 2043 let content; 2044 let bracket_token = bracketed!(content in input); 2045 if content.is_empty() { 2046 return Ok(Expr::Array(ExprArray { 2047 attrs: Vec::new(), 2048 bracket_token, 2049 elems: Punctuated::new(), 2050 })); 2051 } 2052 2053 let first: Expr = content.parse()?; 2054 if content.is_empty() || content.peek(Token![,]) { 2055 let mut elems = Punctuated::new(); 2056 elems.push_value(first); 2057 while !content.is_empty() { 2058 let punct = content.parse()?; 2059 elems.push_punct(punct); 2060 if content.is_empty() { 2061 break; 2062 } 2063 let value = content.parse()?; 2064 elems.push_value(value); 2065 } 2066 Ok(Expr::Array(ExprArray { 2067 attrs: Vec::new(), 2068 bracket_token, 2069 elems, 2070 })) 2071 } else if content.peek(Token![;]) { 2072 let semi_token: Token![;] = content.parse()?; 2073 let len: Expr = content.parse()?; 2074 Ok(Expr::Repeat(ExprRepeat { 2075 attrs: Vec::new(), 2076 bracket_token, 2077 expr: Box::new(first), 2078 semi_token, 2079 len: Box::new(len), 2080 })) 2081 } else { 2082 Err(content.error("expected `,` or `;`")) 2083 } 2084 } 2085 2086 #[cfg(feature = "full")] 2087 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2088 impl Parse for ExprArray { 2089 fn parse(input: ParseStream) -> Result<Self> { 2090 let content; 2091 let bracket_token = bracketed!(content in input); 2092 let mut elems = Punctuated::new(); 2093 2094 while !content.is_empty() { 2095 let first: Expr = content.parse()?; 2096 elems.push_value(first); 2097 if content.is_empty() { 2098 break; 2099 } 2100 let punct = content.parse()?; 2101 elems.push_punct(punct); 2102 } 2103 2104 Ok(ExprArray { 2105 attrs: Vec::new(), 2106 bracket_token, 2107 elems, 2108 }) 2109 } 2110 } 2111 2112 #[cfg(feature = "full")] 2113 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2114 impl Parse for ExprRepeat { 2115 fn parse(input: ParseStream) -> Result<Self> { 2116 let content; 2117 Ok(ExprRepeat { 2118 bracket_token: bracketed!(content in input), 2119 attrs: Vec::new(), 2120 expr: content.parse()?, 2121 semi_token: content.parse()?, 2122 len: content.parse()?, 2123 }) 2124 } 2125 } 2126 2127 #[cfg(feature = "full")] 2128 fn continue_parsing_early(mut expr: &Expr) -> bool { 2129 while let Expr::Group(group) = expr { 2130 expr = &group.expr; 2131 } 2132 match expr { 2133 Expr::If(_) 2134 | Expr::While(_) 2135 | Expr::ForLoop(_) 2136 | Expr::Loop(_) 2137 | Expr::Match(_) 2138 | Expr::TryBlock(_) 2139 | Expr::Unsafe(_) 2140 | Expr::Const(_) 2141 | Expr::Block(_) => false, 2142 _ => true, 2143 } 2144 } 2145 2146 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2147 impl Parse for ExprLit { 2148 fn parse(input: ParseStream) -> Result<Self> { 2149 Ok(ExprLit { 2150 attrs: Vec::new(), 2151 lit: input.parse()?, 2152 }) 2153 } 2154 } 2155 2156 fn expr_group( 2157 input: ParseStream, 2158 #[cfg(feature = "full")] allow_struct: AllowStruct, 2159 ) -> Result<Expr> { 2160 let group = crate::group::parse_group(input)?; 2161 let mut inner: Expr = group.content.parse()?; 2162 2163 match inner { 2164 Expr::Path(mut expr) if expr.attrs.is_empty() => { 2165 let grouped_len = expr.path.segments.len(); 2166 Path::parse_rest(input, &mut expr.path, true)?; 2167 match rest_of_path_or_macro_or_struct( 2168 expr.qself, 2169 expr.path, 2170 input, 2171 #[cfg(feature = "full")] 2172 allow_struct, 2173 )? { 2174 Expr::Path(expr) if expr.path.segments.len() == grouped_len => { 2175 inner = Expr::Path(expr); 2176 } 2177 extended => return Ok(extended), 2178 } 2179 } 2180 _ => {} 2181 } 2182 2183 Ok(Expr::Group(ExprGroup { 2184 attrs: Vec::new(), 2185 group_token: group.token, 2186 expr: Box::new(inner), 2187 })) 2188 } 2189 2190 #[cfg(feature = "full")] 2191 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2192 impl Parse for ExprParen { 2193 fn parse(input: ParseStream) -> Result<Self> { 2194 let content; 2195 Ok(ExprParen { 2196 attrs: Vec::new(), 2197 paren_token: parenthesized!(content in input), 2198 expr: content.parse()?, 2199 }) 2200 } 2201 } 2202 2203 #[cfg(feature = "full")] 2204 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2205 impl Parse for ExprLet { 2206 fn parse(input: ParseStream) -> Result<Self> { 2207 let allow_struct = AllowStruct(true); 2208 expr_let(input, allow_struct) 2209 } 2210 } 2211 2212 #[cfg(feature = "full")] 2213 fn expr_let(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprLet> { 2214 Ok(ExprLet { 2215 attrs: Vec::new(), 2216 let_token: input.parse()?, 2217 pat: Box::new(Pat::parse_multi_with_leading_vert(input)?), 2218 eq_token: input.parse()?, 2219 expr: Box::new({ 2220 let lhs = unary_expr(input, allow_struct)?; 2221 parse_expr(input, lhs, allow_struct, Precedence::Compare)? 2222 }), 2223 }) 2224 } 2225 2226 #[cfg(feature = "full")] 2227 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2228 impl Parse for ExprIf { 2229 fn parse(input: ParseStream) -> Result<Self> { 2230 let attrs = input.call(Attribute::parse_outer)?; 2231 2232 let mut clauses = Vec::new(); 2233 let mut expr; 2234 loop { 2235 let if_token: Token![if] = input.parse()?; 2236 let cond = input.call(Expr::parse_without_eager_brace)?; 2237 let then_branch: Block = input.parse()?; 2238 2239 expr = ExprIf { 2240 attrs: Vec::new(), 2241 if_token, 2242 cond: Box::new(cond), 2243 then_branch, 2244 else_branch: None, 2245 }; 2246 2247 if !input.peek(Token![else]) { 2248 break; 2249 } 2250 2251 let else_token: Token![else] = input.parse()?; 2252 let lookahead = input.lookahead1(); 2253 if lookahead.peek(Token![if]) { 2254 expr.else_branch = Some((else_token, Box::new(Expr::PLACEHOLDER))); 2255 clauses.push(expr); 2256 } else if lookahead.peek(token::Brace) { 2257 expr.else_branch = Some(( 2258 else_token, 2259 Box::new(Expr::Block(ExprBlock { 2260 attrs: Vec::new(), 2261 label: None, 2262 block: input.parse()?, 2263 })), 2264 )); 2265 break; 2266 } else { 2267 return Err(lookahead.error()); 2268 } 2269 } 2270 2271 while let Some(mut prev) = clauses.pop() { 2272 *prev.else_branch.as_mut().unwrap().1 = Expr::If(expr); 2273 expr = prev; 2274 } 2275 expr.attrs = attrs; 2276 Ok(expr) 2277 } 2278 } 2279 2280 #[cfg(feature = "full")] 2281 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2282 impl Parse for ExprInfer { 2283 fn parse(input: ParseStream) -> Result<Self> { 2284 Ok(ExprInfer { 2285 attrs: input.call(Attribute::parse_outer)?, 2286 underscore_token: input.parse()?, 2287 }) 2288 } 2289 } 2290 2291 #[cfg(feature = "full")] 2292 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2293 impl Parse for ExprForLoop { 2294 fn parse(input: ParseStream) -> Result<Self> { 2295 let mut attrs = input.call(Attribute::parse_outer)?; 2296 let label: Option<Label> = input.parse()?; 2297 let for_token: Token![for] = input.parse()?; 2298 2299 let pat = Pat::parse_multi_with_leading_vert(input)?; 2300 2301 let in_token: Token![in] = input.parse()?; 2302 let expr: Expr = input.call(Expr::parse_without_eager_brace)?; 2303 2304 let content; 2305 let brace_token = braced!(content in input); 2306 attr::parsing::parse_inner(&content, &mut attrs)?; 2307 let stmts = content.call(Block::parse_within)?; 2308 2309 Ok(ExprForLoop { 2310 attrs, 2311 label, 2312 for_token, 2313 pat: Box::new(pat), 2314 in_token, 2315 expr: Box::new(expr), 2316 body: Block { brace_token, stmts }, 2317 }) 2318 } 2319 } 2320 2321 #[cfg(feature = "full")] 2322 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2323 impl Parse for ExprLoop { 2324 fn parse(input: ParseStream) -> Result<Self> { 2325 let mut attrs = input.call(Attribute::parse_outer)?; 2326 let label: Option<Label> = input.parse()?; 2327 let loop_token: Token![loop] = input.parse()?; 2328 2329 let content; 2330 let brace_token = braced!(content in input); 2331 attr::parsing::parse_inner(&content, &mut attrs)?; 2332 let stmts = content.call(Block::parse_within)?; 2333 2334 Ok(ExprLoop { 2335 attrs, 2336 label, 2337 loop_token, 2338 body: Block { brace_token, stmts }, 2339 }) 2340 } 2341 } 2342 2343 #[cfg(feature = "full")] 2344 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2345 impl Parse for ExprMatch { 2346 fn parse(input: ParseStream) -> Result<Self> { 2347 let mut attrs = input.call(Attribute::parse_outer)?; 2348 let match_token: Token![match] = input.parse()?; 2349 let expr = Expr::parse_without_eager_brace(input)?; 2350 2351 let content; 2352 let brace_token = braced!(content in input); 2353 attr::parsing::parse_inner(&content, &mut attrs)?; 2354 2355 let arms = Arm::parse_multiple(&content)?; 2356 2357 Ok(ExprMatch { 2358 attrs, 2359 match_token, 2360 expr: Box::new(expr), 2361 brace_token, 2362 arms, 2363 }) 2364 } 2365 } 2366 2367 macro_rules! impl_by_parsing_expr { 2368 ( 2369 $( 2370 $expr_type:ty, $variant:ident, $msg:expr, 2371 )* 2372 ) => { 2373 $( 2374 #[cfg(all(feature = "full", feature = "printing"))] 2375 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2376 impl Parse for $expr_type { 2377 fn parse(input: ParseStream) -> Result<Self> { 2378 let mut expr: Expr = input.parse()?; 2379 loop { 2380 match expr { 2381 Expr::$variant(inner) => return Ok(inner), 2382 Expr::Group(next) => expr = *next.expr, 2383 _ => return Err(Error::new_spanned(expr, $msg)), 2384 } 2385 } 2386 } 2387 } 2388 )* 2389 }; 2390 } 2391 2392 impl_by_parsing_expr! { 2393 ExprAssign, Assign, "expected assignment expression", 2394 ExprAwait, Await, "expected await expression", 2395 ExprBinary, Binary, "expected binary operation", 2396 ExprCall, Call, "expected function call expression", 2397 ExprCast, Cast, "expected cast expression", 2398 ExprField, Field, "expected struct field access", 2399 ExprIndex, Index, "expected indexing expression", 2400 ExprMethodCall, MethodCall, "expected method call expression", 2401 ExprRange, Range, "expected range expression", 2402 ExprTry, Try, "expected try expression", 2403 ExprTuple, Tuple, "expected tuple expression", 2404 } 2405 2406 #[cfg(feature = "full")] 2407 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2408 impl Parse for ExprUnary { 2409 fn parse(input: ParseStream) -> Result<Self> { 2410 let attrs = Vec::new(); 2411 let allow_struct = AllowStruct(true); 2412 expr_unary(input, attrs, allow_struct) 2413 } 2414 } 2415 2416 #[cfg(feature = "full")] 2417 fn expr_unary( 2418 input: ParseStream, 2419 attrs: Vec<Attribute>, 2420 allow_struct: AllowStruct, 2421 ) -> Result<ExprUnary> { 2422 Ok(ExprUnary { 2423 attrs, 2424 op: input.parse()?, 2425 expr: Box::new(unary_expr(input, allow_struct)?), 2426 }) 2427 } 2428 2429 #[cfg(feature = "full")] 2430 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2431 impl Parse for ExprClosure { 2432 fn parse(input: ParseStream) -> Result<Self> { 2433 let allow_struct = AllowStruct(true); 2434 expr_closure(input, allow_struct) 2435 } 2436 } 2437 2438 #[cfg(feature = "full")] 2439 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2440 impl Parse for ExprRawAddr { 2441 fn parse(input: ParseStream) -> Result<Self> { 2442 let allow_struct = AllowStruct(true); 2443 Ok(ExprRawAddr { 2444 attrs: Vec::new(), 2445 and_token: input.parse()?, 2446 raw: input.parse()?, 2447 mutability: input.parse()?, 2448 expr: Box::new(unary_expr(input, allow_struct)?), 2449 }) 2450 } 2451 } 2452 2453 #[cfg(feature = "full")] 2454 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2455 impl Parse for ExprReference { 2456 fn parse(input: ParseStream) -> Result<Self> { 2457 let allow_struct = AllowStruct(true); 2458 Ok(ExprReference { 2459 attrs: Vec::new(), 2460 and_token: input.parse()?, 2461 mutability: input.parse()?, 2462 expr: Box::new(unary_expr(input, allow_struct)?), 2463 }) 2464 } 2465 } 2466 2467 #[cfg(feature = "full")] 2468 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2469 impl Parse for ExprBreak { 2470 fn parse(input: ParseStream) -> Result<Self> { 2471 let allow_struct = AllowStruct(true); 2472 expr_break(input, allow_struct) 2473 } 2474 } 2475 2476 #[cfg(feature = "full")] 2477 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2478 impl Parse for ExprReturn { 2479 fn parse(input: ParseStream) -> Result<Self> { 2480 Ok(ExprReturn { 2481 attrs: Vec::new(), 2482 return_token: input.parse()?, 2483 expr: { 2484 if Expr::peek(input) { 2485 Some(input.parse()?) 2486 } else { 2487 None 2488 } 2489 }, 2490 }) 2491 } 2492 } 2493 2494 #[cfg(feature = "full")] 2495 fn expr_become(input: ParseStream) -> Result<Expr> { 2496 let begin = input.fork(); 2497 input.parse::<Token![become]>()?; 2498 input.parse::<Expr>()?; 2499 Ok(Expr::Verbatim(verbatim::between(&begin, input))) 2500 } 2501 2502 #[cfg(feature = "full")] 2503 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2504 impl Parse for ExprTryBlock { 2505 fn parse(input: ParseStream) -> Result<Self> { 2506 Ok(ExprTryBlock { 2507 attrs: Vec::new(), 2508 try_token: input.parse()?, 2509 block: input.parse()?, 2510 }) 2511 } 2512 } 2513 2514 #[cfg(feature = "full")] 2515 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2516 impl Parse for ExprYield { 2517 fn parse(input: ParseStream) -> Result<Self> { 2518 Ok(ExprYield { 2519 attrs: Vec::new(), 2520 yield_token: input.parse()?, 2521 expr: { 2522 if Expr::peek(input) { 2523 Some(input.parse()?) 2524 } else { 2525 None 2526 } 2527 }, 2528 }) 2529 } 2530 } 2531 2532 #[cfg(feature = "full")] 2533 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> { 2534 let lifetimes: Option<BoundLifetimes> = input.parse()?; 2535 let constness: Option<Token![const]> = input.parse()?; 2536 let movability: Option<Token![static]> = input.parse()?; 2537 let asyncness: Option<Token![async]> = input.parse()?; 2538 let capture: Option<Token![move]> = input.parse()?; 2539 let or1_token: Token![|] = input.parse()?; 2540 2541 let mut inputs = Punctuated::new(); 2542 loop { 2543 if input.peek(Token![|]) { 2544 break; 2545 } 2546 let value = closure_arg(input)?; 2547 inputs.push_value(value); 2548 if input.peek(Token![|]) { 2549 break; 2550 } 2551 let punct: Token![,] = input.parse()?; 2552 inputs.push_punct(punct); 2553 } 2554 2555 let or2_token: Token![|] = input.parse()?; 2556 2557 let (output, body) = if input.peek(Token![->]) { 2558 let arrow_token: Token![->] = input.parse()?; 2559 let ty: Type = input.parse()?; 2560 let body: Block = input.parse()?; 2561 let output = ReturnType::Type(arrow_token, Box::new(ty)); 2562 let block = Expr::Block(ExprBlock { 2563 attrs: Vec::new(), 2564 label: None, 2565 block: body, 2566 }); 2567 (output, block) 2568 } else { 2569 let body = ambiguous_expr(input, allow_struct)?; 2570 (ReturnType::Default, body) 2571 }; 2572 2573 Ok(ExprClosure { 2574 attrs: Vec::new(), 2575 lifetimes, 2576 constness, 2577 movability, 2578 asyncness, 2579 capture, 2580 or1_token, 2581 inputs, 2582 or2_token, 2583 output, 2584 body: Box::new(body), 2585 }) 2586 } 2587 2588 #[cfg(feature = "full")] 2589 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2590 impl Parse for ExprAsync { 2591 fn parse(input: ParseStream) -> Result<Self> { 2592 Ok(ExprAsync { 2593 attrs: Vec::new(), 2594 async_token: input.parse()?, 2595 capture: input.parse()?, 2596 block: input.parse()?, 2597 }) 2598 } 2599 } 2600 2601 #[cfg(feature = "full")] 2602 fn closure_arg(input: ParseStream) -> Result<Pat> { 2603 let attrs = input.call(Attribute::parse_outer)?; 2604 let mut pat = Pat::parse_single(input)?; 2605 2606 if input.peek(Token![:]) { 2607 Ok(Pat::Type(PatType { 2608 attrs, 2609 pat: Box::new(pat), 2610 colon_token: input.parse()?, 2611 ty: input.parse()?, 2612 })) 2613 } else { 2614 match &mut pat { 2615 Pat::Const(pat) => pat.attrs = attrs, 2616 Pat::Ident(pat) => pat.attrs = attrs, 2617 Pat::Lit(pat) => pat.attrs = attrs, 2618 Pat::Macro(pat) => pat.attrs = attrs, 2619 Pat::Or(pat) => pat.attrs = attrs, 2620 Pat::Paren(pat) => pat.attrs = attrs, 2621 Pat::Path(pat) => pat.attrs = attrs, 2622 Pat::Range(pat) => pat.attrs = attrs, 2623 Pat::Reference(pat) => pat.attrs = attrs, 2624 Pat::Rest(pat) => pat.attrs = attrs, 2625 Pat::Slice(pat) => pat.attrs = attrs, 2626 Pat::Struct(pat) => pat.attrs = attrs, 2627 Pat::Tuple(pat) => pat.attrs = attrs, 2628 Pat::TupleStruct(pat) => pat.attrs = attrs, 2629 Pat::Type(_) => unreachable!(), 2630 Pat::Verbatim(_) => {} 2631 Pat::Wild(pat) => pat.attrs = attrs, 2632 } 2633 Ok(pat) 2634 } 2635 } 2636 2637 #[cfg(feature = "full")] 2638 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2639 impl Parse for ExprWhile { 2640 fn parse(input: ParseStream) -> Result<Self> { 2641 let mut attrs = input.call(Attribute::parse_outer)?; 2642 let label: Option<Label> = input.parse()?; 2643 let while_token: Token![while] = input.parse()?; 2644 let cond = Expr::parse_without_eager_brace(input)?; 2645 2646 let content; 2647 let brace_token = braced!(content in input); 2648 attr::parsing::parse_inner(&content, &mut attrs)?; 2649 let stmts = content.call(Block::parse_within)?; 2650 2651 Ok(ExprWhile { 2652 attrs, 2653 label, 2654 while_token, 2655 cond: Box::new(cond), 2656 body: Block { brace_token, stmts }, 2657 }) 2658 } 2659 } 2660 2661 #[cfg(feature = "full")] 2662 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2663 impl Parse for ExprConst { 2664 fn parse(input: ParseStream) -> Result<Self> { 2665 let const_token: Token![const] = input.parse()?; 2666 2667 let content; 2668 let brace_token = braced!(content in input); 2669 let inner_attrs = content.call(Attribute::parse_inner)?; 2670 let stmts = content.call(Block::parse_within)?; 2671 2672 Ok(ExprConst { 2673 attrs: inner_attrs, 2674 const_token, 2675 block: Block { brace_token, stmts }, 2676 }) 2677 } 2678 } 2679 2680 #[cfg(feature = "full")] 2681 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2682 impl Parse for Label { 2683 fn parse(input: ParseStream) -> Result<Self> { 2684 Ok(Label { 2685 name: input.parse()?, 2686 colon_token: input.parse()?, 2687 }) 2688 } 2689 } 2690 2691 #[cfg(feature = "full")] 2692 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2693 impl Parse for Option<Label> { 2694 fn parse(input: ParseStream) -> Result<Self> { 2695 if input.peek(Lifetime) { 2696 input.parse().map(Some) 2697 } else { 2698 Ok(None) 2699 } 2700 } 2701 } 2702 2703 #[cfg(feature = "full")] 2704 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2705 impl Parse for ExprContinue { 2706 fn parse(input: ParseStream) -> Result<Self> { 2707 Ok(ExprContinue { 2708 attrs: Vec::new(), 2709 continue_token: input.parse()?, 2710 label: input.parse()?, 2711 }) 2712 } 2713 } 2714 2715 #[cfg(feature = "full")] 2716 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> { 2717 let break_token: Token![break] = input.parse()?; 2718 2719 let ahead = input.fork(); 2720 let label: Option<Lifetime> = ahead.parse()?; 2721 if label.is_some() && ahead.peek(Token![:]) { 2722 // Not allowed: `break 'label: loop {...}` 2723 // Parentheses are required. `break ('label: loop {...})` 2724 let _: Expr = input.parse()?; 2725 let start_span = label.unwrap().apostrophe; 2726 let end_span = input.cursor().prev_span(); 2727 return Err(crate::error::new2( 2728 start_span, 2729 end_span, 2730 "parentheses required", 2731 )); 2732 } 2733 2734 input.advance_to(&ahead); 2735 let expr = if Expr::peek(input) && (allow_struct.0 || !input.peek(token::Brace)) { 2736 Some(input.parse()?) 2737 } else { 2738 None 2739 }; 2740 2741 Ok(ExprBreak { 2742 attrs: Vec::new(), 2743 break_token, 2744 label, 2745 expr, 2746 }) 2747 } 2748 2749 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2750 impl Parse for FieldValue { 2751 fn parse(input: ParseStream) -> Result<Self> { 2752 let attrs = input.call(Attribute::parse_outer)?; 2753 let member: Member = input.parse()?; 2754 let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() { 2755 let colon_token: Token![:] = input.parse()?; 2756 let value: Expr = input.parse()?; 2757 (Some(colon_token), value) 2758 } else if let Member::Named(ident) = &member { 2759 let value = Expr::Path(ExprPath { 2760 attrs: Vec::new(), 2761 qself: None, 2762 path: Path::from(ident.clone()), 2763 }); 2764 (None, value) 2765 } else { 2766 unreachable!() 2767 }; 2768 2769 Ok(FieldValue { 2770 attrs, 2771 member, 2772 colon_token, 2773 expr: value, 2774 }) 2775 } 2776 } 2777 2778 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2779 impl Parse for ExprStruct { 2780 fn parse(input: ParseStream) -> Result<Self> { 2781 let expr_style = true; 2782 let (qself, path) = path::parsing::qpath(input, expr_style)?; 2783 expr_struct_helper(input, qself, path) 2784 } 2785 } 2786 2787 fn expr_struct_helper( 2788 input: ParseStream, 2789 qself: Option<QSelf>, 2790 path: Path, 2791 ) -> Result<ExprStruct> { 2792 let content; 2793 let brace_token = braced!(content in input); 2794 2795 let mut fields = Punctuated::new(); 2796 while !content.is_empty() { 2797 if content.peek(Token![..]) { 2798 return Ok(ExprStruct { 2799 attrs: Vec::new(), 2800 qself, 2801 path, 2802 brace_token, 2803 fields, 2804 dot2_token: Some(content.parse()?), 2805 rest: if content.is_empty() { 2806 None 2807 } else { 2808 Some(Box::new(content.parse()?)) 2809 }, 2810 }); 2811 } 2812 2813 fields.push(content.parse()?); 2814 if content.is_empty() { 2815 break; 2816 } 2817 let punct: Token![,] = content.parse()?; 2818 fields.push_punct(punct); 2819 } 2820 2821 Ok(ExprStruct { 2822 attrs: Vec::new(), 2823 qself, 2824 path, 2825 brace_token, 2826 fields, 2827 dot2_token: None, 2828 rest: None, 2829 }) 2830 } 2831 2832 #[cfg(feature = "full")] 2833 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2834 impl Parse for ExprUnsafe { 2835 fn parse(input: ParseStream) -> Result<Self> { 2836 let unsafe_token: Token![unsafe] = input.parse()?; 2837 2838 let content; 2839 let brace_token = braced!(content in input); 2840 let inner_attrs = content.call(Attribute::parse_inner)?; 2841 let stmts = content.call(Block::parse_within)?; 2842 2843 Ok(ExprUnsafe { 2844 attrs: inner_attrs, 2845 unsafe_token, 2846 block: Block { brace_token, stmts }, 2847 }) 2848 } 2849 } 2850 2851 #[cfg(feature = "full")] 2852 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2853 impl Parse for ExprBlock { 2854 fn parse(input: ParseStream) -> Result<Self> { 2855 let mut attrs = input.call(Attribute::parse_outer)?; 2856 let label: Option<Label> = input.parse()?; 2857 2858 let content; 2859 let brace_token = braced!(content in input); 2860 attr::parsing::parse_inner(&content, &mut attrs)?; 2861 let stmts = content.call(Block::parse_within)?; 2862 2863 Ok(ExprBlock { 2864 attrs, 2865 label, 2866 block: Block { brace_token, stmts }, 2867 }) 2868 } 2869 } 2870 2871 #[cfg(feature = "full")] 2872 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> { 2873 let limits: RangeLimits = input.parse()?; 2874 let end = parse_range_end(input, &limits, allow_struct)?; 2875 Ok(ExprRange { 2876 attrs: Vec::new(), 2877 start: None, 2878 limits, 2879 end, 2880 }) 2881 } 2882 2883 #[cfg(feature = "full")] 2884 fn parse_range_end( 2885 input: ParseStream, 2886 limits: &RangeLimits, 2887 allow_struct: AllowStruct, 2888 ) -> Result<Option<Box<Expr>>> { 2889 if matches!(limits, RangeLimits::HalfOpen(_)) 2890 && (input.is_empty() 2891 || input.peek(Token![,]) 2892 || input.peek(Token![;]) 2893 || input.peek(Token![.]) && !input.peek(Token![..]) 2894 || input.peek(Token![?]) 2895 || input.peek(Token![=>]) 2896 || !allow_struct.0 && input.peek(token::Brace) 2897 || input.peek(Token![=]) 2898 || input.peek(Token![+]) 2899 || input.peek(Token![/]) 2900 || input.peek(Token![%]) 2901 || input.peek(Token![^]) 2902 || input.peek(Token![>]) 2903 || input.peek(Token![<=]) 2904 || input.peek(Token![!=]) 2905 || input.peek(Token![-=]) 2906 || input.peek(Token![*=]) 2907 || input.peek(Token![&=]) 2908 || input.peek(Token![|=]) 2909 || input.peek(Token![<<=]) 2910 || input.peek(Token![as])) 2911 { 2912 Ok(None) 2913 } else { 2914 let end = parse_binop_rhs(input, allow_struct, Precedence::Range)?; 2915 Ok(Some(end)) 2916 } 2917 } 2918 2919 #[cfg(feature = "full")] 2920 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2921 impl Parse for RangeLimits { 2922 fn parse(input: ParseStream) -> Result<Self> { 2923 let lookahead = input.lookahead1(); 2924 let dot_dot = lookahead.peek(Token![..]); 2925 let dot_dot_eq = dot_dot && lookahead.peek(Token![..=]); 2926 let dot_dot_dot = dot_dot && input.peek(Token![...]); 2927 if dot_dot_eq { 2928 input.parse().map(RangeLimits::Closed) 2929 } else if dot_dot && !dot_dot_dot { 2930 input.parse().map(RangeLimits::HalfOpen) 2931 } else { 2932 Err(lookahead.error()) 2933 } 2934 } 2935 } 2936 2937 #[cfg(feature = "full")] 2938 impl RangeLimits { 2939 pub(crate) fn parse_obsolete(input: ParseStream) -> Result<Self> { 2940 let lookahead = input.lookahead1(); 2941 let dot_dot = lookahead.peek(Token![..]); 2942 let dot_dot_eq = dot_dot && lookahead.peek(Token![..=]); 2943 let dot_dot_dot = dot_dot && input.peek(Token![...]); 2944 if dot_dot_eq { 2945 input.parse().map(RangeLimits::Closed) 2946 } else if dot_dot_dot { 2947 let dot3: Token![...] = input.parse()?; 2948 Ok(RangeLimits::Closed(Token)) 2949 } else if dot_dot { 2950 input.parse().map(RangeLimits::HalfOpen) 2951 } else { 2952 Err(lookahead.error()) 2953 } 2954 } 2955 } 2956 2957 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2958 impl Parse for ExprPath { 2959 fn parse(input: ParseStream) -> Result<Self> { 2960 #[cfg(not(feature = "full"))] 2961 let attrs = Vec::new(); 2962 #[cfg(feature = "full")] 2963 let attrs = input.call(Attribute::parse_outer)?; 2964 2965 let expr_style = true; 2966 let (qself, path) = path::parsing::qpath(input, expr_style)?; 2967 2968 Ok(ExprPath { attrs, qself, path }) 2969 } 2970 } 2971 2972 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2973 impl Parse for Member { 2974 fn parse(input: ParseStream) -> Result<Self> { 2975 if input.peek(Ident) { 2976 input.parse().map(Member::Named) 2977 } else if input.peek(LitInt) { 2978 input.parse().map(Member::Unnamed) 2979 } else { 2980 Err(input.error("expected identifier or integer")) 2981 } 2982 } 2983 } 2984 2985 #[cfg(feature = "full")] 2986 impl Arm { 2987 pub(crate) fn parse_multiple(input: ParseStream) -> Result<Vec<Self>> { 2988 let mut arms = Vec::new(); 2989 while !input.is_empty() { 2990 arms.push(input.call(Arm::parse)?); 2991 } 2992 Ok(arms) 2993 } 2994 } 2995 2996 #[cfg(feature = "full")] 2997 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 2998 impl Parse for Arm { 2999 fn parse(input: ParseStream) -> Result<Arm> { 3000 let requires_comma; 3001 Ok(Arm { 3002 attrs: input.call(Attribute::parse_outer)?, 3003 pat: Pat::parse_multi_with_leading_vert(input)?, 3004 guard: { 3005 if input.peek(Token![if]) { 3006 let if_token: Token![if] = input.parse()?; 3007 let guard: Expr = input.parse()?; 3008 Some((if_token, Box::new(guard))) 3009 } else { 3010 None 3011 } 3012 }, 3013 fat_arrow_token: input.parse()?, 3014 body: { 3015 let body = Expr::parse_with_earlier_boundary_rule(input)?; 3016 requires_comma = classify::requires_comma_to_be_match_arm(&body); 3017 Box::new(body) 3018 }, 3019 comma: { 3020 if requires_comma && !input.is_empty() { 3021 Some(input.parse()?) 3022 } else { 3023 input.parse()? 3024 } 3025 }, 3026 }) 3027 } 3028 } 3029 3030 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 3031 impl Parse for Index { 3032 fn parse(input: ParseStream) -> Result<Self> { 3033 let lit: LitInt = input.parse()?; 3034 if lit.suffix().is_empty() { 3035 Ok(Index { 3036 index: lit 3037 .base10_digits() 3038 .parse() 3039 .map_err(|err| Error::new(lit.span(), err))?, 3040 span: lit.span(), 3041 }) 3042 } else { 3043 Err(Error::new(lit.span(), "expected unsuffixed integer")) 3044 } 3045 } 3046 } 3047 3048 fn multi_index(e: &mut Expr, dot_token: &mut Token![.], float: LitFloat) -> Result<bool> { 3049 let float_token = float.token(); 3050 let float_span = float_token.span(); 3051 let mut float_repr = float_token.to_string(); 3052 let trailing_dot = float_repr.ends_with('.'); 3053 if trailing_dot { 3054 float_repr.truncate(float_repr.len() - 1); 3055 } 3056 3057 let mut offset = 0; 3058 for part in float_repr.split('.') { 3059 let mut index: Index = 3060 crate::parse_str(part).map_err(|err| Error::new(float_span, err))?; 3061 let part_end = offset + part.len(); 3062 index.span = float_token.subspan(offset..part_end).unwrap_or(float_span); 3063 3064 let base = mem::replace(e, Expr::PLACEHOLDER); 3065 *e = Expr::Field(ExprField { 3066 attrs: Vec::new(), 3067 base: Box::new(base), 3068 dot_token: Token, 3069 member: Member::Unnamed(index), 3070 }); 3071 3072 let dot_span = float_token 3073 .subspan(part_end..part_end + 1) 3074 .unwrap_or(float_span); 3075 *dot_token = Token; 3076 offset = part_end + 1; 3077 } 3078 3079 Ok(!trailing_dot) 3080 } 3081 3082 #[cfg(feature = "full")] 3083 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 3084 impl Parse for PointerMutability { 3085 fn parse(input: ParseStream) -> Result<Self> { 3086 let lookahead = input.lookahead1(); 3087 if lookahead.peek(Token![const]) { 3088 Ok(PointerMutability::Const(input.parse()?)) 3089 } else if lookahead.peek(Token![mut]) { 3090 Ok(PointerMutability::Mut(input.parse()?)) 3091 } else { 3092 Err(lookahead.error()) 3093 } 3094 } 3095 } 3096 3097 fn check_cast(input: ParseStream) -> Result<()> { 3098 let kind = if input.peek(Token![.]) && !input.peek(Token![..]) { 3099 if input.peek2(Token![await]) { 3100 "`.await`" 3101 } else if input.peek2(Ident) && (input.peek3(token::Paren) || input.peek3(Token![::])) { 3102 "a method call" 3103 } else { 3104 "a field access" 3105 } 3106 } else if input.peek(Token![?]) { 3107 "`?`" 3108 } else if input.peek(token::Bracket) { 3109 "indexing" 3110 } else if input.peek(token::Paren) { 3111 "a function call" 3112 } else { 3113 return Ok(()); 3114 }; 3115 let msg = format!("casts cannot be followed by {}", kind); 3116 Err(input.error(msg)) 3117 } 3118 } 3119 3120 #[cfg(feature = "printing")] 3121 pub(crate) mod printing { 3122 use crate::attr::Attribute; 3123 #[cfg(feature = "full")] 3124 use crate::attr::FilterAttrs; 3125 #[cfg(feature = "full")] 3126 use crate::classify; 3127 #[cfg(feature = "full")] 3128 use crate::expr::{ 3129 Arm, ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure, 3130 ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch, 3131 ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprUnsafe, 3132 ExprWhile, ExprYield, Label, PointerMutability, RangeLimits, 3133 }; 3134 use crate::expr::{ 3135 Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro, 3136 ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprTuple, ExprUnary, 3137 FieldValue, Index, Member, 3138 }; 3139 use crate::fixup::FixupContext; 3140 use crate::op::BinOp; 3141 use crate::path; 3142 use crate::path::printing::PathStyle; 3143 use crate::precedence::Precedence; 3144 use crate::token; 3145 #[cfg(feature = "full")] 3146 use crate::ty::ReturnType; 3147 use proc_macro2::{Literal, Span, TokenStream}; 3148 use quote::{ToTokens, TokenStreamExt}; 3149 3150 #[cfg(feature = "full")] 3151 pub(crate) fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) { 3152 tokens.append_all(attrs.outer()); 3153 } 3154 3155 #[cfg(feature = "full")] 3156 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) { 3157 tokens.append_all(attrs.inner()); 3158 } 3159 3160 #[cfg(not(feature = "full"))] 3161 pub(crate) fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {} 3162 3163 pub(crate) fn print_subexpression( 3164 expr: &Expr, 3165 needs_group: bool, 3166 tokens: &mut TokenStream, 3167 mut fixup: FixupContext, 3168 ) { 3169 if needs_group { 3170 // If we are surrounding the whole cond in parentheses, such as: 3171 // 3172 // if (return Struct {}) {} 3173 // 3174 // then there is no need for parenthesizing the individual struct 3175 // expressions within. On the other hand if the whole cond is not 3176 // parenthesized, then print_expr must parenthesize exterior struct 3177 // literals. 3178 // 3179 // if x == (Struct {}) {} 3180 // 3181 fixup = FixupContext::NONE; 3182 } 3183 3184 let do_print_expr = |tokens: &mut TokenStream| print_expr(expr, tokens, fixup); 3185 3186 if needs_group { 3187 token::Paren::default().surround(tokens, do_print_expr); 3188 } else { 3189 do_print_expr(tokens); 3190 } 3191 } 3192 3193 pub(crate) fn print_expr(expr: &Expr, tokens: &mut TokenStream, mut fixup: FixupContext) { 3194 #[cfg(feature = "full")] 3195 let needs_group = fixup.parenthesize(expr); 3196 #[cfg(not(feature = "full"))] 3197 let needs_group = false; 3198 3199 if needs_group { 3200 fixup = FixupContext::NONE; 3201 } 3202 3203 let do_print_expr = |tokens: &mut TokenStream| match expr { 3204 #[cfg(feature = "full")] 3205 Expr::Array(e) => e.to_tokens(tokens), 3206 #[cfg(feature = "full")] 3207 Expr::Assign(e) => print_expr_assign(e, tokens, fixup), 3208 #[cfg(feature = "full")] 3209 Expr::Async(e) => e.to_tokens(tokens), 3210 #[cfg(feature = "full")] 3211 Expr::Await(e) => print_expr_await(e, tokens, fixup), 3212 Expr::Binary(e) => print_expr_binary(e, tokens, fixup), 3213 #[cfg(feature = "full")] 3214 Expr::Block(e) => e.to_tokens(tokens), 3215 #[cfg(feature = "full")] 3216 Expr::Break(e) => print_expr_break(e, tokens, fixup), 3217 Expr::Call(e) => print_expr_call(e, tokens, fixup), 3218 Expr::Cast(e) => print_expr_cast(e, tokens, fixup), 3219 #[cfg(feature = "full")] 3220 Expr::Closure(e) => print_expr_closure(e, tokens, fixup), 3221 #[cfg(feature = "full")] 3222 Expr::Const(e) => e.to_tokens(tokens), 3223 #[cfg(feature = "full")] 3224 Expr::Continue(e) => e.to_tokens(tokens), 3225 Expr::Field(e) => print_expr_field(e, tokens, fixup), 3226 #[cfg(feature = "full")] 3227 Expr::ForLoop(e) => e.to_tokens(tokens), 3228 Expr::Group(e) => e.to_tokens(tokens), 3229 #[cfg(feature = "full")] 3230 Expr::If(e) => e.to_tokens(tokens), 3231 Expr::Index(e) => print_expr_index(e, tokens, fixup), 3232 #[cfg(feature = "full")] 3233 Expr::Infer(e) => e.to_tokens(tokens), 3234 #[cfg(feature = "full")] 3235 Expr::Let(e) => print_expr_let(e, tokens, fixup), 3236 Expr::Lit(e) => e.to_tokens(tokens), 3237 #[cfg(feature = "full")] 3238 Expr::Loop(e) => e.to_tokens(tokens), 3239 Expr::Macro(e) => e.to_tokens(tokens), 3240 #[cfg(feature = "full")] 3241 Expr::Match(e) => e.to_tokens(tokens), 3242 Expr::MethodCall(e) => print_expr_method_call(e, tokens, fixup), 3243 Expr::Paren(e) => e.to_tokens(tokens), 3244 Expr::Path(e) => e.to_tokens(tokens), 3245 #[cfg(feature = "full")] 3246 Expr::Range(e) => print_expr_range(e, tokens, fixup), 3247 #[cfg(feature = "full")] 3248 Expr::RawAddr(e) => print_expr_raw_addr(e, tokens, fixup), 3249 Expr::Reference(e) => print_expr_reference(e, tokens, fixup), 3250 #[cfg(feature = "full")] 3251 Expr::Repeat(e) => e.to_tokens(tokens), 3252 #[cfg(feature = "full")] 3253 Expr::Return(e) => print_expr_return(e, tokens, fixup), 3254 Expr::Struct(e) => e.to_tokens(tokens), 3255 #[cfg(feature = "full")] 3256 Expr::Try(e) => print_expr_try(e, tokens, fixup), 3257 #[cfg(feature = "full")] 3258 Expr::TryBlock(e) => e.to_tokens(tokens), 3259 Expr::Tuple(e) => e.to_tokens(tokens), 3260 Expr::Unary(e) => print_expr_unary(e, tokens, fixup), 3261 #[cfg(feature = "full")] 3262 Expr::Unsafe(e) => e.to_tokens(tokens), 3263 Expr::Verbatim(e) => e.to_tokens(tokens), 3264 #[cfg(feature = "full")] 3265 Expr::While(e) => e.to_tokens(tokens), 3266 #[cfg(feature = "full")] 3267 Expr::Yield(e) => print_expr_yield(e, tokens, fixup), 3268 3269 #[cfg(not(feature = "full"))] 3270 _ => unreachable!(), 3271 }; 3272 3273 if needs_group { 3274 token::Paren::default().surround(tokens, do_print_expr); 3275 } else { 3276 do_print_expr(tokens); 3277 } 3278 } 3279 3280 #[cfg(feature = "full")] 3281 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3282 impl ToTokens for ExprArray { 3283 fn to_tokens(&self, tokens: &mut TokenStream) { 3284 outer_attrs_to_tokens(&self.attrs, tokens); 3285 self.bracket_token.surround(tokens, |tokens| { 3286 self.elems.to_tokens(tokens); 3287 }); 3288 } 3289 } 3290 3291 #[cfg(feature = "full")] 3292 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3293 impl ToTokens for ExprAssign { 3294 fn to_tokens(&self, tokens: &mut TokenStream) { 3295 print_expr_assign(self, tokens, FixupContext::NONE); 3296 } 3297 } 3298 3299 #[cfg(feature = "full")] 3300 fn print_expr_assign(e: &ExprAssign, tokens: &mut TokenStream, mut fixup: FixupContext) { 3301 outer_attrs_to_tokens(&e.attrs, tokens); 3302 3303 let needs_group = !e.attrs.is_empty(); 3304 if needs_group { 3305 fixup = FixupContext::NONE; 3306 } 3307 3308 let do_print_expr = |tokens: &mut TokenStream| { 3309 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator( 3310 &e.left, 3311 false, 3312 false, 3313 Precedence::Assign, 3314 ); 3315 print_subexpression(&e.left, left_prec <= Precedence::Range, tokens, left_fixup); 3316 e.eq_token.to_tokens(tokens); 3317 print_expr( 3318 &e.right, 3319 tokens, 3320 fixup.rightmost_subexpression_fixup(false, false, Precedence::Assign), 3321 ); 3322 }; 3323 3324 if needs_group { 3325 token::Paren::default().surround(tokens, do_print_expr); 3326 } else { 3327 do_print_expr(tokens); 3328 } 3329 } 3330 3331 #[cfg(feature = "full")] 3332 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3333 impl ToTokens for ExprAsync { 3334 fn to_tokens(&self, tokens: &mut TokenStream) { 3335 outer_attrs_to_tokens(&self.attrs, tokens); 3336 self.async_token.to_tokens(tokens); 3337 self.capture.to_tokens(tokens); 3338 self.block.to_tokens(tokens); 3339 } 3340 } 3341 3342 #[cfg(feature = "full")] 3343 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3344 impl ToTokens for ExprAwait { 3345 fn to_tokens(&self, tokens: &mut TokenStream) { 3346 print_expr_await(self, tokens, FixupContext::NONE); 3347 } 3348 } 3349 3350 #[cfg(feature = "full")] 3351 fn print_expr_await(e: &ExprAwait, tokens: &mut TokenStream, fixup: FixupContext) { 3352 outer_attrs_to_tokens(&e.attrs, tokens); 3353 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.base); 3354 print_subexpression( 3355 &e.base, 3356 left_prec < Precedence::Unambiguous, 3357 tokens, 3358 left_fixup, 3359 ); 3360 e.dot_token.to_tokens(tokens); 3361 e.await_token.to_tokens(tokens); 3362 } 3363 3364 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3365 impl ToTokens for ExprBinary { 3366 fn to_tokens(&self, tokens: &mut TokenStream) { 3367 print_expr_binary(self, tokens, FixupContext::NONE); 3368 } 3369 } 3370 3371 fn print_expr_binary(e: &ExprBinary, tokens: &mut TokenStream, mut fixup: FixupContext) { 3372 outer_attrs_to_tokens(&e.attrs, tokens); 3373 3374 let needs_group = !e.attrs.is_empty(); 3375 if needs_group { 3376 fixup = FixupContext::NONE; 3377 } 3378 3379 let do_print_expr = |tokens: &mut TokenStream| { 3380 let binop_prec = Precedence::of_binop(&e.op); 3381 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator( 3382 &e.left, 3383 #[cfg(feature = "full")] 3384 match &e.op { 3385 BinOp::Sub(_) 3386 | BinOp::Mul(_) 3387 | BinOp::And(_) 3388 | BinOp::Or(_) 3389 | BinOp::BitAnd(_) 3390 | BinOp::BitOr(_) 3391 | BinOp::Shl(_) 3392 | BinOp::Lt(_) => true, 3393 _ => false, 3394 }, 3395 match &e.op { 3396 BinOp::Shl(_) | BinOp::Lt(_) => true, 3397 _ => false, 3398 }, 3399 #[cfg(feature = "full")] 3400 binop_prec, 3401 ); 3402 let left_needs_group = match binop_prec { 3403 Precedence::Assign => left_prec <= Precedence::Range, 3404 Precedence::Compare => left_prec <= binop_prec, 3405 _ => left_prec < binop_prec, 3406 }; 3407 3408 let right_fixup = fixup.rightmost_subexpression_fixup( 3409 #[cfg(feature = "full")] 3410 false, 3411 #[cfg(feature = "full")] 3412 false, 3413 #[cfg(feature = "full")] 3414 binop_prec, 3415 ); 3416 let right_needs_group = binop_prec != Precedence::Assign 3417 && right_fixup.rightmost_subexpression_precedence(&e.right) <= binop_prec; 3418 3419 print_subexpression(&e.left, left_needs_group, tokens, left_fixup); 3420 e.op.to_tokens(tokens); 3421 print_subexpression(&e.right, right_needs_group, tokens, right_fixup); 3422 }; 3423 3424 if needs_group { 3425 token::Paren::default().surround(tokens, do_print_expr); 3426 } else { 3427 do_print_expr(tokens); 3428 } 3429 } 3430 3431 #[cfg(feature = "full")] 3432 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3433 impl ToTokens for ExprBlock { 3434 fn to_tokens(&self, tokens: &mut TokenStream) { 3435 outer_attrs_to_tokens(&self.attrs, tokens); 3436 self.label.to_tokens(tokens); 3437 self.block.brace_token.surround(tokens, |tokens| { 3438 inner_attrs_to_tokens(&self.attrs, tokens); 3439 tokens.append_all(&self.block.stmts); 3440 }); 3441 } 3442 } 3443 3444 #[cfg(feature = "full")] 3445 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3446 impl ToTokens for ExprBreak { 3447 fn to_tokens(&self, tokens: &mut TokenStream) { 3448 print_expr_break(self, tokens, FixupContext::NONE); 3449 } 3450 } 3451 3452 #[cfg(feature = "full")] 3453 fn print_expr_break(e: &ExprBreak, tokens: &mut TokenStream, fixup: FixupContext) { 3454 outer_attrs_to_tokens(&e.attrs, tokens); 3455 e.break_token.to_tokens(tokens); 3456 e.label.to_tokens(tokens); 3457 if let Some(value) = &e.expr { 3458 print_subexpression( 3459 value, 3460 // Parenthesize `break 'inner: loop { break 'inner 1 } + 1` 3461 // ^---------------------------------^ 3462 e.label.is_none() && classify::expr_leading_label(value), 3463 tokens, 3464 fixup.rightmost_subexpression_fixup(true, true, Precedence::Jump), 3465 ); 3466 } 3467 } 3468 3469 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3470 impl ToTokens for ExprCall { 3471 fn to_tokens(&self, tokens: &mut TokenStream) { 3472 print_expr_call(self, tokens, FixupContext::NONE); 3473 } 3474 } 3475 3476 fn print_expr_call(e: &ExprCall, tokens: &mut TokenStream, fixup: FixupContext) { 3477 outer_attrs_to_tokens(&e.attrs, tokens); 3478 3479 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator( 3480 &e.func, 3481 #[cfg(feature = "full")] 3482 true, 3483 false, 3484 #[cfg(feature = "full")] 3485 Precedence::Unambiguous, 3486 ); 3487 let needs_group = if let Expr::Field(func) = &*e.func { 3488 func.member.is_named() 3489 } else { 3490 left_prec < Precedence::Unambiguous 3491 }; 3492 print_subexpression(&e.func, needs_group, tokens, left_fixup); 3493 3494 e.paren_token.surround(tokens, |tokens| { 3495 e.args.to_tokens(tokens); 3496 }); 3497 } 3498 3499 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3500 impl ToTokens for ExprCast { 3501 fn to_tokens(&self, tokens: &mut TokenStream) { 3502 print_expr_cast(self, tokens, FixupContext::NONE); 3503 } 3504 } 3505 3506 fn print_expr_cast(e: &ExprCast, tokens: &mut TokenStream, mut fixup: FixupContext) { 3507 outer_attrs_to_tokens(&e.attrs, tokens); 3508 3509 let needs_group = !e.attrs.is_empty(); 3510 if needs_group { 3511 fixup = FixupContext::NONE; 3512 } 3513 3514 let do_print_expr = |tokens: &mut TokenStream| { 3515 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator( 3516 &e.expr, 3517 #[cfg(feature = "full")] 3518 false, 3519 false, 3520 #[cfg(feature = "full")] 3521 Precedence::Cast, 3522 ); 3523 print_subexpression(&e.expr, left_prec < Precedence::Cast, tokens, left_fixup); 3524 e.as_token.to_tokens(tokens); 3525 e.ty.to_tokens(tokens); 3526 }; 3527 3528 if needs_group { 3529 token::Paren::default().surround(tokens, do_print_expr); 3530 } else { 3531 do_print_expr(tokens); 3532 } 3533 } 3534 3535 #[cfg(feature = "full")] 3536 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3537 impl ToTokens for ExprClosure { 3538 fn to_tokens(&self, tokens: &mut TokenStream) { 3539 print_expr_closure(self, tokens, FixupContext::NONE); 3540 } 3541 } 3542 3543 #[cfg(feature = "full")] 3544 fn print_expr_closure(e: &ExprClosure, tokens: &mut TokenStream, fixup: FixupContext) { 3545 outer_attrs_to_tokens(&e.attrs, tokens); 3546 e.lifetimes.to_tokens(tokens); 3547 e.constness.to_tokens(tokens); 3548 e.movability.to_tokens(tokens); 3549 e.asyncness.to_tokens(tokens); 3550 e.capture.to_tokens(tokens); 3551 e.or1_token.to_tokens(tokens); 3552 e.inputs.to_tokens(tokens); 3553 e.or2_token.to_tokens(tokens); 3554 e.output.to_tokens(tokens); 3555 if matches!(e.output, ReturnType::Default) 3556 || matches!(&*e.body, Expr::Block(body) if body.attrs.is_empty() && body.label.is_none()) 3557 { 3558 print_expr( 3559 &e.body, 3560 tokens, 3561 fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump), 3562 ); 3563 } else { 3564 token::Brace::default().surround(tokens, |tokens| { 3565 print_expr(&e.body, tokens, FixupContext::new_stmt()); 3566 }); 3567 } 3568 } 3569 3570 #[cfg(feature = "full")] 3571 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3572 impl ToTokens for ExprConst { 3573 fn to_tokens(&self, tokens: &mut TokenStream) { 3574 outer_attrs_to_tokens(&self.attrs, tokens); 3575 self.const_token.to_tokens(tokens); 3576 self.block.brace_token.surround(tokens, |tokens| { 3577 inner_attrs_to_tokens(&self.attrs, tokens); 3578 tokens.append_all(&self.block.stmts); 3579 }); 3580 } 3581 } 3582 3583 #[cfg(feature = "full")] 3584 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3585 impl ToTokens for ExprContinue { 3586 fn to_tokens(&self, tokens: &mut TokenStream) { 3587 outer_attrs_to_tokens(&self.attrs, tokens); 3588 self.continue_token.to_tokens(tokens); 3589 self.label.to_tokens(tokens); 3590 } 3591 } 3592 3593 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3594 impl ToTokens for ExprField { 3595 fn to_tokens(&self, tokens: &mut TokenStream) { 3596 print_expr_field(self, tokens, FixupContext::NONE); 3597 } 3598 } 3599 3600 fn print_expr_field(e: &ExprField, tokens: &mut TokenStream, fixup: FixupContext) { 3601 outer_attrs_to_tokens(&e.attrs, tokens); 3602 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.base); 3603 print_subexpression( 3604 &e.base, 3605 left_prec < Precedence::Unambiguous, 3606 tokens, 3607 left_fixup, 3608 ); 3609 e.dot_token.to_tokens(tokens); 3610 e.member.to_tokens(tokens); 3611 } 3612 3613 #[cfg(feature = "full")] 3614 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3615 impl ToTokens for ExprForLoop { 3616 fn to_tokens(&self, tokens: &mut TokenStream) { 3617 outer_attrs_to_tokens(&self.attrs, tokens); 3618 self.label.to_tokens(tokens); 3619 self.for_token.to_tokens(tokens); 3620 self.pat.to_tokens(tokens); 3621 self.in_token.to_tokens(tokens); 3622 print_expr(&self.expr, tokens, FixupContext::new_condition()); 3623 self.body.brace_token.surround(tokens, |tokens| { 3624 inner_attrs_to_tokens(&self.attrs, tokens); 3625 tokens.append_all(&self.body.stmts); 3626 }); 3627 } 3628 } 3629 3630 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3631 impl ToTokens for ExprGroup { 3632 fn to_tokens(&self, tokens: &mut TokenStream) { 3633 outer_attrs_to_tokens(&self.attrs, tokens); 3634 self.group_token.surround(tokens, |tokens| { 3635 self.expr.to_tokens(tokens); 3636 }); 3637 } 3638 } 3639 3640 #[cfg(feature = "full")] 3641 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3642 impl ToTokens for ExprIf { 3643 fn to_tokens(&self, tokens: &mut TokenStream) { 3644 outer_attrs_to_tokens(&self.attrs, tokens); 3645 3646 let mut expr = self; 3647 loop { 3648 expr.if_token.to_tokens(tokens); 3649 print_expr(&expr.cond, tokens, FixupContext::new_condition()); 3650 expr.then_branch.to_tokens(tokens); 3651 3652 let (else_token, else_) = match &expr.else_branch { 3653 Some(else_branch) => else_branch, 3654 None => break, 3655 }; 3656 3657 else_token.to_tokens(tokens); 3658 match &**else_ { 3659 Expr::If(next) => { 3660 expr = next; 3661 } 3662 Expr::Block(last) => { 3663 last.to_tokens(tokens); 3664 break; 3665 } 3666 // If this is not one of the valid expressions to exist in 3667 // an else clause, wrap it in a block. 3668 other => { 3669 token::Brace::default().surround(tokens, |tokens| { 3670 print_expr(other, tokens, FixupContext::new_stmt()); 3671 }); 3672 break; 3673 } 3674 } 3675 } 3676 } 3677 } 3678 3679 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3680 impl ToTokens for ExprIndex { 3681 fn to_tokens(&self, tokens: &mut TokenStream) { 3682 print_expr_index(self, tokens, FixupContext::NONE); 3683 } 3684 } 3685 3686 fn print_expr_index(e: &ExprIndex, tokens: &mut TokenStream, fixup: FixupContext) { 3687 outer_attrs_to_tokens(&e.attrs, tokens); 3688 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator( 3689 &e.expr, 3690 #[cfg(feature = "full")] 3691 true, 3692 false, 3693 #[cfg(feature = "full")] 3694 Precedence::Unambiguous, 3695 ); 3696 print_subexpression( 3697 &e.expr, 3698 left_prec < Precedence::Unambiguous, 3699 tokens, 3700 left_fixup, 3701 ); 3702 e.bracket_token.surround(tokens, |tokens| { 3703 e.index.to_tokens(tokens); 3704 }); 3705 } 3706 3707 #[cfg(feature = "full")] 3708 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3709 impl ToTokens for ExprInfer { 3710 fn to_tokens(&self, tokens: &mut TokenStream) { 3711 outer_attrs_to_tokens(&self.attrs, tokens); 3712 self.underscore_token.to_tokens(tokens); 3713 } 3714 } 3715 3716 #[cfg(feature = "full")] 3717 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3718 impl ToTokens for ExprLet { 3719 fn to_tokens(&self, tokens: &mut TokenStream) { 3720 print_expr_let(self, tokens, FixupContext::NONE); 3721 } 3722 } 3723 3724 #[cfg(feature = "full")] 3725 fn print_expr_let(e: &ExprLet, tokens: &mut TokenStream, fixup: FixupContext) { 3726 outer_attrs_to_tokens(&e.attrs, tokens); 3727 e.let_token.to_tokens(tokens); 3728 e.pat.to_tokens(tokens); 3729 e.eq_token.to_tokens(tokens); 3730 let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Let); 3731 print_subexpression(&e.expr, right_prec < Precedence::Let, tokens, right_fixup); 3732 } 3733 3734 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3735 impl ToTokens for ExprLit { 3736 fn to_tokens(&self, tokens: &mut TokenStream) { 3737 outer_attrs_to_tokens(&self.attrs, tokens); 3738 self.lit.to_tokens(tokens); 3739 } 3740 } 3741 3742 #[cfg(feature = "full")] 3743 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3744 impl ToTokens for ExprLoop { 3745 fn to_tokens(&self, tokens: &mut TokenStream) { 3746 outer_attrs_to_tokens(&self.attrs, tokens); 3747 self.label.to_tokens(tokens); 3748 self.loop_token.to_tokens(tokens); 3749 self.body.brace_token.surround(tokens, |tokens| { 3750 inner_attrs_to_tokens(&self.attrs, tokens); 3751 tokens.append_all(&self.body.stmts); 3752 }); 3753 } 3754 } 3755 3756 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3757 impl ToTokens for ExprMacro { 3758 fn to_tokens(&self, tokens: &mut TokenStream) { 3759 outer_attrs_to_tokens(&self.attrs, tokens); 3760 self.mac.to_tokens(tokens); 3761 } 3762 } 3763 3764 #[cfg(feature = "full")] 3765 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3766 impl ToTokens for ExprMatch { 3767 fn to_tokens(&self, tokens: &mut TokenStream) { 3768 outer_attrs_to_tokens(&self.attrs, tokens); 3769 self.match_token.to_tokens(tokens); 3770 print_expr(&self.expr, tokens, FixupContext::new_condition()); 3771 self.brace_token.surround(tokens, |tokens| { 3772 inner_attrs_to_tokens(&self.attrs, tokens); 3773 for (i, arm) in self.arms.iter().enumerate() { 3774 arm.to_tokens(tokens); 3775 // Ensure that we have a comma after a non-block arm, except 3776 // for the last one. 3777 let is_last = i == self.arms.len() - 1; 3778 if !is_last 3779 && classify::requires_comma_to_be_match_arm(&arm.body) 3780 && arm.comma.is_none() 3781 { 3782 <Token![,]>::default().to_tokens(tokens); 3783 } 3784 } 3785 }); 3786 } 3787 } 3788 3789 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3790 impl ToTokens for ExprMethodCall { 3791 fn to_tokens(&self, tokens: &mut TokenStream) { 3792 print_expr_method_call(self, tokens, FixupContext::NONE); 3793 } 3794 } 3795 3796 fn print_expr_method_call(e: &ExprMethodCall, tokens: &mut TokenStream, fixup: FixupContext) { 3797 outer_attrs_to_tokens(&e.attrs, tokens); 3798 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.receiver); 3799 print_subexpression( 3800 &e.receiver, 3801 left_prec < Precedence::Unambiguous, 3802 tokens, 3803 left_fixup, 3804 ); 3805 e.dot_token.to_tokens(tokens); 3806 e.method.to_tokens(tokens); 3807 if let Some(turbofish) = &e.turbofish { 3808 path::printing::print_angle_bracketed_generic_arguments( 3809 tokens, 3810 turbofish, 3811 PathStyle::Expr, 3812 ); 3813 } 3814 e.paren_token.surround(tokens, |tokens| { 3815 e.args.to_tokens(tokens); 3816 }); 3817 } 3818 3819 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3820 impl ToTokens for ExprParen { 3821 fn to_tokens(&self, tokens: &mut TokenStream) { 3822 outer_attrs_to_tokens(&self.attrs, tokens); 3823 self.paren_token.surround(tokens, |tokens| { 3824 self.expr.to_tokens(tokens); 3825 }); 3826 } 3827 } 3828 3829 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3830 impl ToTokens for ExprPath { 3831 fn to_tokens(&self, tokens: &mut TokenStream) { 3832 outer_attrs_to_tokens(&self.attrs, tokens); 3833 path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr); 3834 } 3835 } 3836 3837 #[cfg(feature = "full")] 3838 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3839 impl ToTokens for ExprRange { 3840 fn to_tokens(&self, tokens: &mut TokenStream) { 3841 print_expr_range(self, tokens, FixupContext::NONE); 3842 } 3843 } 3844 3845 #[cfg(feature = "full")] 3846 fn print_expr_range(e: &ExprRange, tokens: &mut TokenStream, mut fixup: FixupContext) { 3847 outer_attrs_to_tokens(&e.attrs, tokens); 3848 3849 let needs_group = !e.attrs.is_empty(); 3850 if needs_group { 3851 fixup = FixupContext::NONE; 3852 } 3853 3854 let do_print_expr = |tokens: &mut TokenStream| { 3855 if let Some(start) = &e.start { 3856 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator( 3857 start, 3858 true, 3859 false, 3860 Precedence::Range, 3861 ); 3862 print_subexpression(start, left_prec <= Precedence::Range, tokens, left_fixup); 3863 } 3864 e.limits.to_tokens(tokens); 3865 if let Some(end) = &e.end { 3866 let right_fixup = 3867 fixup.rightmost_subexpression_fixup(false, true, Precedence::Range); 3868 let right_prec = right_fixup.rightmost_subexpression_precedence(end); 3869 print_subexpression(end, right_prec <= Precedence::Range, tokens, right_fixup); 3870 } 3871 }; 3872 3873 if needs_group { 3874 token::Paren::default().surround(tokens, do_print_expr); 3875 } else { 3876 do_print_expr(tokens); 3877 } 3878 } 3879 3880 #[cfg(feature = "full")] 3881 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3882 impl ToTokens for ExprRawAddr { 3883 fn to_tokens(&self, tokens: &mut TokenStream) { 3884 print_expr_raw_addr(self, tokens, FixupContext::NONE); 3885 } 3886 } 3887 3888 #[cfg(feature = "full")] 3889 fn print_expr_raw_addr(e: &ExprRawAddr, tokens: &mut TokenStream, fixup: FixupContext) { 3890 outer_attrs_to_tokens(&e.attrs, tokens); 3891 e.and_token.to_tokens(tokens); 3892 e.raw.to_tokens(tokens); 3893 e.mutability.to_tokens(tokens); 3894 let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Prefix); 3895 print_subexpression( 3896 &e.expr, 3897 right_prec < Precedence::Prefix, 3898 tokens, 3899 right_fixup, 3900 ); 3901 } 3902 3903 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3904 impl ToTokens for ExprReference { 3905 fn to_tokens(&self, tokens: &mut TokenStream) { 3906 print_expr_reference(self, tokens, FixupContext::NONE); 3907 } 3908 } 3909 3910 fn print_expr_reference(e: &ExprReference, tokens: &mut TokenStream, fixup: FixupContext) { 3911 outer_attrs_to_tokens(&e.attrs, tokens); 3912 e.and_token.to_tokens(tokens); 3913 e.mutability.to_tokens(tokens); 3914 let (right_prec, right_fixup) = fixup.rightmost_subexpression( 3915 &e.expr, 3916 #[cfg(feature = "full")] 3917 Precedence::Prefix, 3918 ); 3919 print_subexpression( 3920 &e.expr, 3921 right_prec < Precedence::Prefix, 3922 tokens, 3923 right_fixup, 3924 ); 3925 } 3926 3927 #[cfg(feature = "full")] 3928 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3929 impl ToTokens for ExprRepeat { 3930 fn to_tokens(&self, tokens: &mut TokenStream) { 3931 outer_attrs_to_tokens(&self.attrs, tokens); 3932 self.bracket_token.surround(tokens, |tokens| { 3933 self.expr.to_tokens(tokens); 3934 self.semi_token.to_tokens(tokens); 3935 self.len.to_tokens(tokens); 3936 }); 3937 } 3938 } 3939 3940 #[cfg(feature = "full")] 3941 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3942 impl ToTokens for ExprReturn { 3943 fn to_tokens(&self, tokens: &mut TokenStream) { 3944 print_expr_return(self, tokens, FixupContext::NONE); 3945 } 3946 } 3947 3948 #[cfg(feature = "full")] 3949 fn print_expr_return(e: &ExprReturn, tokens: &mut TokenStream, fixup: FixupContext) { 3950 outer_attrs_to_tokens(&e.attrs, tokens); 3951 e.return_token.to_tokens(tokens); 3952 if let Some(expr) = &e.expr { 3953 print_expr( 3954 expr, 3955 tokens, 3956 fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump), 3957 ); 3958 } 3959 } 3960 3961 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3962 impl ToTokens for ExprStruct { 3963 fn to_tokens(&self, tokens: &mut TokenStream) { 3964 outer_attrs_to_tokens(&self.attrs, tokens); 3965 path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr); 3966 self.brace_token.surround(tokens, |tokens| { 3967 self.fields.to_tokens(tokens); 3968 if let Some(dot2_token) = &self.dot2_token { 3969 dot2_token.to_tokens(tokens); 3970 } else if self.rest.is_some() { 3971 Token).to_tokens(tokens); 3972 } 3973 self.rest.to_tokens(tokens); 3974 }); 3975 } 3976 } 3977 3978 #[cfg(feature = "full")] 3979 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 3980 impl ToTokens for ExprTry { 3981 fn to_tokens(&self, tokens: &mut TokenStream) { 3982 print_expr_try(self, tokens, FixupContext::NONE); 3983 } 3984 } 3985 3986 #[cfg(feature = "full")] 3987 fn print_expr_try(e: &ExprTry, tokens: &mut TokenStream, fixup: FixupContext) { 3988 outer_attrs_to_tokens(&e.attrs, tokens); 3989 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.expr); 3990 print_subexpression( 3991 &e.expr, 3992 left_prec < Precedence::Unambiguous, 3993 tokens, 3994 left_fixup, 3995 ); 3996 e.question_token.to_tokens(tokens); 3997 } 3998 3999 #[cfg(feature = "full")] 4000 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 4001 impl ToTokens for ExprTryBlock { 4002 fn to_tokens(&self, tokens: &mut TokenStream) { 4003 outer_attrs_to_tokens(&self.attrs, tokens); 4004 self.try_token.to_tokens(tokens); 4005 self.block.to_tokens(tokens); 4006 } 4007 } 4008 4009 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 4010 impl ToTokens for ExprTuple { 4011 fn to_tokens(&self, tokens: &mut TokenStream) { 4012 outer_attrs_to_tokens(&self.attrs, tokens); 4013 self.paren_token.surround(tokens, |tokens| { 4014 self.elems.to_tokens(tokens); 4015 // If we only have one argument, we need a trailing comma to 4016 // distinguish ExprTuple from ExprParen. 4017 if self.elems.len() == 1 && !self.elems.trailing_punct() { 4018 <Token![,]>::default().to_tokens(tokens); 4019 } 4020 }); 4021 } 4022 } 4023 4024 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 4025 impl ToTokens for ExprUnary { 4026 fn to_tokens(&self, tokens: &mut TokenStream) { 4027 print_expr_unary(self, tokens, FixupContext::NONE); 4028 } 4029 } 4030 4031 fn print_expr_unary(e: &ExprUnary, tokens: &mut TokenStream, fixup: FixupContext) { 4032 outer_attrs_to_tokens(&e.attrs, tokens); 4033 e.op.to_tokens(tokens); 4034 let (right_prec, right_fixup) = fixup.rightmost_subexpression( 4035 &e.expr, 4036 #[cfg(feature = "full")] 4037 Precedence::Prefix, 4038 ); 4039 print_subexpression( 4040 &e.expr, 4041 right_prec < Precedence::Prefix, 4042 tokens, 4043 right_fixup, 4044 ); 4045 } 4046 4047 #[cfg(feature = "full")] 4048 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 4049 impl ToTokens for ExprUnsafe { 4050 fn to_tokens(&self, tokens: &mut TokenStream) { 4051 outer_attrs_to_tokens(&self.attrs, tokens); 4052 self.unsafe_token.to_tokens(tokens); 4053 self.block.brace_token.surround(tokens, |tokens| { 4054 inner_attrs_to_tokens(&self.attrs, tokens); 4055 tokens.append_all(&self.block.stmts); 4056 }); 4057 } 4058 } 4059 4060 #[cfg(feature = "full")] 4061 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 4062 impl ToTokens for ExprWhile { 4063 fn to_tokens(&self, tokens: &mut TokenStream) { 4064 outer_attrs_to_tokens(&self.attrs, tokens); 4065 self.label.to_tokens(tokens); 4066 self.while_token.to_tokens(tokens); 4067 print_expr(&self.cond, tokens, FixupContext::new_condition()); 4068 self.body.brace_token.surround(tokens, |tokens| { 4069 inner_attrs_to_tokens(&self.attrs, tokens); 4070 tokens.append_all(&self.body.stmts); 4071 }); 4072 } 4073 } 4074 4075 #[cfg(feature = "full")] 4076 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 4077 impl ToTokens for ExprYield { 4078 fn to_tokens(&self, tokens: &mut TokenStream) { 4079 print_expr_yield(self, tokens, FixupContext::NONE); 4080 } 4081 } 4082 4083 #[cfg(feature = "full")] 4084 fn print_expr_yield(e: &ExprYield, tokens: &mut TokenStream, fixup: FixupContext) { 4085 outer_attrs_to_tokens(&e.attrs, tokens); 4086 e.yield_token.to_tokens(tokens); 4087 if let Some(expr) = &e.expr { 4088 print_expr( 4089 expr, 4090 tokens, 4091 fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump), 4092 ); 4093 } 4094 } 4095 4096 #[cfg(feature = "full")] 4097 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 4098 impl ToTokens for Arm { 4099 fn to_tokens(&self, tokens: &mut TokenStream) { 4100 tokens.append_all(&self.attrs); 4101 self.pat.to_tokens(tokens); 4102 if let Some((if_token, guard)) = &self.guard { 4103 if_token.to_tokens(tokens); 4104 guard.to_tokens(tokens); 4105 } 4106 self.fat_arrow_token.to_tokens(tokens); 4107 print_expr(&self.body, tokens, FixupContext::new_match_arm()); 4108 self.comma.to_tokens(tokens); 4109 } 4110 } 4111 4112 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 4113 impl ToTokens for FieldValue { 4114 fn to_tokens(&self, tokens: &mut TokenStream) { 4115 outer_attrs_to_tokens(&self.attrs, tokens); 4116 self.member.to_tokens(tokens); 4117 if let Some(colon_token) = &self.colon_token { 4118 colon_token.to_tokens(tokens); 4119 self.expr.to_tokens(tokens); 4120 } 4121 } 4122 } 4123 4124 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 4125 impl ToTokens for Index { 4126 fn to_tokens(&self, tokens: &mut TokenStream) { 4127 let mut lit = Literal::i64_unsuffixed(i64::from(self.index)); 4128 lit.set_span(self.span); 4129 tokens.append(lit); 4130 } 4131 } 4132 4133 #[cfg(feature = "full")] 4134 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 4135 impl ToTokens for Label { 4136 fn to_tokens(&self, tokens: &mut TokenStream) { 4137 self.name.to_tokens(tokens); 4138 self.colon_token.to_tokens(tokens); 4139 } 4140 } 4141 4142 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 4143 impl ToTokens for Member { 4144 fn to_tokens(&self, tokens: &mut TokenStream) { 4145 match self { 4146 Member::Named(ident) => ident.to_tokens(tokens), 4147 Member::Unnamed(index) => index.to_tokens(tokens), 4148 } 4149 } 4150 } 4151 4152 #[cfg(feature = "full")] 4153 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 4154 impl ToTokens for RangeLimits { 4155 fn to_tokens(&self, tokens: &mut TokenStream) { 4156 match self { 4157 RangeLimits::HalfOpen(t) => t.to_tokens(tokens), 4158 RangeLimits::Closed(t) => t.to_tokens(tokens), 4159 } 4160 } 4161 } 4162 4163 #[cfg(feature = "full")] 4164 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 4165 impl ToTokens for PointerMutability { 4166 fn to_tokens(&self, tokens: &mut TokenStream) { 4167 match self { 4168 PointerMutability::Const(const_token) => const_token.to_tokens(tokens), 4169 PointerMutability::Mut(mut_token) => mut_token.to_tokens(tokens), 4170 } 4171 } 4172 } 4173 } 4174