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