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