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