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