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