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