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