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