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