blob: b7695d7966bb6b04083af798720d9754743ab0f8 [file] [log] [blame]
David Tolnay55535012018-01-05 16:39:23 -08001// 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
David Tolnayf4bbbd92016-09-23 14:41:55 -07009use super::*;
David Tolnaye303b7c2018-05-20 16:46:35 -070010use proc_macro2::{Span, TokenStream};
David Tolnay94d2b792018-04-29 12:26:10 -070011use punctuated::Punctuated;
David Tolnay14982012017-12-29 00:49:51 -050012#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -050013use std::hash::{Hash, Hasher};
David Tolnay2ae520a2017-12-29 11:19:50 -050014#[cfg(feature = "full")]
15use std::mem;
David Tolnay94d2b792018-04-29 12:26:10 -070016#[cfg(feature = "extra-traits")]
17use tt::TokenStreamHelper;
David Tolnayf4bbbd92016-09-23 14:41:55 -070018
Alex Crichton62a0a592017-05-22 13:58:53 -070019ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -080020 /// A Rust expression.
David Tolnay614a0142018-01-07 10:25:43 -080021 ///
David Tolnay461d98e2018-01-07 11:07:19 -080022 /// *This type is available if Syn is built with the `"derive"` or `"full"`
23 /// feature.*
24 ///
David Tolnay614a0142018-01-07 10:25:43 -080025 /// # 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`.
David Tolnay8c91b882017-12-28 23:04:32 -0500106 pub enum Expr {
David Tolnaya454c8f2018-01-07 01:01:10 -0800107 /// A box expression: `box f`.
David Tolnay461d98e2018-01-07 11:07:19 -0800108 ///
109 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400110 pub Box(ExprBox #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500111 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800112 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500113 pub expr: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700114 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500115
David Tolnaya454c8f2018-01-07 01:01:10 -0800116 /// A placement expression: `place <- value`.
David Tolnay461d98e2018-01-07 11:07:19 -0800117 ///
118 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400119 pub InPlace(ExprInPlace #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500120 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700121 pub place: Box<Expr>,
David Tolnay8701a5c2017-12-28 23:31:10 -0500122 pub arrow_token: Token![<-],
Alex Crichton62a0a592017-05-22 13:58:53 -0700123 pub value: Box<Expr>,
124 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500125
David Tolnaya454c8f2018-01-07 01:01:10 -0800126 /// A slice literal expression: `[a, b, c, d]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800127 ///
128 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400129 pub Array(ExprArray #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500130 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500131 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500132 pub elems: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700133 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500134
David Tolnaya454c8f2018-01-07 01:01:10 -0800135 /// A function call expression: `invoke(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800136 ///
137 /// *This type is available if Syn is built with the `"derive"` or
138 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700139 pub Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -0500140 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700141 pub func: Box<Expr>,
David Tolnay32954ef2017-12-26 22:43:16 -0500142 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500143 pub args: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700144 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500145
David Tolnaya454c8f2018-01-07 01:01:10 -0800146 /// A method call expression: `x.foo::<T>(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800147 ///
148 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400149 pub MethodCall(ExprMethodCall #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500150 pub attrs: Vec<Attribute>,
David Tolnay76418512017-12-28 23:47:47 -0500151 pub receiver: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800152 pub dot_token: Token![.],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500153 pub method: Ident,
David Tolnayd60cfec2017-12-29 00:21:38 -0500154 pub turbofish: Option<MethodTurbofish>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500155 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500156 pub args: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700157 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500158
David Tolnaya454c8f2018-01-07 01:01:10 -0800159 /// A tuple expression: `(a, b, c, d)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800160 ///
161 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay05362582017-12-26 01:33:57 -0500162 pub Tuple(ExprTuple #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500163 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500164 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500165 pub elems: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700166 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500167
David Tolnaya454c8f2018-01-07 01:01:10 -0800168 /// A binary operation: `a + b`, `a * b`.
David Tolnay461d98e2018-01-07 11:07:19 -0800169 ///
170 /// *This type is available if Syn is built with the `"derive"` or
171 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700172 pub Binary(ExprBinary {
David Tolnay8c91b882017-12-28 23:04:32 -0500173 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700174 pub left: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500175 pub op: BinOp,
Alex Crichton62a0a592017-05-22 13:58:53 -0700176 pub right: Box<Expr>,
177 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500178
David Tolnaya454c8f2018-01-07 01:01:10 -0800179 /// A unary operation: `!x`, `*x`.
David Tolnay461d98e2018-01-07 11:07:19 -0800180 ///
181 /// *This type is available if Syn is built with the `"derive"` or
182 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700183 pub Unary(ExprUnary {
David Tolnay8c91b882017-12-28 23:04:32 -0500184 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700185 pub op: UnOp,
186 pub expr: Box<Expr>,
187 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500188
David Tolnaya454c8f2018-01-07 01:01:10 -0800189 /// A literal in place of an expression: `1`, `"foo"`.
David Tolnay461d98e2018-01-07 11:07:19 -0800190 ///
191 /// *This type is available if Syn is built with the `"derive"` or
192 /// `"full"` feature.*
David Tolnay8c91b882017-12-28 23:04:32 -0500193 pub Lit(ExprLit {
194 pub attrs: Vec<Attribute>,
195 pub lit: Lit,
196 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500197
David Tolnaya454c8f2018-01-07 01:01:10 -0800198 /// A cast expression: `foo as f64`.
David Tolnay461d98e2018-01-07 11:07:19 -0800199 ///
200 /// *This type is available if Syn is built with the `"derive"` or
201 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700202 pub Cast(ExprCast {
David Tolnay8c91b882017-12-28 23:04:32 -0500203 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700204 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800205 pub as_token: Token![as],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800206 pub ty: Box<Type>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700207 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500208
David Tolnaya454c8f2018-01-07 01:01:10 -0800209 /// A type ascription expression: `foo: f64`.
David Tolnay461d98e2018-01-07 11:07:19 -0800210 ///
211 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay0cf94f22017-12-28 23:46:26 -0500212 pub Type(ExprType #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500213 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700214 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800215 pub colon_token: Token![:],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800216 pub ty: Box<Type>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700217 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500218
David Tolnaya454c8f2018-01-07 01:01:10 -0800219 /// An `if` expression with an optional `else` block: `if expr { ... }
220 /// else { ... }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700221 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800222 /// The `else` branch expression may only be an `If`, `IfLet`, or
223 /// `Block` expression, not any of the other types of expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800224 ///
225 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400226 pub If(ExprIf #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500227 pub attrs: Vec<Attribute>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500228 pub if_token: Token![if],
Alex Crichton62a0a592017-05-22 13:58:53 -0700229 pub cond: Box<Expr>,
David Tolnay2ccf32a2017-12-29 00:34:26 -0500230 pub then_branch: Block,
231 pub else_branch: Option<(Token![else], Box<Expr>)>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700232 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500233
David Tolnaya454c8f2018-01-07 01:01:10 -0800234 /// An `if let` expression with an optional `else` block: `if let pat =
235 /// expr { ... } else { ... }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700236 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800237 /// The `else` branch expression may only be an `If`, `IfLet`, or
238 /// `Block` expression, not any of the other types of expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800239 ///
240 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400241 pub IfLet(ExprIfLet #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500242 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800243 pub if_token: Token![if],
244 pub let_token: Token![let],
David Tolnay5b5b7d22018-03-31 21:05:00 +0200245 pub pats: Punctuated<Pat, Token![|]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800246 pub eq_token: Token![=],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500247 pub expr: Box<Expr>,
David Tolnay2ccf32a2017-12-29 00:34:26 -0500248 pub then_branch: Block,
249 pub else_branch: Option<(Token![else], Box<Expr>)>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700250 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500251
David Tolnaya454c8f2018-01-07 01:01:10 -0800252 /// A while loop: `while expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800253 ///
254 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400255 pub While(ExprWhile #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500256 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500257 pub label: Option<Label>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800258 pub while_token: Token![while],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500259 pub cond: Box<Expr>,
260 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700261 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500262
David Tolnaya454c8f2018-01-07 01:01:10 -0800263 /// A while-let loop: `while let pat = expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800264 ///
265 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400266 pub WhileLet(ExprWhileLet #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500267 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500268 pub label: Option<Label>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800269 pub while_token: Token![while],
270 pub let_token: Token![let],
David Tolnay5b5b7d22018-03-31 21:05:00 +0200271 pub pats: Punctuated<Pat, Token![|]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800272 pub eq_token: Token![=],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500273 pub expr: Box<Expr>,
274 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700275 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500276
David Tolnaya454c8f2018-01-07 01:01:10 -0800277 /// A for loop: `for pat in expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800278 ///
279 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400280 pub ForLoop(ExprForLoop #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500281 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500282 pub label: Option<Label>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500283 pub for_token: Token![for],
Alex Crichton62a0a592017-05-22 13:58:53 -0700284 pub pat: Box<Pat>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500285 pub in_token: Token![in],
Alex Crichton62a0a592017-05-22 13:58:53 -0700286 pub expr: Box<Expr>,
287 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700288 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500289
David Tolnaya454c8f2018-01-07 01:01:10 -0800290 /// Conditionless loop: `loop { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800291 ///
292 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400293 pub Loop(ExprLoop #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500294 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500295 pub label: Option<Label>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500296 pub loop_token: Token![loop],
297 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700298 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500299
David Tolnaya454c8f2018-01-07 01:01:10 -0800300 /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800301 ///
302 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400303 pub Match(ExprMatch #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500304 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800305 pub match_token: Token![match],
Alex Crichton62a0a592017-05-22 13:58:53 -0700306 pub expr: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500307 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700308 pub arms: Vec<Arm>,
309 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500310
David Tolnaya454c8f2018-01-07 01:01:10 -0800311 /// A closure expression: `|a, b| a + b`.
David Tolnay461d98e2018-01-07 11:07:19 -0800312 ///
313 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400314 pub Closure(ExprClosure #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500315 pub attrs: Vec<Attribute>,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +0900316 pub asyncness: Option<Token![async]>,
David Tolnay13d4c0e2018-03-31 20:53:59 +0200317 pub movability: Option<Token![static]>,
David Tolnayefc96fb2017-12-29 02:03:15 -0500318 pub capture: Option<Token![move]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800319 pub or1_token: Token![|],
David Tolnayf2cfd722017-12-31 18:02:51 -0500320 pub inputs: Punctuated<FnArg, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800321 pub or2_token: Token![|],
David Tolnay7f675742017-12-27 22:43:21 -0500322 pub output: ReturnType,
323 pub body: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700324 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500325
David Tolnaya454c8f2018-01-07 01:01:10 -0800326 /// An unsafe block: `unsafe { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800327 ///
328 /// *This type is available if Syn is built with the `"full"` feature.*
Nika Layzell640832a2017-12-04 13:37:09 -0500329 pub Unsafe(ExprUnsafe #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500330 pub attrs: Vec<Attribute>,
Nika Layzell640832a2017-12-04 13:37:09 -0500331 pub unsafe_token: Token![unsafe],
332 pub block: Block,
333 }),
334
David Tolnaya454c8f2018-01-07 01:01:10 -0800335 /// A blocked scope: `{ ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800336 ///
337 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400338 pub Block(ExprBlock #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500339 pub attrs: Vec<Attribute>,
David Tolnay1d8e9962018-08-24 19:04:20 -0400340 pub label: Option<Label>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700341 pub block: Block,
342 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700343
David Tolnaya454c8f2018-01-07 01:01:10 -0800344 /// An assignment expression: `a = compute()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800345 ///
346 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400347 pub Assign(ExprAssign #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500348 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700349 pub left: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800350 pub eq_token: Token![=],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500351 pub right: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700352 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500353
David Tolnaya454c8f2018-01-07 01:01:10 -0800354 /// A compound assignment expression: `counter += 1`.
David Tolnay461d98e2018-01-07 11:07:19 -0800355 ///
356 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400357 pub AssignOp(ExprAssignOp #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500358 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700359 pub left: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500360 pub op: BinOp,
Alex Crichton62a0a592017-05-22 13:58:53 -0700361 pub right: Box<Expr>,
362 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500363
David Tolnaya454c8f2018-01-07 01:01:10 -0800364 /// Access of a named struct field (`obj.k`) or unnamed tuple struct
David Tolnay85b69a42017-12-27 20:43:10 -0500365 /// field (`obj.0`).
David Tolnay461d98e2018-01-07 11:07:19 -0800366 ///
367 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd5147742018-06-30 10:09:52 -0700368 pub Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -0500369 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -0500370 pub base: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800371 pub dot_token: Token![.],
David Tolnay85b69a42017-12-27 20:43:10 -0500372 pub member: Member,
Alex Crichton62a0a592017-05-22 13:58:53 -0700373 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500374
David Tolnay05658502018-01-07 09:56:37 -0800375 /// A square bracketed indexing expression: `vector[2]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800376 ///
377 /// *This type is available if Syn is built with the `"derive"` or
378 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700379 pub Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -0500380 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700381 pub expr: Box<Expr>,
David Tolnay32954ef2017-12-26 22:43:16 -0500382 pub bracket_token: token::Bracket,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500383 pub index: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700384 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500385
David Tolnaya454c8f2018-01-07 01:01:10 -0800386 /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800387 ///
388 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400389 pub Range(ExprRange #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500390 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700391 pub from: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700392 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500393 pub to: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700394 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700395
David Tolnaya454c8f2018-01-07 01:01:10 -0800396 /// A path like `std::mem::replace` possibly containing generic
397 /// parameters and a qualified self-type.
Alex Crichton62a0a592017-05-22 13:58:53 -0700398 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800399 /// A plain identifier like `x` is a path of length 1.
David Tolnay461d98e2018-01-07 11:07:19 -0800400 ///
401 /// *This type is available if Syn is built with the `"derive"` or
402 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700403 pub Path(ExprPath {
David Tolnay8c91b882017-12-28 23:04:32 -0500404 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700405 pub qself: Option<QSelf>,
406 pub path: Path,
407 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700408
David Tolnaya454c8f2018-01-07 01:01:10 -0800409 /// A referencing operation: `&a` or `&mut a`.
David Tolnay461d98e2018-01-07 11:07:19 -0800410 ///
411 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay00674ba2018-03-31 18:14:11 +0200412 pub Reference(ExprReference #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500413 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800414 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500415 pub mutability: Option<Token![mut]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700416 pub expr: Box<Expr>,
417 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500418
David Tolnaya454c8f2018-01-07 01:01:10 -0800419 /// A `break`, with an optional label to break and an optional
420 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800421 ///
422 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400423 pub Break(ExprBreak #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500424 pub attrs: Vec<Attribute>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500425 pub break_token: Token![break],
David Tolnay63e3dee2017-06-03 20:13:17 -0700426 pub label: Option<Lifetime>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700427 pub expr: Option<Box<Expr>>,
428 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500429
David Tolnaya454c8f2018-01-07 01:01:10 -0800430 /// A `continue`, with an optional label.
David Tolnay461d98e2018-01-07 11:07:19 -0800431 ///
432 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400433 pub Continue(ExprContinue #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500434 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800435 pub continue_token: Token![continue],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500436 pub label: Option<Lifetime>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700437 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500438
David Tolnaya454c8f2018-01-07 01:01:10 -0800439 /// A `return`, with an optional value to be returned.
David Tolnay461d98e2018-01-07 11:07:19 -0800440 ///
441 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayc246cd32017-12-28 23:14:32 -0500442 pub Return(ExprReturn #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500443 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800444 pub return_token: Token![return],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500445 pub expr: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700446 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700447
David Tolnaya454c8f2018-01-07 01:01:10 -0800448 /// A macro invocation expression: `format!("{}", q)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800449 ///
450 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay8c91b882017-12-28 23:04:32 -0500451 pub Macro(ExprMacro #full {
452 pub attrs: Vec<Attribute>,
453 pub mac: Macro,
454 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700455
David Tolnaya454c8f2018-01-07 01:01:10 -0800456 /// A struct literal expression: `Point { x: 1, y: 1 }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700457 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800458 /// The `rest` provides the value of the remaining fields as in `S { a:
459 /// 1, b: 1, ..rest }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800460 ///
461 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400462 pub Struct(ExprStruct #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500463 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700464 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500465 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500466 pub fields: Punctuated<FieldValue, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500467 pub dot2_token: Option<Token![..]>,
468 pub rest: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700469 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700470
David Tolnaya454c8f2018-01-07 01:01:10 -0800471 /// An array literal constructed from one repeated element: `[0u8; N]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800472 ///
473 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400474 pub Repeat(ExprRepeat #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500475 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500476 pub bracket_token: token::Bracket,
Alex Crichton62a0a592017-05-22 13:58:53 -0700477 pub expr: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500478 pub semi_token: Token![;],
David Tolnay84d80442018-01-07 01:03:20 -0800479 pub len: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700480 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700481
David Tolnaya454c8f2018-01-07 01:01:10 -0800482 /// A parenthesized expression: `(a + b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800483 ///
484 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay9374bc02018-01-27 18:49:36 -0800485 pub Paren(ExprParen {
David Tolnay8c91b882017-12-28 23:04:32 -0500486 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500487 pub paren_token: token::Paren,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500488 pub expr: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700489 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700490
David Tolnaya454c8f2018-01-07 01:01:10 -0800491 /// An expression contained within invisible delimiters.
Michael Layzell93c36282017-06-04 20:43:14 -0400492 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800493 /// This variant is important for faithfully representing the precedence
494 /// of expressions and is related to `None`-delimited spans in a
495 /// `TokenStream`.
David Tolnay461d98e2018-01-07 11:07:19 -0800496 ///
497 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaye98775f2017-12-28 23:17:00 -0500498 pub Group(ExprGroup #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500499 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500500 pub group_token: token::Group,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500501 pub expr: Box<Expr>,
Michael Layzell93c36282017-06-04 20:43:14 -0400502 }),
503
David Tolnaya454c8f2018-01-07 01:01:10 -0800504 /// A try-expression: `expr?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800505 ///
506 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400507 pub Try(ExprTry #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500508 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700509 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800510 pub question_token: Token![?],
Alex Crichton62a0a592017-05-22 13:58:53 -0700511 }),
Arnavion02ef13f2017-04-25 00:54:31 -0700512
David Tolnay02a9c6f2018-08-24 18:58:45 -0400513 /// An async block: `async { ... }`.
514 ///
515 /// *This type is available if Syn is built with the `"full"` feature.*
516 pub Async(ExprAsync #full {
517 pub attrs: Vec<Attribute>,
518 pub async_token: Token![async],
519 pub capture: Option<Token![move]>,
520 pub block: Block,
521 }),
522
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400523 /// A try block: `try { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800524 ///
525 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400526 pub TryBlock(ExprTryBlock #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500527 pub attrs: Vec<Attribute>,
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400528 pub try_token: Token![try],
Alex Crichton62a0a592017-05-22 13:58:53 -0700529 pub block: Block,
530 }),
Alex Crichtonfe110462017-06-01 12:49:27 -0700531
David Tolnaya454c8f2018-01-07 01:01:10 -0800532 /// A yield expression: `yield expr`.
David Tolnay461d98e2018-01-07 11:07:19 -0800533 ///
534 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonfe110462017-06-01 12:49:27 -0700535 pub Yield(ExprYield #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500536 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800537 pub yield_token: Token![yield],
Alex Crichtonfe110462017-06-01 12:49:27 -0700538 pub expr: Option<Box<Expr>>,
539 }),
David Tolnay2ae520a2017-12-29 11:19:50 -0500540
David Tolnaya454c8f2018-01-07 01:01:10 -0800541 /// Tokens in expression position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800542 ///
543 /// *This type is available if Syn is built with the `"derive"` or
544 /// `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500545 pub Verbatim(ExprVerbatim #manual_extra_traits {
546 pub tts: TokenStream,
547 }),
548 }
549}
550
551#[cfg(feature = "extra-traits")]
552impl Eq for ExprVerbatim {}
553
554#[cfg(feature = "extra-traits")]
555impl PartialEq for ExprVerbatim {
556 fn eq(&self, other: &Self) -> bool {
557 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
558 }
559}
560
561#[cfg(feature = "extra-traits")]
562impl Hash for ExprVerbatim {
563 fn hash<H>(&self, state: &mut H)
564 where
565 H: Hasher,
566 {
567 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700568 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700569}
570
David Tolnay8c91b882017-12-28 23:04:32 -0500571impl Expr {
572 // Not public API.
573 #[doc(hidden)]
David Tolnay096d4982017-12-28 23:18:18 -0500574 #[cfg(feature = "full")]
David Tolnay2ae520a2017-12-29 11:19:50 -0500575 pub fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
David Tolnay8c91b882017-12-28 23:04:32 -0500576 match *self {
David Tolnay61037c62018-01-05 16:21:03 -0800577 Expr::Box(ExprBox { ref mut attrs, .. })
578 | Expr::InPlace(ExprInPlace { ref mut attrs, .. })
579 | Expr::Array(ExprArray { ref mut attrs, .. })
580 | Expr::Call(ExprCall { ref mut attrs, .. })
581 | Expr::MethodCall(ExprMethodCall { ref mut attrs, .. })
582 | Expr::Tuple(ExprTuple { ref mut attrs, .. })
583 | Expr::Binary(ExprBinary { ref mut attrs, .. })
584 | Expr::Unary(ExprUnary { ref mut attrs, .. })
585 | Expr::Lit(ExprLit { ref mut attrs, .. })
586 | Expr::Cast(ExprCast { ref mut attrs, .. })
587 | Expr::Type(ExprType { ref mut attrs, .. })
588 | Expr::If(ExprIf { ref mut attrs, .. })
589 | Expr::IfLet(ExprIfLet { ref mut attrs, .. })
590 | Expr::While(ExprWhile { ref mut attrs, .. })
591 | Expr::WhileLet(ExprWhileLet { ref mut attrs, .. })
592 | Expr::ForLoop(ExprForLoop { ref mut attrs, .. })
593 | Expr::Loop(ExprLoop { ref mut attrs, .. })
594 | Expr::Match(ExprMatch { ref mut attrs, .. })
595 | Expr::Closure(ExprClosure { ref mut attrs, .. })
596 | Expr::Unsafe(ExprUnsafe { ref mut attrs, .. })
597 | Expr::Block(ExprBlock { ref mut attrs, .. })
598 | Expr::Assign(ExprAssign { ref mut attrs, .. })
599 | Expr::AssignOp(ExprAssignOp { ref mut attrs, .. })
600 | Expr::Field(ExprField { ref mut attrs, .. })
601 | Expr::Index(ExprIndex { ref mut attrs, .. })
602 | Expr::Range(ExprRange { ref mut attrs, .. })
603 | Expr::Path(ExprPath { ref mut attrs, .. })
David Tolnay00674ba2018-03-31 18:14:11 +0200604 | Expr::Reference(ExprReference { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800605 | Expr::Break(ExprBreak { ref mut attrs, .. })
606 | Expr::Continue(ExprContinue { ref mut attrs, .. })
607 | Expr::Return(ExprReturn { ref mut attrs, .. })
608 | Expr::Macro(ExprMacro { ref mut attrs, .. })
609 | Expr::Struct(ExprStruct { ref mut attrs, .. })
610 | Expr::Repeat(ExprRepeat { ref mut attrs, .. })
611 | Expr::Paren(ExprParen { ref mut attrs, .. })
612 | Expr::Group(ExprGroup { ref mut attrs, .. })
613 | Expr::Try(ExprTry { ref mut attrs, .. })
David Tolnay02a9c6f2018-08-24 18:58:45 -0400614 | Expr::Async(ExprAsync { ref mut attrs, .. })
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400615 | Expr::TryBlock(ExprTryBlock { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800616 | Expr::Yield(ExprYield { ref mut attrs, .. }) => mem::replace(attrs, new),
David Tolnay10f464a2018-08-30 18:48:55 -0700617 Expr::Verbatim(_) => Vec::new(),
David Tolnay8c91b882017-12-28 23:04:32 -0500618 }
619 }
620}
621
David Tolnay85b69a42017-12-27 20:43:10 -0500622ast_enum! {
623 /// A struct or tuple struct field accessed in a struct literal or field
624 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800625 ///
626 /// *This type is available if Syn is built with the `"derive"` or `"full"`
627 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500628 pub enum Member {
629 /// A named field like `self.x`.
630 Named(Ident),
631 /// An unnamed field like `self.0`.
632 Unnamed(Index),
633 }
634}
635
David Tolnay85b69a42017-12-27 20:43:10 -0500636ast_struct! {
637 /// The index of an unnamed tuple struct field.
David Tolnay461d98e2018-01-07 11:07:19 -0800638 ///
639 /// *This type is available if Syn is built with the `"derive"` or `"full"`
640 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500641 pub struct Index #manual_extra_traits {
642 pub index: u32,
643 pub span: Span,
644 }
645}
646
David Tolnay14982012017-12-29 00:49:51 -0500647impl From<usize> for Index {
648 fn from(index: usize) -> Index {
David Tolnay34071ba2018-05-20 20:00:41 -0700649 assert!(index < u32::max_value() as usize);
David Tolnay14982012017-12-29 00:49:51 -0500650 Index {
651 index: index as u32,
Alex Crichton9a4dca22018-03-28 06:32:19 -0700652 span: Span::call_site(),
David Tolnay14982012017-12-29 00:49:51 -0500653 }
654 }
655}
656
657#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500658impl Eq for Index {}
659
David Tolnay14982012017-12-29 00:49:51 -0500660#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500661impl PartialEq for Index {
662 fn eq(&self, other: &Self) -> bool {
663 self.index == other.index
664 }
665}
666
David Tolnay14982012017-12-29 00:49:51 -0500667#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500668impl Hash for Index {
669 fn hash<H: Hasher>(&self, state: &mut H) {
670 self.index.hash(state);
671 }
672}
673
674#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700675ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800676 /// The `::<>` explicit type parameters passed to a method call:
677 /// `parse::<u64>()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800678 ///
679 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500680 pub struct MethodTurbofish {
681 pub colon2_token: Token![::],
682 pub lt_token: Token![<],
David Tolnayf2cfd722017-12-31 18:02:51 -0500683 pub args: Punctuated<GenericMethodArgument, Token![,]>,
David Tolnayd60cfec2017-12-29 00:21:38 -0500684 pub gt_token: Token![>],
685 }
686}
687
688#[cfg(feature = "full")]
689ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800690 /// An individual generic argument to a method, like `T`.
David Tolnay461d98e2018-01-07 11:07:19 -0800691 ///
692 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500693 pub enum GenericMethodArgument {
David Tolnaya454c8f2018-01-07 01:01:10 -0800694 /// A type argument.
David Tolnayd60cfec2017-12-29 00:21:38 -0500695 Type(Type),
David Tolnaya454c8f2018-01-07 01:01:10 -0800696 /// A const expression. Must be inside of a block.
David Tolnayd60cfec2017-12-29 00:21:38 -0500697 ///
698 /// NOTE: Identity expressions are represented as Type arguments, as
699 /// they are indistinguishable syntactically.
700 Const(Expr),
701 }
702}
703
704#[cfg(feature = "full")]
705ast_struct! {
Alex Crichton62a0a592017-05-22 13:58:53 -0700706 /// A field-value pair in a struct literal.
David Tolnay461d98e2018-01-07 11:07:19 -0800707 ///
708 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700709 pub struct FieldValue {
David Tolnay85b69a42017-12-27 20:43:10 -0500710 /// Attributes tagged on the field.
711 pub attrs: Vec<Attribute>,
712
713 /// Name or index of the field.
714 pub member: Member,
715
David Tolnay5d7098a2017-12-29 01:35:24 -0500716 /// The colon in `Struct { x: x }`. If written in shorthand like
717 /// `Struct { x }`, there is no colon.
David Tolnay85b69a42017-12-27 20:43:10 -0500718 pub colon_token: Option<Token![:]>,
Clar Charrd22b5702017-03-10 15:24:56 -0500719
Alex Crichton62a0a592017-05-22 13:58:53 -0700720 /// Value of the field.
721 pub expr: Expr,
Alex Crichton62a0a592017-05-22 13:58:53 -0700722 }
David Tolnay055a7042016-10-02 19:23:54 -0700723}
724
Michael Layzell734adb42017-06-07 16:58:31 -0400725#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700726ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800727 /// A lifetime labeling a `for`, `while`, or `loop`.
David Tolnay461d98e2018-01-07 11:07:19 -0800728 ///
729 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaybcd498f2017-12-29 12:02:33 -0500730 pub struct Label {
731 pub name: Lifetime,
732 pub colon_token: Token![:],
733 }
734}
735
736#[cfg(feature = "full")]
737ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800738 /// A braced block containing Rust statements.
David Tolnay461d98e2018-01-07 11:07:19 -0800739 ///
740 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700741 pub struct Block {
David Tolnay32954ef2017-12-26 22:43:16 -0500742 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700743 /// Statements in a block
744 pub stmts: Vec<Stmt>,
745 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700746}
747
Michael Layzell734adb42017-06-07 16:58:31 -0400748#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700749ast_enum! {
750 /// A statement, usually ending in a semicolon.
David Tolnay461d98e2018-01-07 11:07:19 -0800751 ///
752 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700753 pub enum Stmt {
754 /// A local (let) binding.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800755 Local(Local),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700756
Alex Crichton62a0a592017-05-22 13:58:53 -0700757 /// An item definition.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800758 Item(Item),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700759
Alex Crichton62a0a592017-05-22 13:58:53 -0700760 /// Expr without trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800761 Expr(Expr),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700762
David Tolnaya454c8f2018-01-07 01:01:10 -0800763 /// Expression with trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800764 Semi(Expr, Token![;]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700765 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700766}
767
Michael Layzell734adb42017-06-07 16:58:31 -0400768#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700769ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800770 /// A local `let` binding: `let x: u64 = s.parse()?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800771 ///
772 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700773 pub struct Local {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500774 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800775 pub let_token: Token![let],
David Tolnay5b5b7d22018-03-31 21:05:00 +0200776 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500777 pub ty: Option<(Token![:], Box<Type>)>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500778 pub init: Option<(Token![=], Box<Expr>)>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500779 pub semi_token: Token![;],
Alex Crichton62a0a592017-05-22 13:58:53 -0700780 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700781}
782
Michael Layzell734adb42017-06-07 16:58:31 -0400783#[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700784ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800785 /// A pattern in a local binding, function signature, match expression, or
786 /// various other places.
David Tolnay614a0142018-01-07 10:25:43 -0800787 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800788 /// *This type is available if Syn is built with the `"full"` feature.*
789 ///
David Tolnay614a0142018-01-07 10:25:43 -0800790 /// # Syntax tree enum
791 ///
792 /// This type is a [syntax tree enum].
793 ///
794 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
Alex Crichton62a0a592017-05-22 13:58:53 -0700795 // Clippy false positive
796 // https://github.com/Manishearth/rust-clippy/issues/1241
797 #[cfg_attr(feature = "cargo-clippy", allow(enum_variant_names))]
798 pub enum Pat {
David Tolnaya454c8f2018-01-07 01:01:10 -0800799 /// A pattern that matches any value: `_`.
David Tolnay461d98e2018-01-07 11:07:19 -0800800 ///
801 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700802 pub Wild(PatWild {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800803 pub underscore_token: Token![_],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700804 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700805
David Tolnaya454c8f2018-01-07 01:01:10 -0800806 /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
David Tolnay461d98e2018-01-07 11:07:19 -0800807 ///
808 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700809 pub Ident(PatIdent {
David Tolnay24237fb2017-12-29 02:15:26 -0500810 pub by_ref: Option<Token![ref]>,
811 pub mutability: Option<Token![mut]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700812 pub ident: Ident,
David Tolnay8b4d3022017-12-29 12:11:10 -0500813 pub subpat: Option<(Token![@], Box<Pat>)>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700814 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700815
David Tolnaya454c8f2018-01-07 01:01:10 -0800816 /// A struct or struct variant pattern: `Variant { x, y, .. }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800817 ///
818 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700819 pub Struct(PatStruct {
820 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500821 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500822 pub fields: Punctuated<FieldPat, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800823 pub dot2_token: Option<Token![..]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700824 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700825
David Tolnaya454c8f2018-01-07 01:01:10 -0800826 /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800827 ///
828 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700829 pub TupleStruct(PatTupleStruct {
830 pub path: Path,
831 pub pat: PatTuple,
832 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700833
David Tolnaya454c8f2018-01-07 01:01:10 -0800834 /// A path pattern like `Color::Red`, optionally qualified with a
835 /// self-type.
836 ///
837 /// Unquailfied path patterns can legally refer to variants, structs,
838 /// constants or associated constants. Quailfied path patterns like
839 /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
840 /// associated constants.
David Tolnay461d98e2018-01-07 11:07:19 -0800841 ///
842 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700843 pub Path(PatPath {
844 pub qself: Option<QSelf>,
845 pub path: Path,
846 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700847
David Tolnaya454c8f2018-01-07 01:01:10 -0800848 /// A tuple pattern: `(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800849 ///
850 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700851 pub Tuple(PatTuple {
David Tolnay32954ef2017-12-26 22:43:16 -0500852 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500853 pub front: Punctuated<Pat, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500854 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500855 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500856 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700857 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800858
859 /// A box pattern: `box v`.
David Tolnay461d98e2018-01-07 11:07:19 -0800860 ///
861 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700862 pub Box(PatBox {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800863 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500864 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700865 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800866
867 /// A reference pattern: `&mut (first, second)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800868 ///
869 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700870 pub Ref(PatRef {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800871 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500872 pub mutability: Option<Token![mut]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500873 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700874 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800875
876 /// A literal pattern: `0`.
877 ///
878 /// This holds an `Expr` rather than a `Lit` because negative numbers
879 /// are represented as an `Expr::Unary`.
David Tolnay461d98e2018-01-07 11:07:19 -0800880 ///
881 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700882 pub Lit(PatLit {
883 pub expr: Box<Expr>,
884 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800885
886 /// A range pattern: `1..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800887 ///
888 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700889 pub Range(PatRange {
890 pub lo: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700891 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500892 pub hi: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700893 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800894
895 /// A dynamically sized slice pattern: `[a, b, i.., y, z]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800896 ///
897 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700898 pub Slice(PatSlice {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500899 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500900 pub front: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700901 pub middle: Option<Box<Pat>>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500902 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500903 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500904 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700905 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800906
907 /// A macro in expression position.
David Tolnay461d98e2018-01-07 11:07:19 -0800908 ///
909 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay323279a2017-12-29 11:26:32 -0500910 pub Macro(PatMacro {
911 pub mac: Macro,
912 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800913
914 /// Tokens in pattern position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800915 ///
916 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500917 pub Verbatim(PatVerbatim #manual_extra_traits {
918 pub tts: TokenStream,
919 }),
920 }
921}
922
David Tolnayc43b44e2017-12-30 23:55:54 -0500923#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500924impl Eq for PatVerbatim {}
925
David Tolnayc43b44e2017-12-30 23:55:54 -0500926#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500927impl PartialEq for PatVerbatim {
928 fn eq(&self, other: &Self) -> bool {
929 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
930 }
931}
932
David Tolnayc43b44e2017-12-30 23:55:54 -0500933#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500934impl Hash for PatVerbatim {
935 fn hash<H>(&self, state: &mut H)
936 where
937 H: Hasher,
938 {
939 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700940 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700941}
942
Michael Layzell734adb42017-06-07 16:58:31 -0400943#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700944ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800945 /// One arm of a `match` expression: `0...10 => { return true; }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700946 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800947 /// As in:
Alex Crichton62a0a592017-05-22 13:58:53 -0700948 ///
David Tolnaybcf26022017-12-25 22:10:52 -0500949 /// ```rust
David Tolnaya454c8f2018-01-07 01:01:10 -0800950 /// # fn f() -> bool {
David Tolnaybcf26022017-12-25 22:10:52 -0500951 /// # let n = 0;
Alex Crichton62a0a592017-05-22 13:58:53 -0700952 /// match n {
David Tolnaya454c8f2018-01-07 01:01:10 -0800953 /// 0...10 => {
954 /// return true;
955 /// }
956 /// // ...
David Tolnaybcf26022017-12-25 22:10:52 -0500957 /// # _ => {}
Alex Crichton62a0a592017-05-22 13:58:53 -0700958 /// }
David Tolnaya454c8f2018-01-07 01:01:10 -0800959 /// # false
David Tolnaybcf26022017-12-25 22:10:52 -0500960 /// # }
Alex Crichton62a0a592017-05-22 13:58:53 -0700961 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800962 ///
963 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700964 pub struct Arm {
965 pub attrs: Vec<Attribute>,
David Tolnay18cc4d42018-03-31 18:47:20 +0200966 pub leading_vert: Option<Token![|]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500967 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500968 pub guard: Option<(Token![if], Box<Expr>)>,
David Tolnaydfb91432018-03-31 19:19:44 +0200969 pub fat_arrow_token: Token![=>],
Alex Crichton62a0a592017-05-22 13:58:53 -0700970 pub body: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800971 pub comma: Option<Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700972 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700973}
974
Michael Layzell734adb42017-06-07 16:58:31 -0400975#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700976ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800977 /// Limit types of a range, inclusive or exclusive.
David Tolnay461d98e2018-01-07 11:07:19 -0800978 ///
979 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton2e0229c2017-05-23 09:34:50 -0700980 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700981 pub enum RangeLimits {
David Tolnaya454c8f2018-01-07 01:01:10 -0800982 /// Inclusive at the beginning, exclusive at the end.
David Tolnayf8db7ba2017-11-11 22:52:16 -0800983 HalfOpen(Token![..]),
David Tolnaya454c8f2018-01-07 01:01:10 -0800984 /// Inclusive at the beginning and end.
David Tolnaybe55d7b2017-12-17 23:41:20 -0800985 Closed(Token![..=]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700986 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700987}
988
Michael Layzell734adb42017-06-07 16:58:31 -0400989#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700990ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800991 /// A single field in a struct pattern.
Alex Crichton62a0a592017-05-22 13:58:53 -0700992 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800993 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
994 /// the same as `x: x, y: ref y, z: ref mut z` but there is no colon token.
David Tolnay461d98e2018-01-07 11:07:19 -0800995 ///
996 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700997 pub struct FieldPat {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500998 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -0500999 pub member: Member,
David Tolnay4a3f59a2017-12-28 21:21:12 -05001000 pub colon_token: Option<Token![:]>,
Alex Crichton62a0a592017-05-22 13:58:53 -07001001 pub pat: Box<Pat>,
Alex Crichton62a0a592017-05-22 13:58:53 -07001002 }
David Tolnayf4bbbd92016-09-23 14:41:55 -07001003}
1004
Michael Layzell3936ceb2017-07-08 00:28:36 -04001005#[cfg(any(feature = "parsing", feature = "printing"))]
1006#[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -07001007fn requires_terminator(expr: &Expr) -> bool {
David Tolnay01218d12018-08-29 18:13:07 -07001008 // see https://github.com/rust-lang/rust/blob/eb8f2586e/src/libsyntax/parse/classify.rs#L17-L37
David Tolnay8c91b882017-12-28 23:04:32 -05001009 match *expr {
1010 Expr::Unsafe(..)
1011 | Expr::Block(..)
1012 | Expr::If(..)
1013 | Expr::IfLet(..)
1014 | Expr::Match(..)
1015 | Expr::While(..)
1016 | Expr::WhileLet(..)
1017 | Expr::Loop(..)
1018 | Expr::ForLoop(..)
David Tolnay02a9c6f2018-08-24 18:58:45 -04001019 | Expr::Async(..)
David Tolnayfb2dd4b2018-08-24 16:45:34 -04001020 | Expr::TryBlock(..) => false,
Alex Crichton03b30272017-08-28 09:35:24 -07001021 _ => true,
Michael Layzell3936ceb2017-07-08 00:28:36 -04001022 }
1023}
1024
David Tolnayb9c8e322016-09-23 20:48:37 -07001025#[cfg(feature = "parsing")]
1026pub mod parsing {
1027 use super::*;
David Tolnay60291082018-08-28 09:54:49 -07001028 use path;
David Tolnayb9c8e322016-09-23 20:48:37 -07001029
David Tolnay9389c382018-08-27 09:13:37 -07001030 use parse::{Parse, ParseStream, Result};
Michael Layzell734adb42017-06-07 16:58:31 -04001031 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001032 use synom::ext::IdentExt;
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001033
David Tolnaybcf26022017-12-25 22:10:52 -05001034 // When we're parsing expressions which occur before blocks, like in an if
1035 // statement's condition, we cannot parse a struct literal.
1036 //
1037 // Struct literals are ambiguous in certain positions
1038 // https://github.com/rust-lang/rfcs/pull/92
David Tolnay9389c382018-08-27 09:13:37 -07001039 #[derive(Copy, Clone)]
1040 pub struct AllowStruct(bool);
1041
David Tolnay01218d12018-08-29 18:13:07 -07001042 #[derive(Copy, Clone, PartialEq, PartialOrd)]
1043 enum Precedence {
1044 Any,
1045 Assign,
1046 Placement,
1047 Range,
1048 Or,
1049 And,
1050 Compare,
1051 BitOr,
1052 BitXor,
1053 BitAnd,
1054 Shift,
1055 Arithmetic,
1056 Term,
1057 Cast,
1058 }
1059
1060 impl Precedence {
1061 fn of(op: &BinOp) -> Self {
1062 match *op {
1063 BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic,
1064 BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term,
1065 BinOp::And(_) => Precedence::And,
1066 BinOp::Or(_) => Precedence::Or,
1067 BinOp::BitXor(_) => Precedence::BitXor,
1068 BinOp::BitAnd(_) => Precedence::BitAnd,
1069 BinOp::BitOr(_) => Precedence::BitOr,
1070 BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
1071 BinOp::Eq(_) | BinOp::Lt(_) | BinOp::Le(_) | BinOp::Ne(_) | BinOp::Ge(_) | BinOp::Gt(_) => Precedence::Compare,
1072 BinOp::AddEq(_) | BinOp::SubEq(_) | BinOp::MulEq(_) | BinOp::DivEq(_) | BinOp::RemEq(_) | BinOp::BitXorEq(_) | BinOp::BitAndEq(_) | BinOp::BitOrEq(_) | BinOp::ShlEq(_) | BinOp::ShrEq(_) => Precedence::Assign,
1073 }
1074 }
1075 }
1076
David Tolnay9389c382018-08-27 09:13:37 -07001077 impl Parse for Expr {
1078 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001079 ambiguous_expr(input, AllowStruct(true))
Alex Crichton954046c2017-05-30 21:49:42 -07001080 }
1081 }
1082
Michael Layzell734adb42017-06-07 16:58:31 -04001083 #[cfg(feature = "full")]
David Tolnay9fb0aed2018-08-27 10:23:12 -07001084 fn expr_no_struct(input: ParseStream) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001085 ambiguous_expr(input, AllowStruct(false))
David Tolnay9fb0aed2018-08-27 10:23:12 -07001086 }
David Tolnayaf2557e2016-10-24 11:52:21 -07001087
David Tolnay01218d12018-08-29 18:13:07 -07001088 #[cfg(feature = "full")]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001089 fn parse_expr(input: ParseStream, mut lhs: Expr, allow_struct: AllowStruct, base: Precedence) -> Result<Expr> {
David Tolnay01218d12018-08-29 18:13:07 -07001090 loop {
1091 if input.fork().parse::<BinOp>().ok().map_or(false, |op| Precedence::of(&op) >= base) {
1092 let op: BinOp = input.parse()?;
1093 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001094 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001095 loop {
1096 let next = peek_precedence(input);
1097 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001098 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001099 } else {
1100 break;
1101 }
1102 }
1103 lhs = Expr::Binary(ExprBinary {
1104 attrs: Vec::new(),
1105 left: Box::new(lhs),
1106 op: op,
1107 right: Box::new(rhs),
1108 });
1109 } else if Precedence::Assign >= base && input.peek(Token![=]) && !input.peek(Token![==]) && !input.peek(Token![=>]) {
1110 let eq_token: Token![=] = input.parse()?;
David Tolnay7d2e1db2018-08-30 11:49:04 -07001111 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001112 loop {
1113 let next = peek_precedence(input);
1114 if next >= Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001115 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001116 } else {
1117 break;
1118 }
1119 }
1120 lhs = Expr::Assign(ExprAssign {
1121 attrs: Vec::new(),
1122 left: Box::new(lhs),
1123 eq_token: eq_token,
1124 right: Box::new(rhs),
1125 });
1126 } else if Precedence::Placement >= base && input.peek(Token![<-]) {
1127 let arrow_token: Token![<-] = input.parse()?;
David Tolnay7d2e1db2018-08-30 11:49:04 -07001128 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001129 loop {
1130 let next = peek_precedence(input);
1131 if next > Precedence::Placement {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001132 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001133 } else {
1134 break;
1135 }
1136 }
1137 lhs = Expr::InPlace(ExprInPlace {
1138 attrs: Vec::new(),
1139 place: Box::new(lhs),
1140 arrow_token: arrow_token,
1141 value: Box::new(rhs),
1142 });
1143 } else if Precedence::Range >= base && input.peek(Token![..]) {
1144 let limits: RangeLimits = input.parse()?;
1145 let rhs = if input.is_empty()
1146 || input.peek(Token![,])
1147 || input.peek(Token![;])
1148 || !allow_struct.0 && input.peek(token::Brace)
1149 {
1150 None
1151 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001152 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001153 loop {
1154 let next = peek_precedence(input);
1155 if next > Precedence::Range {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001156 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001157 } else {
1158 break;
1159 }
1160 }
1161 Some(rhs)
1162 };
1163 lhs = Expr::Range(ExprRange {
1164 attrs: Vec::new(),
1165 from: Some(Box::new(lhs)),
1166 limits: limits,
1167 to: rhs.map(Box::new),
1168 });
1169 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1170 let as_token: Token![as] = input.parse()?;
1171 let ty = input.call(Type::without_plus)?;
1172 lhs = Expr::Cast(ExprCast {
1173 attrs: Vec::new(),
1174 expr: Box::new(lhs),
1175 as_token: as_token,
1176 ty: Box::new(ty),
1177 });
1178 } else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) {
1179 let colon_token: Token![:] = input.parse()?;
1180 let ty = input.call(Type::without_plus)?;
1181 lhs = Expr::Type(ExprType {
1182 attrs: Vec::new(),
1183 expr: Box::new(lhs),
1184 colon_token: colon_token,
1185 ty: Box::new(ty),
1186 });
1187 } else {
1188 break;
1189 }
1190 }
1191 Ok(lhs)
1192 }
1193
David Tolnay3e541292018-08-30 11:42:15 -07001194 #[cfg(not(feature = "full"))]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001195 fn parse_expr(input: ParseStream, mut lhs: Expr, allow_struct: AllowStruct, base: Precedence) -> Result<Expr> {
David Tolnay3e541292018-08-30 11:42:15 -07001196 loop {
1197 if input.fork().parse::<BinOp>().ok().map_or(false, |op| Precedence::of(&op) >= base) {
1198 let op: BinOp = input.parse()?;
1199 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001200 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay3e541292018-08-30 11:42:15 -07001201 loop {
1202 let next = peek_precedence(input);
1203 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001204 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay3e541292018-08-30 11:42:15 -07001205 } else {
1206 break;
1207 }
1208 }
1209 lhs = Expr::Binary(ExprBinary {
1210 attrs: Vec::new(),
1211 left: Box::new(lhs),
1212 op: op,
1213 right: Box::new(rhs),
1214 });
1215 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1216 let as_token: Token![as] = input.parse()?;
1217 let ty = input.call(Type::without_plus)?;
1218 lhs = Expr::Cast(ExprCast {
1219 attrs: Vec::new(),
1220 expr: Box::new(lhs),
1221 as_token: as_token,
1222 ty: Box::new(ty),
1223 });
1224 } else {
1225 break;
1226 }
1227 }
1228 Ok(lhs)
1229 }
1230
David Tolnay01218d12018-08-29 18:13:07 -07001231 fn peek_precedence(input: ParseStream) -> Precedence {
1232 if let Ok(op) = input.fork().parse() {
1233 Precedence::of(&op)
David Tolnay3e541292018-08-30 11:42:15 -07001234 } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
David Tolnay01218d12018-08-29 18:13:07 -07001235 Precedence::Assign
1236 } else if input.peek(Token![<-]) {
1237 Precedence::Placement
1238 } else if input.peek(Token![..]) {
1239 Precedence::Range
1240 } else if input.peek(Token![as]) || input.peek(Token![:]) && !input.peek(Token![::]) {
1241 Precedence::Cast
1242 } else {
1243 Precedence::Any
1244 }
1245 }
1246
David Tolnaybcf26022017-12-25 22:10:52 -05001247 // Parse an arbitrary expression.
David Tolnay60291082018-08-28 09:54:49 -07001248 fn ambiguous_expr(
1249 input: ParseStream,
1250 allow_struct: AllowStruct,
David Tolnay60291082018-08-28 09:54:49 -07001251 ) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001252 let lhs = unary_expr(input, allow_struct)?;
1253 parse_expr(input, lhs, allow_struct, Precedence::Any)
Michael Layzellb78f3b52017-06-04 19:03:03 -04001254 }
1255
David Tolnaybcf26022017-12-25 22:10:52 -05001256 // <UnOp> <trailer>
1257 // & <trailer>
1258 // &mut <trailer>
1259 // box <trailer>
Michael Layzell734adb42017-06-07 16:58:31 -04001260 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001261 fn unary_expr(
1262 input: ParseStream,
1263 allow_struct: AllowStruct,
David Tolnay60291082018-08-28 09:54:49 -07001264 ) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001265 let ahead = input.fork();
1266 ahead.call(Attribute::parse_outer)?;
1267 if ahead.peek(Token![&])
1268 || ahead.peek(Token![box])
1269 || ahead.peek(Token![*])
1270 || ahead.peek(Token![!])
1271 || ahead.peek(Token![-])
1272 {
1273 let attrs = input.call(Attribute::parse_outer)?;
1274 if input.peek(Token![&]) {
1275 Ok(Expr::Reference(ExprReference {
1276 attrs: attrs,
1277 and_token: input.parse()?,
1278 mutability: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001279 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001280 }))
1281 } else if input.peek(Token![box]) {
1282 Ok(Expr::Box(ExprBox {
1283 attrs: attrs,
1284 box_token: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001285 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001286 }))
1287 } else {
1288 Ok(Expr::Unary(ExprUnary {
1289 attrs: attrs,
1290 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001291 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001292 }))
1293 }
1294 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001295 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001296 }
1297 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001298
Michael Layzell734adb42017-06-07 16:58:31 -04001299 // XXX: This duplication is ugly
1300 #[cfg(not(feature = "full"))]
David Tolnay60291082018-08-28 09:54:49 -07001301 fn unary_expr(
1302 input: ParseStream,
1303 allow_struct: AllowStruct,
David Tolnay60291082018-08-28 09:54:49 -07001304 ) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001305 let ahead = input.fork();
1306 ahead.call(Attribute::parse_outer)?;
1307 if ahead.peek(Token![*]) || ahead.peek(Token![!]) || ahead.peek(Token![-]) {
1308 Ok(Expr::Unary(ExprUnary {
1309 attrs: input.call(Attribute::parse_outer)?,
1310 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001311 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001312 }))
1313 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001314 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001315 }
1316 }
Michael Layzell734adb42017-06-07 16:58:31 -04001317
David Tolnayd997aef2018-07-21 18:42:31 -07001318 #[cfg(feature = "full")]
David Tolnay5d314dc2018-07-21 16:40:01 -07001319 fn take_outer(attrs: &mut Vec<Attribute>) -> Vec<Attribute> {
1320 let mut outer = Vec::new();
1321 let mut inner = Vec::new();
1322 for attr in mem::replace(attrs, Vec::new()) {
1323 match attr.style {
1324 AttrStyle::Outer => outer.push(attr),
1325 AttrStyle::Inner(_) => inner.push(attr),
1326 }
1327 }
1328 *attrs = inner;
1329 outer
1330 }
1331
David Tolnaybcf26022017-12-25 22:10:52 -05001332 // <atom> (..<args>) ...
1333 // <atom> . <ident> (..<args>) ...
1334 // <atom> . <ident> ...
1335 // <atom> . <lit> ...
1336 // <atom> [ <expr> ] ...
1337 // <atom> ? ...
Michael Layzell734adb42017-06-07 16:58:31 -04001338 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001339 fn trailer_expr(
1340 input: ParseStream,
1341 allow_struct: AllowStruct,
David Tolnay60291082018-08-28 09:54:49 -07001342 ) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001343 let mut e = atom_expr(input, allow_struct)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001344
1345 let mut attrs = e.replace_attrs(Vec::new());
1346 let outer_attrs = take_outer(&mut attrs);
1347 e.replace_attrs(attrs);
1348
David Tolnay01218d12018-08-29 18:13:07 -07001349 e = trailer_helper(input, e)?;
1350
1351 let mut attrs = outer_attrs;
1352 attrs.extend(e.replace_attrs(Vec::new()));
1353 e.replace_attrs(attrs);
1354 Ok(e)
1355 }
1356
1357 #[cfg(feature = "full")]
1358 fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
David Tolnay1501f7e2018-08-27 14:21:03 -07001359 loop {
1360 if input.peek(token::Paren) {
1361 let content;
1362 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001363 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001364 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001365 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001366 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001367 });
1368 } else if input.peek(Token![.]) && !input.peek(Token![..]) {
1369 let dot_token: Token![.] = input.parse()?;
1370 let member: Member = input.parse()?;
1371 let turbofish = if member.is_named() && input.peek(Token![::]) {
1372 Some(MethodTurbofish {
1373 colon2_token: input.parse()?,
1374 lt_token: input.parse()?,
1375 args: {
1376 let mut args = Punctuated::new();
1377 loop {
1378 if input.peek(Token![>]) {
1379 break;
1380 }
David Tolnay310b3262018-08-30 15:33:00 -07001381 let value = input.call(generic_method_argument)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001382 args.push_value(value);
1383 if input.peek(Token![>]) {
1384 break;
1385 }
1386 let punct = input.parse()?;
1387 args.push_punct(punct);
1388 }
1389 args
1390 },
1391 gt_token: input.parse()?,
1392 })
1393 } else {
1394 None
1395 };
1396
1397 if turbofish.is_some() || input.peek(token::Paren) {
1398 if let Member::Named(method) = member {
1399 let content;
1400 e = Expr::MethodCall(ExprMethodCall {
1401 attrs: Vec::new(),
1402 receiver: Box::new(e),
1403 dot_token: dot_token,
1404 method: method,
1405 turbofish: turbofish,
1406 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001407 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001408 });
1409 continue;
1410 }
1411 }
1412
1413 e = Expr::Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -05001414 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001415 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001416 dot_token: dot_token,
David Tolnay85b69a42017-12-27 20:43:10 -05001417 member: member,
David Tolnay1501f7e2018-08-27 14:21:03 -07001418 });
1419 } else if input.peek(token::Bracket) {
1420 let content;
1421 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001422 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001423 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001424 bracket_token: bracketed!(content in input),
1425 index: content.parse()?,
1426 });
1427 } else if input.peek(Token![?]) {
1428 e = Expr::Try(ExprTry {
David Tolnay8c91b882017-12-28 23:04:32 -05001429 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001430 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001431 question_token: input.parse()?,
1432 });
1433 } else {
1434 break;
1435 }
1436 }
David Tolnay1501f7e2018-08-27 14:21:03 -07001437 Ok(e)
1438 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001439
Michael Layzell734adb42017-06-07 16:58:31 -04001440 // XXX: Duplication == ugly
1441 #[cfg(not(feature = "full"))]
David Tolnay60291082018-08-28 09:54:49 -07001442 fn trailer_expr(
1443 input: ParseStream,
1444 allow_struct: AllowStruct,
David Tolnay60291082018-08-28 09:54:49 -07001445 ) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001446 let mut e = atom_expr(input, allow_struct)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001447
1448 loop {
1449 if input.peek(token::Paren) {
1450 let content;
1451 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001452 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001453 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001454 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001455 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001456 });
1457 } else if input.peek(Token![.]) {
1458 e = Expr::Field(ExprField {
David Tolnayd5147742018-06-30 10:09:52 -07001459 attrs: Vec::new(),
1460 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001461 dot_token: input.parse()?,
1462 member: input.parse()?,
1463 });
1464 } else if input.peek(token::Bracket) {
1465 let content;
1466 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001467 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001468 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001469 bracket_token: bracketed!(content in input),
1470 index: content.parse()?,
1471 });
1472 } else {
1473 break;
1474 }
1475 }
1476
1477 Ok(e)
1478 }
Michael Layzell734adb42017-06-07 16:58:31 -04001479
David Tolnaya454c8f2018-01-07 01:01:10 -08001480 // Parse all atomic expressions which don't have to worry about precedence
David Tolnaybcf26022017-12-25 22:10:52 -05001481 // interactions, as they are fully contained.
Michael Layzell734adb42017-06-07 16:58:31 -04001482 #[cfg(feature = "full")]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001483 fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001484 if input.peek(token::Group) {
David Tolnay310b3262018-08-30 15:33:00 -07001485 return input.call(expr_group).map(Expr::Group);
David Tolnay6e1e5052018-08-30 10:21:48 -07001486 }
1487
1488 let mut attrs = input.call(Attribute::parse_outer)?;
1489
1490 let mut expr = if input.peek(token::Group) {
David Tolnay310b3262018-08-30 15:33:00 -07001491 Expr::Group(input.call(expr_group)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001492 } else if input.peek(Lit) {
David Tolnay310b3262018-08-30 15:33:00 -07001493 Expr::Lit(input.call(expr_lit)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001494 } else if input.peek(Token![async])
1495 && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
1496 {
David Tolnay310b3262018-08-30 15:33:00 -07001497 Expr::Async(input.call(expr_async)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001498 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001499 Expr::TryBlock(input.call(expr_try_block)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001500 } else if input.peek(Token![|])
1501 || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1502 || input.peek(Token![static])
1503 || input.peek(Token![move])
1504 {
1505 Expr::Closure(expr_closure(input, allow_struct)?)
1506 } else if input.peek(Ident)
1507 || input.peek(Token![::])
1508 || input.peek(Token![<])
1509 || input.peek(Token![self])
1510 || input.peek(Token![Self])
1511 || input.peek(Token![super])
1512 || input.peek(Token![extern])
1513 || input.peek(Token![crate])
1514 {
1515 path_or_macro_or_struct(input, allow_struct)?
1516 } else if input.peek(token::Paren) {
1517 paren_or_tuple(input)?
1518 } else if input.peek(Token![break]) {
1519 Expr::Break(expr_break(input, allow_struct)?)
1520 } else if input.peek(Token![continue]) {
David Tolnay310b3262018-08-30 15:33:00 -07001521 Expr::Continue(input.call(expr_continue)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001522 } else if input.peek(Token![return]) {
1523 Expr::Return(expr_ret(input, allow_struct)?)
1524 } else if input.peek(token::Bracket) {
1525 array_or_repeat(input)?
1526 } else if input.peek(Token![if]) {
1527 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001528 Expr::IfLet(input.call(expr_if_let)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001529 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001530 Expr::If(input.call(expr_if)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001531 }
1532 } else if input.peek(Token![while]) {
1533 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001534 Expr::WhileLet(input.call(expr_while_let)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001535 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001536 Expr::While(input.call(expr_while)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001537 }
1538 } else if input.peek(Token![for]) {
David Tolnay310b3262018-08-30 15:33:00 -07001539 Expr::ForLoop(input.call(expr_for_loop)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001540 } else if input.peek(Token![loop]) {
David Tolnay310b3262018-08-30 15:33:00 -07001541 Expr::Loop(input.call(expr_loop)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001542 } else if input.peek(Token![match]) {
David Tolnay310b3262018-08-30 15:33:00 -07001543 Expr::Match(input.call(expr_match)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001544 } else if input.peek(Token![yield]) {
David Tolnay310b3262018-08-30 15:33:00 -07001545 Expr::Yield(input.call(expr_yield)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001546 } else if input.peek(Token![unsafe]) {
David Tolnay310b3262018-08-30 15:33:00 -07001547 Expr::Unsafe(input.call(expr_unsafe)?)
David Tolnay7d2e1db2018-08-30 11:49:04 -07001548 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001549 Expr::Block(input.call(expr_block)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001550 } else if input.peek(Token![..]) {
1551 Expr::Range(expr_range(input, allow_struct)?)
1552 } else if input.peek(Lifetime) {
1553 let the_label: Label = input.parse()?;
1554 let mut expr = if input.peek(Token![while]) {
1555 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001556 Expr::WhileLet(input.call(expr_while_let)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001557 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001558 Expr::While(input.call(expr_while)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001559 }
1560 } else if input.peek(Token![for]) {
David Tolnay310b3262018-08-30 15:33:00 -07001561 Expr::ForLoop(input.call(expr_for_loop)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001562 } else if input.peek(Token![loop]) {
David Tolnay310b3262018-08-30 15:33:00 -07001563 Expr::Loop(input.call(expr_loop)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001564 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001565 Expr::Block(input.call(expr_block)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001566 } else {
1567 return Err(input.error("expected loop or block expression"));
1568 };
1569 match expr {
1570 Expr::WhileLet(ExprWhileLet { ref mut label, .. }) |
1571 Expr::While(ExprWhile { ref mut label, .. }) |
1572 Expr::ForLoop(ExprForLoop { ref mut label, .. }) |
1573 Expr::Loop(ExprLoop { ref mut label, .. }) |
1574 Expr::Block(ExprBlock { ref mut label, .. }) => *label = Some(the_label),
1575 _ => unreachable!(),
1576 }
1577 expr
1578 } else {
1579 return Err(input.error("expected expression"));
1580 };
1581
1582 attrs.extend(expr.replace_attrs(Vec::new()));
1583 expr.replace_attrs(attrs);
1584 Ok(expr)
1585 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001586
Michael Layzell734adb42017-06-07 16:58:31 -04001587 #[cfg(not(feature = "full"))]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001588 fn atom_expr(input: ParseStream, _allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001589 if input.peek(Lit) {
David Tolnay310b3262018-08-30 15:33:00 -07001590 input.call(expr_lit).map(Expr::Lit)
David Tolnay6e1e5052018-08-30 10:21:48 -07001591 } else if input.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07001592 input.call(expr_paren).map(Expr::Paren)
David Tolnay6e1e5052018-08-30 10:21:48 -07001593 } else if input.peek(Ident)
1594 || input.peek(Token![::])
1595 || input.peek(Token![<])
1596 || input.peek(Token![self])
1597 || input.peek(Token![Self])
1598 || input.peek(Token![super])
1599 || input.peek(Token![extern])
1600 || input.peek(Token![crate])
1601 {
1602 input.parse().map(Expr::Path)
1603 } else {
1604 Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
1605 }
1606 }
1607
1608 #[cfg(feature = "full")]
1609 fn path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1610 let expr: ExprPath = input.parse()?;
1611 if expr.qself.is_some() {
1612 return Ok(Expr::Path(expr));
1613 }
1614
1615 if input.peek(Token![!]) && !input.peek(Token![!=]) {
1616 let mut contains_arguments = false;
1617 for segment in &expr.path.segments {
1618 match segment.arguments {
1619 PathArguments::None => {}
1620 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
1621 contains_arguments = true;
1622 }
1623 }
1624 }
1625
1626 if !contains_arguments {
1627 let bang_token: Token![!] = input.parse()?;
1628 let (delimiter, tts) = mac::parse_delimiter(input)?;
1629 return Ok(Expr::Macro(ExprMacro {
1630 attrs: Vec::new(),
1631 mac: Macro {
1632 path: expr.path,
1633 bang_token: bang_token,
1634 delimiter: delimiter,
1635 tts: tts,
1636 },
1637 }));
1638 }
1639 }
1640
1641 if allow_struct.0 && input.peek(token::Brace) {
1642 let outer_attrs = Vec::new();
1643 expr_struct_helper(input, outer_attrs, expr.path).map(Expr::Struct)
1644 } else {
1645 Ok(Expr::Path(expr))
1646 }
1647 }
1648
1649 #[cfg(feature = "full")]
1650 fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
1651 let content;
1652 let paren_token = parenthesized!(content in input);
1653 let inner_attrs = content.call(Attribute::parse_inner)?;
1654 if content.is_empty() {
1655 return Ok(Expr::Tuple(ExprTuple {
1656 attrs: inner_attrs,
1657 paren_token: paren_token,
1658 elems: Punctuated::new(),
1659 }));
1660 }
1661
1662 let first: Expr = content.parse()?;
1663 if content.is_empty() {
1664 return Ok(Expr::Paren(ExprParen {
1665 attrs: inner_attrs,
1666 paren_token: paren_token,
1667 expr: Box::new(first),
1668 }));
1669 }
1670
1671 let mut elems = Punctuated::new();
1672 elems.push_value(first);
1673 while !content.is_empty() {
1674 let punct = content.parse()?;
1675 elems.push_punct(punct);
1676 if content.is_empty() {
1677 break;
1678 }
1679 let value = content.parse()?;
1680 elems.push_value(value);
1681 }
1682 Ok(Expr::Tuple(ExprTuple {
1683 attrs: inner_attrs,
1684 paren_token: paren_token,
1685 elems: elems,
1686 }))
1687 }
1688
1689 #[cfg(feature = "full")]
1690 fn array_or_repeat(input: ParseStream) -> Result<Expr> {
1691 let content;
1692 let bracket_token = bracketed!(content in input);
1693 let inner_attrs = content.call(Attribute::parse_inner)?;
1694 if content.is_empty() {
1695 return Ok(Expr::Array(ExprArray {
1696 attrs: inner_attrs,
1697 bracket_token: bracket_token,
1698 elems: Punctuated::new(),
1699 }));
1700 }
1701
1702 let first: Expr = content.parse()?;
1703 if content.is_empty() || content.peek(Token![,]) {
1704 let mut elems = Punctuated::new();
1705 elems.push_value(first);
1706 while !content.is_empty() {
1707 let punct = content.parse()?;
1708 elems.push_punct(punct);
1709 if content.is_empty() {
1710 break;
1711 }
1712 let value = content.parse()?;
1713 elems.push_value(value);
1714 }
1715 Ok(Expr::Array(ExprArray {
1716 attrs: inner_attrs,
1717 bracket_token: bracket_token,
1718 elems: elems,
1719 }))
1720 } else if content.peek(Token![;]) {
1721 let semi_token: Token![;] = content.parse()?;
1722 let len: Expr = content.parse()?;
1723 Ok(Expr::Repeat(ExprRepeat {
1724 attrs: inner_attrs,
1725 bracket_token: bracket_token,
1726 expr: Box::new(first),
1727 semi_token: semi_token,
1728 len: Box::new(len),
1729 }))
1730 } else {
1731 Err(content.error("expected `,` or `;`"))
1732 }
1733 }
Michael Layzell734adb42017-06-07 16:58:31 -04001734
Michael Layzell734adb42017-06-07 16:58:31 -04001735 #[cfg(feature = "full")]
David Tolnay01218d12018-08-29 18:13:07 -07001736 fn expr_early(input: ParseStream) -> Result<Expr> {
1737 let mut attrs = input.call(Attribute::parse_outer)?;
1738 let mut expr = if input.peek(Token![if]) {
1739 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001740 Expr::IfLet(input.call(expr_if_let)?)
David Tolnay01218d12018-08-29 18:13:07 -07001741 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001742 Expr::If(input.call(expr_if)?)
David Tolnay01218d12018-08-29 18:13:07 -07001743 }
1744 } else if input.peek(Token![while]) {
1745 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001746 Expr::WhileLet(input.call(expr_while_let)?)
David Tolnay01218d12018-08-29 18:13:07 -07001747 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001748 Expr::While(input.call(expr_while)?)
David Tolnay01218d12018-08-29 18:13:07 -07001749 }
1750 } else if input.peek(Token![for]) {
David Tolnay310b3262018-08-30 15:33:00 -07001751 Expr::ForLoop(input.call(expr_for_loop)?)
David Tolnay01218d12018-08-29 18:13:07 -07001752 } else if input.peek(Token![loop]) {
David Tolnay310b3262018-08-30 15:33:00 -07001753 Expr::Loop(input.call(expr_loop)?)
David Tolnay01218d12018-08-29 18:13:07 -07001754 } else if input.peek(Token![match]) {
David Tolnay310b3262018-08-30 15:33:00 -07001755 Expr::Match(input.call(expr_match)?)
David Tolnay01218d12018-08-29 18:13:07 -07001756 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001757 Expr::TryBlock(input.call(expr_try_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001758 } else if input.peek(Token![unsafe]) {
David Tolnay310b3262018-08-30 15:33:00 -07001759 Expr::Unsafe(input.call(expr_unsafe)?)
David Tolnay01218d12018-08-29 18:13:07 -07001760 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001761 Expr::Block(input.call(expr_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001762 } else {
1763 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001764 let mut expr = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001765
1766 attrs.extend(expr.replace_attrs(Vec::new()));
1767 expr.replace_attrs(attrs);
1768
David Tolnay7d2e1db2018-08-30 11:49:04 -07001769 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001770 };
1771
1772 if input.peek(Token![.]) || input.peek(Token![?]) {
1773 expr = trailer_helper(input, expr)?;
1774
1775 attrs.extend(expr.replace_attrs(Vec::new()));
1776 expr.replace_attrs(attrs);
1777
1778 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001779 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001780 }
1781
1782 attrs.extend(expr.replace_attrs(Vec::new()));
1783 expr.replace_attrs(attrs);
1784 Ok(expr)
1785 }
Michael Layzell35418782017-06-07 09:20:25 -04001786
David Tolnay310b3262018-08-30 15:33:00 -07001787 pub fn expr_lit(input: ParseStream) -> Result<ExprLit> {
1788 Ok(ExprLit {
1789 attrs: Vec::new(),
1790 lit: input.parse()?,
1791 })
David Tolnay8c91b882017-12-28 23:04:32 -05001792 }
1793
1794 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001795 fn expr_group(input: ParseStream) -> Result<ExprGroup> {
1796 let content;
1797 Ok(ExprGroup {
1798 attrs: Vec::new(),
1799 group_token: grouped!(content in input),
1800 expr: content.parse()?,
1801 })
1802 }
1803
1804 #[cfg(not(feature = "full"))]
1805 fn expr_paren(input: ParseStream) -> Result<ExprParen> {
1806 let content;
1807 Ok(ExprParen {
1808 attrs: Vec::new(),
1809 paren_token: parenthesized!(content in input),
1810 expr: content.parse()?,
1811 })
David Tolnay8c91b882017-12-28 23:04:32 -05001812 }
1813
David Tolnaye98775f2017-12-28 23:17:00 -05001814 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001815 fn generic_method_argument(input: ParseStream) -> Result<GenericMethodArgument> {
David Tolnayd60cfec2017-12-29 00:21:38 -05001816 // TODO parse const generics as well
David Tolnay8db2d662018-08-30 17:40:59 -07001817 input.parse().map(GenericMethodArgument::Type)
David Tolnayd60cfec2017-12-29 00:21:38 -05001818 }
1819
1820 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001821 fn expr_if_let(input: ParseStream) -> Result<ExprIfLet> {
1822 Ok(ExprIfLet {
1823 attrs: Vec::new(),
1824 if_token: input.parse()?,
1825 let_token: input.parse()?,
1826 pats: {
1827 let mut pats = Punctuated::new();
1828 let value: Pat = input.parse()?;
1829 pats.push_value(value);
1830 while input.peek(Token![|])
1831 && !input.peek(Token![||])
1832 && !input.peek(Token![|=])
1833 {
1834 let punct = input.parse()?;
1835 pats.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07001836 let value: Pat = input.parse()?;
1837 pats.push_value(value);
David Tolnay310b3262018-08-30 15:33:00 -07001838 }
1839 pats
1840 },
1841 eq_token: input.parse()?,
1842 expr: Box::new(input.call(expr_no_struct)?),
1843 then_branch: input.parse()?,
1844 else_branch: {
1845 if input.peek(Token![else]) {
1846 Some(input.call(else_block)?)
1847 } else {
1848 None
1849 }
1850 },
1851 })
David Tolnay29f9ce12016-10-02 20:58:40 -07001852 }
1853
Michael Layzell734adb42017-06-07 16:58:31 -04001854 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001855 fn expr_if(input: ParseStream) -> Result<ExprIf> {
1856 Ok(ExprIf {
1857 attrs: Vec::new(),
1858 if_token: input.parse()?,
1859 cond: Box::new(input.call(expr_no_struct)?),
1860 then_branch: input.parse()?,
1861 else_branch: {
1862 if input.peek(Token![else]) {
1863 Some(input.call(else_block)?)
1864 } else {
1865 None
1866 }
1867 },
1868 })
Alex Crichton954046c2017-05-30 21:49:42 -07001869 }
David Tolnaybb6feae2016-10-02 21:25:20 -07001870
Michael Layzell734adb42017-06-07 16:58:31 -04001871 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001872 fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
1873 let else_token: Token![else] = input.parse()?;
1874
1875 let lookahead = input.lookahead1();
1876 let else_branch = if input.peek(Token![if]) {
1877 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001878 input.call(expr_if_let).map(Expr::IfLet)?
David Tolnay60291082018-08-28 09:54:49 -07001879 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001880 input.call(expr_if).map(Expr::If)?
David Tolnay60291082018-08-28 09:54:49 -07001881 }
1882 } else if input.peek(token::Brace) {
1883 Expr::Block(ExprBlock {
1884 attrs: Vec::new(),
1885 label: None,
1886 block: input.parse()?,
1887 })
1888 } else {
1889 return Err(lookahead.error());
1890 };
1891
1892 Ok((else_token, Box::new(else_branch)))
1893 }
David Tolnay939766a2016-09-23 23:48:12 -07001894
Michael Layzell734adb42017-06-07 16:58:31 -04001895 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001896 fn expr_for_loop(input: ParseStream) -> Result<ExprForLoop> {
1897 let label: Option<Label> = input.parse()?;
1898 let for_token: Token![for] = input.parse()?;
1899 let pat: Pat = input.parse()?;
1900 let in_token: Token![in] = input.parse()?;
1901 let expr: Expr = input.call(expr_no_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07001902
David Tolnay310b3262018-08-30 15:33:00 -07001903 let content;
1904 let brace_token = braced!(content in input);
1905 let inner_attrs = content.call(Attribute::parse_inner)?;
1906 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07001907
David Tolnay310b3262018-08-30 15:33:00 -07001908 Ok(ExprForLoop {
1909 attrs: inner_attrs,
1910 label: label,
1911 for_token: for_token,
1912 pat: Box::new(pat),
1913 in_token: in_token,
1914 expr: Box::new(expr),
1915 body: Block {
David Tolnay60291082018-08-28 09:54:49 -07001916 brace_token: brace_token,
David Tolnay310b3262018-08-30 15:33:00 -07001917 stmts: stmts,
1918 },
1919 })
Alex Crichton954046c2017-05-30 21:49:42 -07001920 }
David Tolnay1978c672016-10-27 22:05:52 -07001921
Michael Layzell734adb42017-06-07 16:58:31 -04001922 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001923 fn expr_loop(input: ParseStream) -> Result<ExprLoop> {
1924 let label: Option<Label> = input.parse()?;
1925 let loop_token: Token![loop] = input.parse()?;
1926
1927 let content;
1928 let brace_token = braced!(content in input);
1929 let inner_attrs = content.call(Attribute::parse_inner)?;
1930 let stmts = content.call(Block::parse_within)?;
1931
1932 Ok(ExprLoop {
1933 attrs: inner_attrs,
1934 label: label,
1935 loop_token: loop_token,
1936 body: Block {
1937 brace_token: brace_token,
1938 stmts: stmts,
1939 },
1940 })
Alex Crichton954046c2017-05-30 21:49:42 -07001941 }
Arnavion02ef13f2017-04-25 00:54:31 -07001942
Michael Layzell734adb42017-06-07 16:58:31 -04001943 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001944 fn expr_match(input: ParseStream) -> Result<ExprMatch> {
1945 let match_token: Token![match] = input.parse()?;
1946 let expr = expr_no_struct(input)?;
1947
1948 let content;
1949 let brace_token = braced!(content in input);
1950 let inner_attrs = content.call(Attribute::parse_inner)?;
1951
1952 let mut arms = Vec::new();
1953 while !content.is_empty() {
1954 arms.push(content.call(match_arm)?);
1955 }
1956
1957 Ok(ExprMatch {
1958 attrs: inner_attrs,
1959 match_token: match_token,
1960 expr: Box::new(expr),
1961 brace_token: brace_token,
1962 arms: arms,
1963 })
1964 }
1965
1966 #[cfg(feature = "full")]
1967 fn expr_try_block(input: ParseStream) -> Result<ExprTryBlock> {
1968 Ok(ExprTryBlock {
1969 attrs: Vec::new(),
1970 try_token: input.parse()?,
1971 block: input.parse()?,
1972 })
1973 }
1974
1975 #[cfg(feature = "full")]
1976 fn expr_yield(input: ParseStream) -> Result<ExprYield> {
1977 Ok(ExprYield {
1978 attrs: Vec::new(),
1979 yield_token: input.parse()?,
1980 expr: {
1981 if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
1982 Some(input.parse()?)
1983 } else {
1984 None
1985 }
1986 },
1987 })
1988 }
1989
1990 #[cfg(feature = "full")]
1991 fn match_arm(input: ParseStream) -> Result<Arm> {
1992 let requires_comma;
1993 Ok(Arm {
1994 attrs: input.call(Attribute::parse_outer)?,
1995 leading_vert: input.parse()?,
1996 pats: {
1997 let mut pats = Punctuated::new();
1998 let value: Pat = input.parse()?;
1999 pats.push_value(value);
2000 loop {
2001 if !input.peek(Token![|]) {
2002 break;
David Tolnay60291082018-08-28 09:54:49 -07002003 }
David Tolnay310b3262018-08-30 15:33:00 -07002004 let punct = input.parse()?;
2005 pats.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002006 let value: Pat = input.parse()?;
2007 pats.push_value(value);
David Tolnay310b3262018-08-30 15:33:00 -07002008 }
2009 pats
2010 },
2011 guard: {
2012 if input.peek(Token![if]) {
2013 let if_token: Token![if] = input.parse()?;
2014 let guard: Expr = input.parse()?;
2015 Some((if_token, Box::new(guard)))
2016 } else {
2017 None
2018 }
2019 },
2020 fat_arrow_token: input.parse()?,
2021 body: {
2022 let body = input.call(expr_early)?;
David Tolnaye532d6b2018-08-30 16:55:01 -07002023 requires_comma = requires_terminator(&body);
David Tolnay310b3262018-08-30 15:33:00 -07002024 Box::new(body)
2025 },
2026 comma: {
2027 if requires_comma && !input.is_empty() {
2028 Some(input.parse()?)
2029 } else {
2030 input.parse()?
2031 }
2032 },
2033 })
Alex Crichton954046c2017-05-30 21:49:42 -07002034 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07002035
Michael Layzell734adb42017-06-07 16:58:31 -04002036 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002037 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
David Tolnay60291082018-08-28 09:54:49 -07002038 let asyncness: Option<Token![async]> = input.parse()?;
2039 let movability: Option<Token![static]> = if asyncness.is_none() {
2040 input.parse()?
2041 } else {
2042 None
2043 };
2044 let capture: Option<Token![move]> = input.parse()?;
2045 let or1_token: Token![|] = input.parse()?;
2046
2047 let mut inputs = Punctuated::new();
2048 loop {
2049 if input.peek(Token![|]) {
2050 break;
2051 }
2052 let value = fn_arg(input)?;
2053 inputs.push_value(value);
2054 if input.peek(Token![|]) {
2055 break;
2056 }
2057 let punct: Token![,] = input.parse()?;
2058 inputs.push_punct(punct);
2059 }
2060
2061 let or2_token: Token![|] = input.parse()?;
2062
2063 let (output, body) = if input.peek(Token![->]) {
2064 let arrow_token: Token![->] = input.parse()?;
2065 let ty: Type = input.parse()?;
2066 let body: Block = input.parse()?;
2067 let output = ReturnType::Type(arrow_token, Box::new(ty));
2068 let block = Expr::Block(ExprBlock {
2069 attrs: Vec::new(),
2070 label: None,
2071 block: body,
2072 });
2073 (output, block)
2074 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002075 let body = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002076 (ReturnType::Default, body)
2077 };
2078
2079 Ok(ExprClosure {
David Tolnay310b3262018-08-30 15:33:00 -07002080 attrs: Vec::new(),
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002081 asyncness: asyncness,
2082 movability: movability,
2083 capture: capture,
David Tolnay60291082018-08-28 09:54:49 -07002084 or1_token: or1_token,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002085 inputs: inputs,
David Tolnay60291082018-08-28 09:54:49 -07002086 or2_token: or2_token,
2087 output: output,
2088 body: Box::new(body),
2089 })
David Tolnay02a9c6f2018-08-24 18:58:45 -04002090 }
Yusuke Sasaki851062f2018-08-01 06:28:28 +09002091
2092 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002093 fn expr_async(input: ParseStream) -> Result<ExprAsync> {
2094 Ok(ExprAsync {
2095 attrs: Vec::new(),
2096 async_token: input.parse()?,
2097 capture: input.parse()?,
2098 block: input.parse()?,
2099 })
David Tolnay60291082018-08-28 09:54:49 -07002100 }
Gregory Katz3e562cc2016-09-28 18:33:02 -04002101
Michael Layzell734adb42017-06-07 16:58:31 -04002102 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002103 fn fn_arg(input: ParseStream) -> Result<FnArg> {
2104 let pat: Pat = input.parse()?;
2105
2106 if input.peek(Token![:]) {
2107 Ok(FnArg::Captured(ArgCaptured {
2108 pat: pat,
2109 colon_token: input.parse()?,
2110 ty: input.parse()?,
2111 }))
2112 } else {
2113 Ok(FnArg::Inferred(pat))
2114 }
2115 }
2116
2117 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002118 fn expr_while(input: ParseStream) -> Result<ExprWhile> {
2119 let label: Option<Label> = input.parse()?;
2120 let while_token: Token![while] = input.parse()?;
2121 let cond = expr_no_struct(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002122
David Tolnay310b3262018-08-30 15:33:00 -07002123 let content;
2124 let brace_token = braced!(content in input);
2125 let inner_attrs = content.call(Attribute::parse_inner)?;
2126 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002127
David Tolnay310b3262018-08-30 15:33:00 -07002128 Ok(ExprWhile {
2129 attrs: inner_attrs,
2130 label: label,
2131 while_token: while_token,
2132 cond: Box::new(cond),
2133 body: Block {
2134 brace_token: brace_token,
2135 stmts: stmts,
2136 },
2137 })
Alex Crichton954046c2017-05-30 21:49:42 -07002138 }
2139
Michael Layzell734adb42017-06-07 16:58:31 -04002140 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002141 fn expr_while_let(input: ParseStream) -> Result<ExprWhileLet> {
2142 let label: Option<Label> = input.parse()?;
2143 let while_token: Token![while] = input.parse()?;
2144 let let_token: Token![let] = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002145
David Tolnay310b3262018-08-30 15:33:00 -07002146 let mut pats = Punctuated::new();
2147 let value: Pat = input.parse()?;
2148 pats.push_value(value);
2149 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2150 let punct = input.parse()?;
2151 pats.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002152 let value: Pat = input.parse()?;
2153 pats.push_value(value);
David Tolnay60291082018-08-28 09:54:49 -07002154 }
David Tolnay310b3262018-08-30 15:33:00 -07002155
2156 let eq_token: Token![=] = input.parse()?;
2157 let expr = expr_no_struct(input)?;
2158
2159 let content;
2160 let brace_token = braced!(content in input);
2161 let inner_attrs = content.call(Attribute::parse_inner)?;
2162 let stmts = content.call(Block::parse_within)?;
2163
2164 Ok(ExprWhileLet {
2165 attrs: inner_attrs,
2166 label: label,
2167 while_token: while_token,
2168 let_token: let_token,
2169 pats: pats,
2170 eq_token: eq_token,
2171 expr: Box::new(expr),
2172 body: Block {
2173 brace_token: brace_token,
2174 stmts: stmts,
2175 },
2176 })
David Tolnaybcd498f2017-12-29 12:02:33 -05002177 }
2178
2179 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002180 impl Parse for Label {
2181 fn parse(input: ParseStream) -> Result<Self> {
2182 Ok(Label {
2183 name: input.parse()?,
2184 colon_token: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04002185 })
David Tolnay60291082018-08-28 09:54:49 -07002186 }
Alex Crichton954046c2017-05-30 21:49:42 -07002187 }
2188
Michael Layzell734adb42017-06-07 16:58:31 -04002189 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002190 impl Parse for Option<Label> {
2191 fn parse(input: ParseStream) -> Result<Self> {
2192 if input.peek(Lifetime) {
2193 input.parse().map(Some)
2194 } else {
2195 Ok(None)
2196 }
2197 }
2198 }
2199
2200 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002201 fn expr_continue(input: ParseStream) -> Result<ExprContinue> {
2202 Ok(ExprContinue {
2203 attrs: Vec::new(),
2204 continue_token: input.parse()?,
2205 label: input.parse()?,
2206 })
Alex Crichton954046c2017-05-30 21:49:42 -07002207 }
Gregory Katzfd6935d2016-09-30 22:51:25 -04002208
Michael Layzell734adb42017-06-07 16:58:31 -04002209 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002210 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2211 Ok(ExprBreak {
David Tolnay310b3262018-08-30 15:33:00 -07002212 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002213 break_token: input.parse()?,
2214 label: input.parse()?,
2215 expr: {
2216 if input.is_empty()
2217 || input.peek(Token![,])
2218 || input.peek(Token![;])
2219 || !allow_struct.0 && input.peek(token::Brace)
2220 {
2221 None
2222 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002223 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002224 Some(Box::new(expr))
Michael Layzell92639a52017-06-01 00:07:44 -04002225 }
David Tolnay60291082018-08-28 09:54:49 -07002226 },
2227 })
Alex Crichton954046c2017-05-30 21:49:42 -07002228 }
2229
Michael Layzell734adb42017-06-07 16:58:31 -04002230 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002231 fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
2232 Ok(ExprReturn {
David Tolnay310b3262018-08-30 15:33:00 -07002233 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002234 return_token: input.parse()?,
2235 expr: {
2236 if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
2237 None
2238 } else {
2239 // NOTE: return is greedy and eats blocks after it even when in a
2240 // position where structs are not allowed, such as in if statement
2241 // conditions. For example:
2242 //
2243 // if return { println!("A") } {} // Prints "A"
David Tolnay7d2e1db2018-08-30 11:49:04 -07002244 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002245 Some(Box::new(expr))
2246 }
2247 },
2248 })
2249 }
2250
2251 #[cfg(feature = "full")]
David Tolnay6e1e5052018-08-30 10:21:48 -07002252 fn expr_struct_helper(input: ParseStream, outer_attrs: Vec<Attribute>, path: Path) -> Result<ExprStruct> {
2253 let content;
2254 let brace_token = braced!(content in input);
2255 let inner_attrs = content.call(Attribute::parse_inner)?;
David Tolnay60291082018-08-28 09:54:49 -07002256
David Tolnay6e1e5052018-08-30 10:21:48 -07002257 let mut fields = Punctuated::new();
2258 loop {
2259 let attrs = content.call(Attribute::parse_outer)?;
2260 if content.fork().parse::<Member>().is_err() {
2261 if attrs.is_empty() {
David Tolnay60291082018-08-28 09:54:49 -07002262 break;
David Tolnay6e1e5052018-08-30 10:21:48 -07002263 } else {
2264 return Err(content.error("expected struct field"));
David Tolnay60291082018-08-28 09:54:49 -07002265 }
David Tolnay60291082018-08-28 09:54:49 -07002266 }
2267
David Tolnay6e1e5052018-08-30 10:21:48 -07002268 let member: Member = content.parse()?;
2269 let (colon_token, value) = if content.peek(Token![:]) || !member.is_named() {
2270 let colon_token: Token![:] = content.parse()?;
2271 let value: Expr = content.parse()?;
2272 (Some(colon_token), value)
2273 } else if let Member::Named(ref ident) = member {
2274 let value = Expr::Path(ExprPath {
2275 attrs: Vec::new(),
2276 qself: None,
2277 path: Path::from(ident.clone()),
2278 });
2279 (None, value)
David Tolnay60291082018-08-28 09:54:49 -07002280 } else {
David Tolnay6e1e5052018-08-30 10:21:48 -07002281 unreachable!()
David Tolnay60291082018-08-28 09:54:49 -07002282 };
2283
David Tolnay6e1e5052018-08-30 10:21:48 -07002284 fields.push(FieldValue {
2285 attrs: attrs,
2286 member: member,
2287 colon_token: colon_token,
2288 expr: value,
2289 });
2290
2291 if !content.peek(Token![,]) {
2292 break;
2293 }
2294 let punct: Token![,] = content.parse()?;
2295 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002296 }
David Tolnay6e1e5052018-08-30 10:21:48 -07002297
2298 let (dot2_token, rest) = if fields.empty_or_trailing() && content.peek(Token![..]) {
2299 let dot2_token: Token![..] = content.parse()?;
2300 let rest: Expr = content.parse()?;
2301 (Some(dot2_token), Some(Box::new(rest)))
2302 } else {
2303 (None, None)
2304 };
2305
2306 Ok(ExprStruct {
2307 attrs: {
2308 let mut attrs = outer_attrs;
2309 attrs.extend(inner_attrs);
2310 attrs
2311 },
2312 brace_token: brace_token,
2313 path: path,
2314 fields: fields,
2315 dot2_token: dot2_token,
2316 rest: rest,
2317 })
Alex Crichton954046c2017-05-30 21:49:42 -07002318 }
David Tolnay055a7042016-10-02 19:23:54 -07002319
Michael Layzell734adb42017-06-07 16:58:31 -04002320 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002321 fn expr_unsafe(input: ParseStream) -> Result<ExprUnsafe> {
2322 let unsafe_token: Token![unsafe] = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002323
David Tolnay310b3262018-08-30 15:33:00 -07002324 let content;
2325 let brace_token = braced!(content in input);
2326 let inner_attrs = content.call(Attribute::parse_inner)?;
2327 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002328
David Tolnay310b3262018-08-30 15:33:00 -07002329 Ok(ExprUnsafe {
2330 attrs: inner_attrs,
2331 unsafe_token: unsafe_token,
2332 block: Block {
2333 brace_token: brace_token,
2334 stmts: stmts,
2335 },
2336 })
Alex Crichton954046c2017-05-30 21:49:42 -07002337 }
David Tolnay055a7042016-10-02 19:23:54 -07002338
Michael Layzell734adb42017-06-07 16:58:31 -04002339 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002340 pub fn expr_block(input: ParseStream) -> Result<ExprBlock> {
2341 let label: Option<Label> = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002342
David Tolnay310b3262018-08-30 15:33:00 -07002343 let content;
2344 let brace_token = braced!(content in input);
2345 let inner_attrs = content.call(Attribute::parse_inner)?;
2346 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002347
David Tolnay310b3262018-08-30 15:33:00 -07002348 Ok(ExprBlock {
2349 attrs: inner_attrs,
2350 label: label,
2351 block: Block {
2352 brace_token: brace_token,
2353 stmts: stmts,
2354 },
2355 })
Alex Crichton954046c2017-05-30 21:49:42 -07002356 }
David Tolnay89e05672016-10-02 14:39:42 -07002357
Michael Layzell734adb42017-06-07 16:58:31 -04002358 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002359 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2360 Ok(ExprRange {
David Tolnay8c91b882017-12-28 23:04:32 -05002361 attrs: Vec::new(),
2362 from: None,
David Tolnay60291082018-08-28 09:54:49 -07002363 limits: input.parse()?,
2364 to: {
2365 if input.is_empty()
2366 || input.peek(Token![,])
2367 || input.peek(Token![;])
2368 || !allow_struct.0 && input.peek(token::Brace)
2369 {
2370 None
2371 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002372 let to = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002373 Some(Box::new(to))
2374 }
2375 },
2376 })
2377 }
David Tolnay438c9052016-10-07 23:24:48 -07002378
Michael Layzell734adb42017-06-07 16:58:31 -04002379 #[cfg(feature = "full")]
David Tolnayc4c631e2018-08-27 10:44:37 -07002380 impl Parse for RangeLimits {
2381 fn parse(input: ParseStream) -> Result<Self> {
2382 let lookahead = input.lookahead1();
2383 if lookahead.peek(Token![..=]) {
2384 input.parse().map(RangeLimits::Closed)
2385 } else if lookahead.peek(Token![...]) {
2386 let dot3: Token![...] = input.parse()?;
2387 Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2388 } else if lookahead.peek(Token![..]) {
2389 input.parse().map(RangeLimits::HalfOpen)
2390 } else {
2391 Err(lookahead.error())
2392 }
2393 }
Alex Crichton954046c2017-05-30 21:49:42 -07002394 }
David Tolnay438c9052016-10-07 23:24:48 -07002395
David Tolnay60291082018-08-28 09:54:49 -07002396 impl Parse for ExprPath {
2397 fn parse(input: ParseStream) -> Result<Self> {
2398 #[cfg(not(feature = "full"))]
2399 let attrs = Vec::new();
2400 #[cfg(feature = "full")]
2401 let attrs = input.call(Attribute::parse_outer)?;
David Tolnayeb981bb2018-07-21 19:31:38 -07002402
David Tolnay60291082018-08-28 09:54:49 -07002403 let (qself, path) = path::parsing::qpath(input, true)?;
2404
2405 Ok(ExprPath {
David Tolnay73c9b522018-07-21 15:58:40 -07002406 attrs: attrs,
David Tolnay60291082018-08-28 09:54:49 -07002407 qself: qself,
2408 path: path,
Michael Layzell92639a52017-06-01 00:07:44 -04002409 })
David Tolnay60291082018-08-28 09:54:49 -07002410 }
Alex Crichton954046c2017-05-30 21:49:42 -07002411 }
David Tolnay42602292016-10-01 22:25:45 -07002412
Michael Layzell734adb42017-06-07 16:58:31 -04002413 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002414 impl Parse for Block {
2415 fn parse(input: ParseStream) -> Result<Self> {
2416 let content;
2417 Ok(Block {
2418 brace_token: braced!(content in input),
2419 stmts: content.call(Block::parse_within)?,
Michael Layzell92639a52017-06-01 00:07:44 -04002420 })
David Tolnay60291082018-08-28 09:54:49 -07002421 }
Alex Crichton954046c2017-05-30 21:49:42 -07002422 }
David Tolnay939766a2016-09-23 23:48:12 -07002423
Michael Layzell734adb42017-06-07 16:58:31 -04002424 #[cfg(feature = "full")]
Alex Crichton954046c2017-05-30 21:49:42 -07002425 impl Block {
David Tolnay9389c382018-08-27 09:13:37 -07002426 pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002427 let mut stmts = Vec::new();
David Tolnay7158c5f2018-08-30 17:28:34 -07002428 loop {
2429 while input.peek(Token![;]) {
2430 input.parse::<Token![;]>()?;
Michael Layzell92639a52017-06-01 00:07:44 -04002431 }
David Tolnay7158c5f2018-08-30 17:28:34 -07002432 if input.is_empty() {
2433 break;
2434 }
2435 let s = parse_stmt(input, true)?;
2436 let requires_semicolon = if let Stmt::Expr(ref s) = s {
2437 requires_terminator(s)
2438 } else {
2439 false
2440 };
David Tolnaye532d6b2018-08-30 16:55:01 -07002441 stmts.push(s);
David Tolnay7158c5f2018-08-30 17:28:34 -07002442 if input.is_empty() {
2443 break;
2444 } else if requires_semicolon {
2445 return Err(input.error("unexpected token"));
2446 }
David Tolnaye532d6b2018-08-30 16:55:01 -07002447 }
2448 Ok(stmts)
2449 }
Alex Crichton954046c2017-05-30 21:49:42 -07002450 }
2451
Michael Layzell734adb42017-06-07 16:58:31 -04002452 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002453 impl Parse for Stmt {
2454 fn parse(input: ParseStream) -> Result<Self> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002455 parse_stmt(input, false)
2456 }
2457 }
David Tolnay939766a2016-09-23 23:48:12 -07002458
David Tolnaye532d6b2018-08-30 16:55:01 -07002459 #[cfg(feature = "full")]
2460 fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
2461 let ahead = input.fork();
2462 ahead.call(Attribute::parse_outer)?;
2463
David Tolnaye532d6b2018-08-30 16:55:01 -07002464 if {
2465 let ahead = ahead.fork();
2466 // Only parse braces here; paren and bracket will get parsed as
2467 // expression statements
2468 ahead.call(Path::parse_mod_style).is_ok()
2469 && ahead.parse::<Token![!]>().is_ok()
2470 && (ahead.peek(token::Brace) || ahead.peek(Ident))
2471 } {
2472 stmt_mac(input)
2473 } else if ahead.peek(Token![let]) {
2474 stmt_local(input).map(Stmt::Local)
2475 } else if ahead.peek(Token![pub])
2476 || ahead.peek(Token![crate]) && !ahead.peek2(Token![::])
2477 || ahead.peek(Token![extern]) && !ahead.peek2(Token![::])
2478 || ahead.peek(Token![use])
2479 || ahead.peek(Token![static]) && (ahead.peek2(Token![mut]) || ahead.peek2(Ident))
2480 || ahead.peek(Token![const])
2481 || ahead.peek(Token![unsafe]) && !ahead.peek2(token::Brace)
2482 || ahead.peek(Token![async]) && (ahead.peek2(Token![extern]) || ahead.peek2(Token![fn]))
2483 || ahead.peek(Token![fn])
2484 || ahead.peek(Token![mod])
2485 || ahead.peek(Token![type])
2486 || ahead.peek(Token![existential]) && ahead.peek2(Token![type])
2487 || ahead.peek(Token![struct])
2488 || ahead.peek(Token![enum])
2489 || ahead.peek(Token![union]) && ahead.peek2(Ident)
2490 || ahead.peek(Token![auto]) && ahead.peek2(Token![trait])
2491 || ahead.peek(Token![trait])
2492 || ahead.peek(Token![default]) && (ahead.peek2(Token![unsafe]) || ahead.peek2(Token![impl]))
2493 || ahead.peek(Token![impl])
2494 || ahead.peek(Token![macro])
2495 {
2496 input.parse().map(Stmt::Item)
2497 } else {
2498 stmt_expr(input, allow_nosemi)
David Tolnay60291082018-08-28 09:54:49 -07002499 }
Alex Crichton954046c2017-05-30 21:49:42 -07002500 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07002501
Michael Layzell734adb42017-06-07 16:58:31 -04002502 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002503 fn stmt_mac(input: ParseStream) -> Result<Stmt> {
2504 let attrs = input.call(Attribute::parse_outer)?;
2505 let path = input.call(Path::parse_mod_style)?;
2506 let bang_token: Token![!] = input.parse()?;
2507 let ident: Option<Ident> = input.parse()?;
2508 let (delimiter, tts) = mac::parse_delimiter(input)?;
2509 let semi_token: Option<Token![;]> = input.parse()?;
2510
2511 Ok(Stmt::Item(Item::Macro(ItemMacro {
2512 attrs: attrs,
2513 ident: ident,
2514 mac: Macro {
2515 path: path,
2516 bang_token: bang_token,
2517 delimiter: delimiter,
2518 tts: tts,
2519 },
2520 semi_token: semi_token,
2521 })))
Alex Crichton954046c2017-05-30 21:49:42 -07002522 }
David Tolnay84aa0752016-10-02 23:01:13 -07002523
Michael Layzell734adb42017-06-07 16:58:31 -04002524 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002525 fn stmt_local(input: ParseStream) -> Result<Local> {
2526 Ok(Local {
2527 attrs: input.call(Attribute::parse_outer)?,
2528 let_token: input.parse()?,
2529 pats: {
2530 let mut pats = Punctuated::new();
2531 let value: Pat = input.parse()?;
2532 pats.push_value(value);
2533 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2534 let punct = input.parse()?;
2535 pats.push_punct(punct);
2536 let value: Pat = input.parse()?;
2537 pats.push_value(value);
2538 }
2539 pats
2540 },
2541 ty: {
2542 if input.peek(Token![:]) {
2543 let colon_token: Token![:] = input.parse()?;
2544 let ty: Type = input.parse()?;
2545 Some((colon_token, Box::new(ty)))
2546 } else {
2547 None
2548 }
2549 },
2550 init: {
2551 if input.peek(Token![=]) {
2552 let eq_token: Token![=] = input.parse()?;
2553 let init: Expr = input.parse()?;
2554 Some((eq_token, Box::new(init)))
2555 } else {
2556 None
2557 }
2558 },
2559 semi_token: input.parse()?,
2560 })
2561 }
2562
2563 #[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -07002564 fn stmt_expr(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
David Tolnay60291082018-08-28 09:54:49 -07002565 let mut attrs = input.call(Attribute::parse_outer)?;
David Tolnay01218d12018-08-29 18:13:07 -07002566 let mut e = expr_early(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002567
2568 attrs.extend(e.replace_attrs(Vec::new()));
2569 e.replace_attrs(attrs);
2570
2571 if input.peek(Token![;]) {
David Tolnay01218d12018-08-29 18:13:07 -07002572 return Ok(Stmt::Semi(e, input.parse()?));
David Tolnay60291082018-08-28 09:54:49 -07002573 }
David Tolnay60291082018-08-28 09:54:49 -07002574
David Tolnayf00a2762018-08-30 17:22:22 -07002575 if allow_nosemi || !requires_terminator(&e) {
David Tolnaye532d6b2018-08-30 16:55:01 -07002576 Ok(Stmt::Expr(e))
2577 } else {
2578 Err(input.error("expected semicolon"))
David Tolnay01218d12018-08-29 18:13:07 -07002579 }
David Tolnay60291082018-08-28 09:54:49 -07002580 }
2581
2582 #[cfg(feature = "full")]
2583 impl Parse for Pat {
2584 fn parse(input: ParseStream) -> Result<Self> {
2585 // TODO: better error messages
2586 let lookahead = input.lookahead1();
2587 if lookahead.peek(Token![_]) {
David Tolnay310b3262018-08-30 15:33:00 -07002588 input.call(pat_wild).map(Pat::Wild)
David Tolnay60291082018-08-28 09:54:49 -07002589 } else if lookahead.peek(Token![box]) {
David Tolnay310b3262018-08-30 15:33:00 -07002590 input.call(pat_box).map(Pat::Box)
2591 } else if input.fork().call(pat_range).is_ok() {
David Tolnay60291082018-08-28 09:54:49 -07002592 // must be before Pat::Lit
David Tolnay310b3262018-08-30 15:33:00 -07002593 input.call(pat_range).map(Pat::Range)
2594 } else if input.fork().call(pat_tuple_struct).is_ok() {
David Tolnay60291082018-08-28 09:54:49 -07002595 // must be before Pat::Ident
David Tolnay310b3262018-08-30 15:33:00 -07002596 input.call(pat_tuple_struct).map(Pat::TupleStruct)
2597 } else if input.fork().call(pat_struct).is_ok() {
David Tolnay60291082018-08-28 09:54:49 -07002598 // must be before Pat::Ident
David Tolnay310b3262018-08-30 15:33:00 -07002599 input.call(pat_struct).map(Pat::Struct)
2600 } else if input.fork().call(pat_macro).is_ok() {
David Tolnay60291082018-08-28 09:54:49 -07002601 // must be before Pat::Ident
David Tolnay310b3262018-08-30 15:33:00 -07002602 input.call(pat_macro).map(Pat::Macro)
2603 } else if input.fork().call(pat_lit).is_ok() {
David Tolnay60291082018-08-28 09:54:49 -07002604 // must be before Pat::Ident
David Tolnay310b3262018-08-30 15:33:00 -07002605 input.call(pat_lit).map(Pat::Lit)
2606 } else if input.fork().call(pat_ident).is_ok() {
2607 input.call(pat_ident).map(Pat::Ident)
2608 } else if input.fork().call(pat_path).is_ok() {
2609 input.call(pat_path).map(Pat::Path)
David Tolnay60291082018-08-28 09:54:49 -07002610 } else if lookahead.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07002611 input.call(pat_tuple).map(Pat::Tuple)
David Tolnay60291082018-08-28 09:54:49 -07002612 } else if lookahead.peek(Token![&]) {
David Tolnay310b3262018-08-30 15:33:00 -07002613 input.call(pat_ref).map(Pat::Ref)
David Tolnay60291082018-08-28 09:54:49 -07002614 } else if lookahead.peek(token::Bracket) {
David Tolnay310b3262018-08-30 15:33:00 -07002615 input.call(pat_slice).map(Pat::Slice)
David Tolnay60291082018-08-28 09:54:49 -07002616 } else {
2617 Err(lookahead.error())
2618 }
2619 }
2620 }
2621
2622 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002623 fn pat_wild(input: ParseStream) -> Result<PatWild> {
2624 Ok(PatWild {
2625 underscore_token: input.parse()?,
2626 })
Alex Crichton954046c2017-05-30 21:49:42 -07002627 }
2628
Michael Layzell734adb42017-06-07 16:58:31 -04002629 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002630 fn pat_box(input: ParseStream) -> Result<PatBox> {
2631 Ok(PatBox {
2632 box_token: input.parse()?,
2633 pat: input.parse()?,
2634 })
David Tolnay60291082018-08-28 09:54:49 -07002635 }
2636
2637 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002638 fn pat_ident(input: ParseStream) -> Result<PatIdent> {
2639 Ok(PatIdent {
2640 by_ref: input.parse()?,
2641 mutability: input.parse()?,
2642 ident: {
2643 let ident = if input.peek(Ident) || input.peek(Token![self]) {
David Tolnay0dea1b92018-08-30 17:47:29 -07002644 input.call(Ident::parse_any)?
David Tolnay310b3262018-08-30 15:33:00 -07002645 } else {
2646 return Err(input.error("expected identifier or `self`"));
2647 };
2648 if input.peek(Token![<]) || input.peek(Token![::]) {
2649 return Err(input.error("unexpected token"));
David Tolnay60291082018-08-28 09:54:49 -07002650 }
David Tolnay310b3262018-08-30 15:33:00 -07002651 ident
2652 },
2653 subpat: {
2654 if input.peek(Token![@]) {
2655 let at_token: Token![@] = input.parse()?;
2656 let subpat: Pat = input.parse()?;
2657 Some((at_token, Box::new(subpat)))
2658 } else {
2659 None
2660 }
2661 },
2662 })
David Tolnay60291082018-08-28 09:54:49 -07002663 }
2664
2665 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002666 fn pat_tuple_struct(input: ParseStream) -> Result<PatTupleStruct> {
2667 Ok(PatTupleStruct {
2668 path: input.parse()?,
2669 pat: input.call(pat_tuple)?,
2670 })
2671 }
David Tolnay60291082018-08-28 09:54:49 -07002672
David Tolnay310b3262018-08-30 15:33:00 -07002673 #[cfg(feature = "full")]
2674 fn pat_struct(input: ParseStream) -> Result<PatStruct> {
2675 let path: Path = input.parse()?;
2676
2677 let content;
2678 let brace_token = braced!(content in input);
2679
2680 let mut fields = Punctuated::new();
2681 while !content.is_empty() && !content.peek(Token![..]) {
2682 let value = content.call(field_pat)?;
2683 fields.push_value(value);
2684 if !content.peek(Token![,]) {
2685 break;
David Tolnay60291082018-08-28 09:54:49 -07002686 }
David Tolnay310b3262018-08-30 15:33:00 -07002687 let punct: Token![,] = content.parse()?;
2688 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002689 }
David Tolnay310b3262018-08-30 15:33:00 -07002690
2691 let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) {
2692 Some(content.parse()?)
2693 } else {
2694 None
2695 };
2696
2697 Ok(PatStruct {
2698 path: path,
2699 brace_token: brace_token,
2700 fields: fields,
2701 dot2_token: dot2_token,
2702 })
2703 }
2704
2705 #[cfg(feature = "full")]
2706 fn field_pat(input: ParseStream) -> Result<FieldPat> {
2707 let boxed: Option<Token![box]> = input.parse()?;
2708 let by_ref: Option<Token![ref]> = input.parse()?;
2709 let mutability: Option<Token![mut]> = input.parse()?;
2710 let member: Member = input.parse()?;
2711
2712 if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
2713 || member.is_unnamed()
2714 {
2715 return Ok(FieldPat {
2716 attrs: Vec::new(),
2717 member: member,
2718 colon_token: input.parse()?,
2719 pat: input.parse()?,
2720 });
2721 }
2722
2723 let ident = match member {
2724 Member::Named(ident) => ident,
2725 Member::Unnamed(_) => unreachable!(),
2726 };
2727
2728 let mut pat = Pat::Ident(PatIdent {
2729 by_ref: by_ref,
2730 mutability: mutability,
2731 ident: ident.clone(),
2732 subpat: None,
2733 });
2734
2735 if let Some(boxed) = boxed {
2736 pat = Pat::Box(PatBox {
2737 pat: Box::new(pat),
2738 box_token: boxed,
2739 });
2740 }
2741
2742 Ok(FieldPat {
2743 member: Member::Named(ident),
2744 pat: Box::new(pat),
2745 attrs: Vec::new(),
2746 colon_token: None,
2747 })
Alex Crichton954046c2017-05-30 21:49:42 -07002748 }
2749
David Tolnay1501f7e2018-08-27 14:21:03 -07002750 impl Parse for Member {
2751 fn parse(input: ParseStream) -> Result<Self> {
2752 if input.peek(Ident) {
2753 input.parse().map(Member::Named)
2754 } else if input.peek(LitInt) {
2755 input.parse().map(Member::Unnamed)
2756 } else {
2757 Err(input.error("expected identifier or integer"))
2758 }
2759 }
David Tolnay85b69a42017-12-27 20:43:10 -05002760 }
2761
David Tolnay1501f7e2018-08-27 14:21:03 -07002762 impl Parse for Index {
2763 fn parse(input: ParseStream) -> Result<Self> {
2764 let lit: LitInt = input.parse()?;
2765 if let IntSuffix::None = lit.suffix() {
2766 Ok(Index {
2767 index: lit.value() as u32,
2768 span: lit.span(),
2769 })
2770 } else {
2771 Err(input.error("expected unsuffixed integer"))
2772 }
2773 }
David Tolnay85b69a42017-12-27 20:43:10 -05002774 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07002775
Michael Layzell734adb42017-06-07 16:58:31 -04002776 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002777 fn pat_path(input: ParseStream) -> Result<PatPath> {
2778 let p: ExprPath = input.parse()?;
2779 Ok(PatPath {
2780 qself: p.qself,
2781 path: p.path,
2782 })
Alex Crichton954046c2017-05-30 21:49:42 -07002783 }
David Tolnay9636c052016-10-02 17:11:17 -07002784
Michael Layzell734adb42017-06-07 16:58:31 -04002785 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002786 fn pat_tuple(input: ParseStream) -> Result<PatTuple> {
2787 let content;
2788 let paren_token = parenthesized!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002789
David Tolnay310b3262018-08-30 15:33:00 -07002790 let mut front = Punctuated::new();
2791 let mut dot2_token = None::<Token![..]>;
2792 let mut comma_token = None::<Token![,]>;
2793 loop {
2794 if content.is_empty() {
2795 break;
David Tolnay60291082018-08-28 09:54:49 -07002796 }
David Tolnay310b3262018-08-30 15:33:00 -07002797 if content.peek(Token![..]) {
2798 dot2_token = Some(content.parse()?);
2799 comma_token = content.parse()?;
2800 break;
David Tolnay60291082018-08-28 09:54:49 -07002801 }
David Tolnay310b3262018-08-30 15:33:00 -07002802 let value: Pat = content.parse()?;
2803 front.push_value(value);
2804 if content.is_empty() {
2805 break;
2806 }
2807 let punct = content.parse()?;
2808 front.push_punct(punct);
2809 }
2810
David Tolnayf5ebc192018-08-30 18:23:46 -07002811 let mut back = Punctuated::new();
2812 while !content.is_empty() {
2813 let value: Pat = content.parse()?;
2814 back.push_value(value);
2815 if content.is_empty() {
2816 break;
2817 }
2818 let punct = content.parse()?;
2819 back.push_punct(punct);
2820 }
David Tolnay310b3262018-08-30 15:33:00 -07002821
2822 Ok(PatTuple {
2823 paren_token: paren_token,
2824 front: front,
2825 dot2_token: dot2_token,
2826 comma_token: comma_token,
2827 back: back,
2828 })
2829 }
2830
2831 #[cfg(feature = "full")]
2832 fn pat_ref(input: ParseStream) -> Result<PatRef> {
2833 Ok(PatRef {
2834 and_token: input.parse()?,
2835 mutability: input.parse()?,
2836 pat: input.parse()?,
2837 })
2838 }
2839
2840 #[cfg(feature = "full")]
2841 fn pat_lit(input: ParseStream) -> Result<PatLit> {
2842 if input.peek(Lit) || input.peek(Token![-]) && input.peek2(Lit) {
2843 Ok(PatLit {
2844 expr: input.call(pat_lit_expr)?,
2845 })
2846 } else {
2847 Err(input.error("expected literal pattern"))
David Tolnay60291082018-08-28 09:54:49 -07002848 }
2849 }
2850
2851 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002852 fn pat_range(input: ParseStream) -> Result<PatRange> {
2853 Ok(PatRange {
2854 lo: input.call(pat_lit_expr)?,
2855 limits: input.parse()?,
2856 hi: input.call(pat_lit_expr)?,
2857 })
David Tolnay60291082018-08-28 09:54:49 -07002858 }
2859
2860 #[cfg(feature = "full")]
2861 fn pat_lit_expr(input: ParseStream) -> Result<Box<Expr>> {
2862 let neg: Option<Token![-]> = input.parse()?;
2863
2864 let lookahead = input.lookahead1();
2865 let expr = if lookahead.peek(Lit) {
David Tolnay310b3262018-08-30 15:33:00 -07002866 Expr::Lit(input.call(expr_lit)?)
David Tolnay60291082018-08-28 09:54:49 -07002867 } else if lookahead.peek(Ident)
2868 || lookahead.peek(Token![::])
2869 || lookahead.peek(Token![<])
2870 || lookahead.peek(Token![self])
2871 || lookahead.peek(Token![Self])
2872 || lookahead.peek(Token![super])
2873 || lookahead.peek(Token![extern])
2874 || lookahead.peek(Token![crate])
2875 {
2876 Expr::Path(input.parse()?)
2877 } else {
2878 return Err(lookahead.error());
2879 };
2880
2881 Ok(Box::new(if let Some(neg) = neg {
David Tolnay8c91b882017-12-28 23:04:32 -05002882 Expr::Unary(ExprUnary {
2883 attrs: Vec::new(),
David Tolnayc29b9892017-12-27 22:58:14 -05002884 op: UnOp::Neg(neg),
David Tolnay60291082018-08-28 09:54:49 -07002885 expr: Box::new(expr),
David Tolnay3bc597f2017-12-31 02:31:11 -05002886 })
David Tolnay0ad9e9f2016-10-29 22:20:02 -07002887 } else {
David Tolnay60291082018-08-28 09:54:49 -07002888 expr
2889 }))
Alex Crichton954046c2017-05-30 21:49:42 -07002890 }
David Tolnay323279a2017-12-29 11:26:32 -05002891
2892 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002893 fn pat_slice(input: ParseStream) -> Result<PatSlice> {
2894 let content;
2895 let bracket_token = bracketed!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002896
David Tolnay310b3262018-08-30 15:33:00 -07002897 let mut front = Punctuated::new();
2898 let mut middle = None;
2899 loop {
2900 if content.is_empty() || content.peek(Token![..]) {
2901 break;
David Tolnay60291082018-08-28 09:54:49 -07002902 }
David Tolnay310b3262018-08-30 15:33:00 -07002903 let value: Pat = content.parse()?;
2904 if content.peek(Token![..]) {
2905 middle = Some(Box::new(value));
2906 break;
David Tolnay60291082018-08-28 09:54:49 -07002907 }
David Tolnay310b3262018-08-30 15:33:00 -07002908 front.push_value(value);
2909 if content.is_empty() {
2910 break;
2911 }
2912 let punct = content.parse()?;
2913 front.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002914 }
David Tolnay310b3262018-08-30 15:33:00 -07002915
2916 let dot2_token: Option<Token![..]> = content.parse()?;
2917 let mut comma_token = None::<Token![,]>;
2918 let mut back = Punctuated::new();
2919 if dot2_token.is_some() {
2920 comma_token = content.parse()?;
2921 if comma_token.is_some() {
2922 loop {
2923 if content.is_empty() {
2924 break;
2925 }
2926 let value: Pat = content.parse()?;
2927 back.push_value(value);
2928 if content.is_empty() {
2929 break;
2930 }
2931 let punct = content.parse()?;
2932 back.push_punct(punct);
2933 }
2934 }
2935 }
2936
2937 Ok(PatSlice {
2938 bracket_token: bracket_token,
2939 front: front,
2940 middle: middle,
2941 dot2_token: dot2_token,
2942 comma_token: comma_token,
2943 back: back,
2944 })
David Tolnay60291082018-08-28 09:54:49 -07002945 }
2946
2947 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002948 fn pat_macro(input: ParseStream) -> Result<PatMacro> {
2949 Ok(PatMacro {
2950 mac: input.parse()?,
2951 })
David Tolnay323279a2017-12-29 11:26:32 -05002952 }
David Tolnay1501f7e2018-08-27 14:21:03 -07002953
2954 #[cfg(feature = "full")]
2955 impl Member {
2956 fn is_named(&self) -> bool {
2957 match *self {
2958 Member::Named(_) => true,
2959 Member::Unnamed(_) => false,
2960 }
2961 }
David Tolnay60291082018-08-28 09:54:49 -07002962
2963 fn is_unnamed(&self) -> bool {
2964 match *self {
2965 Member::Named(_) => false,
2966 Member::Unnamed(_) => true,
2967 }
2968 }
David Tolnay1501f7e2018-08-27 14:21:03 -07002969 }
David Tolnayb9c8e322016-09-23 20:48:37 -07002970}
2971
David Tolnayf4bbbd92016-09-23 14:41:55 -07002972#[cfg(feature = "printing")]
2973mod printing {
2974 use super::*;
Michael Layzell734adb42017-06-07 16:58:31 -04002975 #[cfg(feature = "full")]
David Tolnay13b3d352016-10-03 00:31:15 -07002976 use attr::FilterAttrs;
Alex Crichtona74a1c82018-05-16 10:20:44 -07002977 use proc_macro2::{Literal, TokenStream};
2978 use quote::{ToTokens, TokenStreamExt};
David Tolnayf4bbbd92016-09-23 14:41:55 -07002979
David Tolnaybcf26022017-12-25 22:10:52 -05002980 // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
David Tolnayb6a0e7d2018-05-20 22:06:47 -07002981 // before appending it to `TokenStream`.
Michael Layzell3936ceb2017-07-08 00:28:36 -04002982 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07002983 fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) {
David Tolnay8c91b882017-12-28 23:04:32 -05002984 if let Expr::Struct(_) = *e {
David Tolnay32954ef2017-12-26 22:43:16 -05002985 token::Paren::default().surround(tokens, |tokens| {
Michael Layzell3936ceb2017-07-08 00:28:36 -04002986 e.to_tokens(tokens);
2987 });
2988 } else {
2989 e.to_tokens(tokens);
2990 }
2991 }
2992
David Tolnay8c91b882017-12-28 23:04:32 -05002993 #[cfg(feature = "full")]
David Tolnayd997aef2018-07-21 18:42:31 -07002994 fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
David Tolnay8c91b882017-12-28 23:04:32 -05002995 tokens.append_all(attrs.outer());
2996 }
Michael Layzell734adb42017-06-07 16:58:31 -04002997
David Tolnayd997aef2018-07-21 18:42:31 -07002998 #[cfg(feature = "full")]
2999 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3000 tokens.append_all(attrs.inner());
3001 }
3002
David Tolnay8c91b882017-12-28 23:04:32 -05003003 #[cfg(not(feature = "full"))]
David Tolnayd997aef2018-07-21 18:42:31 -07003004 fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3005
3006 #[cfg(not(feature = "full"))]
3007 fn inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
Alex Crichton62a0a592017-05-22 13:58:53 -07003008
Michael Layzell734adb42017-06-07 16:58:31 -04003009 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003010 impl ToTokens for ExprBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003011 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003012 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003013 self.box_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003014 self.expr.to_tokens(tokens);
3015 }
3016 }
3017
Michael Layzell734adb42017-06-07 16:58:31 -04003018 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003019 impl ToTokens for ExprInPlace {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003020 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003021 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8701a5c2017-12-28 23:31:10 -05003022 self.place.to_tokens(tokens);
3023 self.arrow_token.to_tokens(tokens);
3024 self.value.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003025 }
3026 }
3027
Michael Layzell734adb42017-06-07 16:58:31 -04003028 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003029 impl ToTokens for ExprArray {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003030 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003031 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003032 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003033 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003034 self.elems.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003035 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003036 }
3037 }
3038
3039 impl ToTokens for ExprCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003040 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003041 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003042 self.func.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003043 self.paren_token.surround(tokens, |tokens| {
3044 self.args.to_tokens(tokens);
3045 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003046 }
3047 }
3048
Michael Layzell734adb42017-06-07 16:58:31 -04003049 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003050 impl ToTokens for ExprMethodCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003051 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003052 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay76418512017-12-28 23:47:47 -05003053 self.receiver.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003054 self.dot_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003055 self.method.to_tokens(tokens);
David Tolnayd60cfec2017-12-29 00:21:38 -05003056 self.turbofish.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003057 self.paren_token.surround(tokens, |tokens| {
3058 self.args.to_tokens(tokens);
3059 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003060 }
3061 }
3062
Michael Layzell734adb42017-06-07 16:58:31 -04003063 #[cfg(feature = "full")]
David Tolnayd60cfec2017-12-29 00:21:38 -05003064 impl ToTokens for MethodTurbofish {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003065 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003066 self.colon2_token.to_tokens(tokens);
3067 self.lt_token.to_tokens(tokens);
3068 self.args.to_tokens(tokens);
3069 self.gt_token.to_tokens(tokens);
3070 }
3071 }
3072
3073 #[cfg(feature = "full")]
3074 impl ToTokens for GenericMethodArgument {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003075 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003076 match *self {
3077 GenericMethodArgument::Type(ref t) => t.to_tokens(tokens),
3078 GenericMethodArgument::Const(ref c) => c.to_tokens(tokens),
3079 }
3080 }
3081 }
3082
3083 #[cfg(feature = "full")]
David Tolnay05362582017-12-26 01:33:57 -05003084 impl ToTokens for ExprTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003085 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003086 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003087 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003088 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003089 self.elems.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003090 // If we only have one argument, we need a trailing comma to
David Tolnay05362582017-12-26 01:33:57 -05003091 // distinguish ExprTuple from ExprParen.
David Tolnaya0834b42018-01-01 21:30:02 -08003092 if self.elems.len() == 1 && !self.elems.trailing_punct() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003093 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003094 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003095 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003096 }
3097 }
3098
3099 impl ToTokens for ExprBinary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003100 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003101 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003102 self.left.to_tokens(tokens);
3103 self.op.to_tokens(tokens);
3104 self.right.to_tokens(tokens);
3105 }
3106 }
3107
3108 impl ToTokens for ExprUnary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003109 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003110 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003111 self.op.to_tokens(tokens);
3112 self.expr.to_tokens(tokens);
3113 }
3114 }
3115
David Tolnay8c91b882017-12-28 23:04:32 -05003116 impl ToTokens for ExprLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003117 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003118 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003119 self.lit.to_tokens(tokens);
3120 }
3121 }
3122
Alex Crichton62a0a592017-05-22 13:58:53 -07003123 impl ToTokens for ExprCast {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003124 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003125 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003126 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003127 self.as_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003128 self.ty.to_tokens(tokens);
3129 }
3130 }
3131
David Tolnay0cf94f22017-12-28 23:46:26 -05003132 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003133 impl ToTokens for ExprType {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003134 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003135 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003136 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003137 self.colon_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003138 self.ty.to_tokens(tokens);
3139 }
3140 }
3141
Michael Layzell734adb42017-06-07 16:58:31 -04003142 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003143 fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>) {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003144 if let Some((ref else_token, ref else_)) = *else_ {
3145 else_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003146
3147 // If we are not one of the valid expressions to exist in an else
3148 // clause, wrap ourselves in a block.
David Tolnay2ccf32a2017-12-29 00:34:26 -05003149 match **else_ {
David Tolnay8c91b882017-12-28 23:04:32 -05003150 Expr::If(_) | Expr::IfLet(_) | Expr::Block(_) => {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003151 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003152 }
3153 _ => {
David Tolnay32954ef2017-12-26 22:43:16 -05003154 token::Brace::default().surround(tokens, |tokens| {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003155 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003156 });
3157 }
3158 }
3159 }
3160 }
3161
3162 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003163 impl ToTokens for ExprIf {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003164 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003165 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003166 self.if_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003167 wrap_bare_struct(tokens, &self.cond);
David Tolnay2ccf32a2017-12-29 00:34:26 -05003168 self.then_branch.to_tokens(tokens);
3169 maybe_wrap_else(tokens, &self.else_branch);
Alex Crichton62a0a592017-05-22 13:58:53 -07003170 }
3171 }
3172
Michael Layzell734adb42017-06-07 16:58:31 -04003173 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003174 impl ToTokens for ExprIfLet {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003175 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003176 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003177 self.if_token.to_tokens(tokens);
3178 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003179 self.pats.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003180 self.eq_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003181 wrap_bare_struct(tokens, &self.expr);
David Tolnay2ccf32a2017-12-29 00:34:26 -05003182 self.then_branch.to_tokens(tokens);
3183 maybe_wrap_else(tokens, &self.else_branch);
Alex Crichton62a0a592017-05-22 13:58:53 -07003184 }
3185 }
3186
Michael Layzell734adb42017-06-07 16:58:31 -04003187 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003188 impl ToTokens for ExprWhile {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003189 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003190 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003191 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003192 self.while_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003193 wrap_bare_struct(tokens, &self.cond);
David Tolnay5d314dc2018-07-21 16:40:01 -07003194 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003195 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003196 tokens.append_all(&self.body.stmts);
3197 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003198 }
3199 }
3200
Michael Layzell734adb42017-06-07 16:58:31 -04003201 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003202 impl ToTokens for ExprWhileLet {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003203 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003204 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003205 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003206 self.while_token.to_tokens(tokens);
3207 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003208 self.pats.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003209 self.eq_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003210 wrap_bare_struct(tokens, &self.expr);
David Tolnay5d314dc2018-07-21 16:40:01 -07003211 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003212 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003213 tokens.append_all(&self.body.stmts);
3214 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003215 }
3216 }
3217
Michael Layzell734adb42017-06-07 16:58:31 -04003218 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003219 impl ToTokens for ExprForLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003220 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003221 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003222 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003223 self.for_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003224 self.pat.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003225 self.in_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003226 wrap_bare_struct(tokens, &self.expr);
David Tolnay5d314dc2018-07-21 16:40:01 -07003227 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003228 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003229 tokens.append_all(&self.body.stmts);
3230 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003231 }
3232 }
3233
Michael Layzell734adb42017-06-07 16:58:31 -04003234 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003235 impl ToTokens for ExprLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003236 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003237 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003238 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003239 self.loop_token.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003240 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003241 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003242 tokens.append_all(&self.body.stmts);
3243 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003244 }
3245 }
3246
Michael Layzell734adb42017-06-07 16:58:31 -04003247 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003248 impl ToTokens for ExprMatch {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003249 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003250 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003251 self.match_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003252 wrap_bare_struct(tokens, &self.expr);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003253 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003254 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay51382052017-12-27 13:46:21 -05003255 for (i, arm) in self.arms.iter().enumerate() {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003256 arm.to_tokens(tokens);
3257 // Ensure that we have a comma after a non-block arm, except
3258 // for the last one.
3259 let is_last = i == self.arms.len() - 1;
David Tolnaye532d6b2018-08-30 16:55:01 -07003260 if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003261 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003262 }
3263 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003264 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003265 }
3266 }
3267
Michael Layzell734adb42017-06-07 16:58:31 -04003268 #[cfg(feature = "full")]
David Tolnay02a9c6f2018-08-24 18:58:45 -04003269 impl ToTokens for ExprAsync {
3270 fn to_tokens(&self, tokens: &mut TokenStream) {
3271 outer_attrs_to_tokens(&self.attrs, tokens);
3272 self.async_token.to_tokens(tokens);
3273 self.capture.to_tokens(tokens);
3274 self.block.to_tokens(tokens);
3275 }
3276 }
3277
3278 #[cfg(feature = "full")]
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003279 impl ToTokens for ExprTryBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003280 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003281 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003282 self.try_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003283 self.block.to_tokens(tokens);
3284 }
3285 }
3286
Michael Layzell734adb42017-06-07 16:58:31 -04003287 #[cfg(feature = "full")]
Alex Crichtonfe110462017-06-01 12:49:27 -07003288 impl ToTokens for ExprYield {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003289 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003290 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonfe110462017-06-01 12:49:27 -07003291 self.yield_token.to_tokens(tokens);
3292 self.expr.to_tokens(tokens);
3293 }
3294 }
3295
3296 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003297 impl ToTokens for ExprClosure {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003298 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003299 outer_attrs_to_tokens(&self.attrs, tokens);
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09003300 self.asyncness.to_tokens(tokens);
David Tolnay13d4c0e2018-03-31 20:53:59 +02003301 self.movability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003302 self.capture.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003303 self.or1_token.to_tokens(tokens);
David Tolnay56080682018-01-06 14:01:52 -08003304 for input in self.inputs.pairs() {
3305 match **input.value() {
David Tolnay51382052017-12-27 13:46:21 -05003306 FnArg::Captured(ArgCaptured {
3307 ref pat,
3308 ty: Type::Infer(_),
3309 ..
3310 }) => {
Alex Crichton62a0a592017-05-22 13:58:53 -07003311 pat.to_tokens(tokens);
David Tolnay9636c052016-10-02 17:11:17 -07003312 }
David Tolnay56080682018-01-06 14:01:52 -08003313 _ => input.value().to_tokens(tokens),
David Tolnay3c2467c2016-10-02 17:55:08 -07003314 }
David Tolnayf2cfd722017-12-31 18:02:51 -05003315 input.punct().to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003316 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003317 self.or2_token.to_tokens(tokens);
David Tolnay7f675742017-12-27 22:43:21 -05003318 self.output.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003319 self.body.to_tokens(tokens);
3320 }
3321 }
3322
Michael Layzell734adb42017-06-07 16:58:31 -04003323 #[cfg(feature = "full")]
Nika Layzell640832a2017-12-04 13:37:09 -05003324 impl ToTokens for ExprUnsafe {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003325 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003326 outer_attrs_to_tokens(&self.attrs, tokens);
Nika Layzell640832a2017-12-04 13:37:09 -05003327 self.unsafe_token.to_tokens(tokens);
David Tolnayc4be3512018-08-27 06:25:44 -07003328 self.block.brace_token.surround(tokens, |tokens| {
3329 inner_attrs_to_tokens(&self.attrs, tokens);
3330 tokens.append_all(&self.block.stmts);
3331 });
Nika Layzell640832a2017-12-04 13:37:09 -05003332 }
3333 }
3334
3335 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003336 impl ToTokens for ExprBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003337 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003338 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay1d8e9962018-08-24 19:04:20 -04003339 self.label.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003340 self.block.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003341 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003342 tokens.append_all(&self.block.stmts);
3343 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003344 }
3345 }
3346
Michael Layzell734adb42017-06-07 16:58:31 -04003347 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003348 impl ToTokens for ExprAssign {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003349 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003350 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003351 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003352 self.eq_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003353 self.right.to_tokens(tokens);
3354 }
3355 }
3356
Michael Layzell734adb42017-06-07 16:58:31 -04003357 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003358 impl ToTokens for ExprAssignOp {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003359 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003360 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003361 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003362 self.op.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003363 self.right.to_tokens(tokens);
3364 }
3365 }
3366
3367 impl ToTokens for ExprField {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003368 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003369 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003370 self.base.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003371 self.dot_token.to_tokens(tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003372 self.member.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003373 }
3374 }
3375
David Tolnay85b69a42017-12-27 20:43:10 -05003376 impl ToTokens for Member {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003377 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay85b69a42017-12-27 20:43:10 -05003378 match *self {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003379 Member::Named(ref ident) => ident.to_tokens(tokens),
David Tolnay85b69a42017-12-27 20:43:10 -05003380 Member::Unnamed(ref index) => index.to_tokens(tokens),
3381 }
3382 }
3383 }
3384
David Tolnay85b69a42017-12-27 20:43:10 -05003385 impl ToTokens for Index {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003386 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichton9a4dca22018-03-28 06:32:19 -07003387 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
3388 lit.set_span(self.span);
3389 tokens.append(lit);
Alex Crichton62a0a592017-05-22 13:58:53 -07003390 }
3391 }
3392
3393 impl ToTokens for ExprIndex {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003394 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003395 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003396 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003397 self.bracket_token.surround(tokens, |tokens| {
3398 self.index.to_tokens(tokens);
3399 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003400 }
3401 }
3402
Michael Layzell734adb42017-06-07 16:58:31 -04003403 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003404 impl ToTokens for ExprRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003405 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003406 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003407 self.from.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003408 match self.limits {
3409 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
3410 RangeLimits::Closed(ref t) => t.to_tokens(tokens),
3411 }
Alex Crichton62a0a592017-05-22 13:58:53 -07003412 self.to.to_tokens(tokens);
3413 }
3414 }
3415
3416 impl ToTokens for ExprPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003417 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003418 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003419 ::PathTokens(&self.qself, &self.path).to_tokens(tokens)
Alex Crichton62a0a592017-05-22 13:58:53 -07003420 }
3421 }
3422
Michael Layzell734adb42017-06-07 16:58:31 -04003423 #[cfg(feature = "full")]
David Tolnay00674ba2018-03-31 18:14:11 +02003424 impl ToTokens for ExprReference {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003425 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003426 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003427 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003428 self.mutability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003429 self.expr.to_tokens(tokens);
3430 }
3431 }
3432
Michael Layzell734adb42017-06-07 16:58:31 -04003433 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003434 impl ToTokens for ExprBreak {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003435 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003436 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003437 self.break_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003438 self.label.to_tokens(tokens);
3439 self.expr.to_tokens(tokens);
3440 }
3441 }
3442
Michael Layzell734adb42017-06-07 16:58:31 -04003443 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003444 impl ToTokens for ExprContinue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003445 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003446 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003447 self.continue_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003448 self.label.to_tokens(tokens);
3449 }
3450 }
3451
Michael Layzell734adb42017-06-07 16:58:31 -04003452 #[cfg(feature = "full")]
David Tolnayc246cd32017-12-28 23:14:32 -05003453 impl ToTokens for ExprReturn {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003454 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003455 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003456 self.return_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003457 self.expr.to_tokens(tokens);
3458 }
3459 }
3460
Michael Layzell734adb42017-06-07 16:58:31 -04003461 #[cfg(feature = "full")]
David Tolnay8c91b882017-12-28 23:04:32 -05003462 impl ToTokens for ExprMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003463 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003464 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003465 self.mac.to_tokens(tokens);
3466 }
3467 }
3468
3469 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003470 impl ToTokens for ExprStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003471 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003472 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003473 self.path.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003474 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003475 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003476 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003477 if self.rest.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -07003478 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003479 self.rest.to_tokens(tokens);
3480 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003481 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003482 }
3483 }
3484
Michael Layzell734adb42017-06-07 16:58:31 -04003485 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003486 impl ToTokens for ExprRepeat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003487 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003488 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003489 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003490 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003491 self.expr.to_tokens(tokens);
3492 self.semi_token.to_tokens(tokens);
David Tolnay84d80442018-01-07 01:03:20 -08003493 self.len.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003494 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003495 }
3496 }
3497
David Tolnaye98775f2017-12-28 23:17:00 -05003498 #[cfg(feature = "full")]
Michael Layzell93c36282017-06-04 20:43:14 -04003499 impl ToTokens for ExprGroup {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003500 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003501 outer_attrs_to_tokens(&self.attrs, tokens);
Michael Layzell93c36282017-06-04 20:43:14 -04003502 self.group_token.surround(tokens, |tokens| {
3503 self.expr.to_tokens(tokens);
3504 });
3505 }
3506 }
3507
Alex Crichton62a0a592017-05-22 13:58:53 -07003508 impl ToTokens for ExprParen {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003509 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003510 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003511 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003512 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003513 self.expr.to_tokens(tokens);
3514 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003515 }
3516 }
3517
Michael Layzell734adb42017-06-07 16:58:31 -04003518 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003519 impl ToTokens for ExprTry {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003520 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003521 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003522 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003523 self.question_token.to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003524 }
3525 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07003526
David Tolnay2ae520a2017-12-29 11:19:50 -05003527 impl ToTokens for ExprVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003528 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003529 self.tts.to_tokens(tokens);
3530 }
3531 }
3532
Michael Layzell734adb42017-06-07 16:58:31 -04003533 #[cfg(feature = "full")]
David Tolnaybcd498f2017-12-29 12:02:33 -05003534 impl ToTokens for Label {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003535 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaybcd498f2017-12-29 12:02:33 -05003536 self.name.to_tokens(tokens);
3537 self.colon_token.to_tokens(tokens);
3538 }
3539 }
3540
3541 #[cfg(feature = "full")]
David Tolnay055a7042016-10-02 19:23:54 -07003542 impl ToTokens for FieldValue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003543 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003544 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003545 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003546 if let Some(ref colon_token) = self.colon_token {
3547 colon_token.to_tokens(tokens);
David Tolnay276690f2016-10-30 12:06:59 -07003548 self.expr.to_tokens(tokens);
3549 }
David Tolnay055a7042016-10-02 19:23:54 -07003550 }
3551 }
3552
Michael Layzell734adb42017-06-07 16:58:31 -04003553 #[cfg(feature = "full")]
David Tolnayb4ad3b52016-10-01 21:58:13 -07003554 impl ToTokens for Arm {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003555 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003556 tokens.append_all(&self.attrs);
David Tolnay18cc4d42018-03-31 18:47:20 +02003557 self.leading_vert.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003558 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003559 if let Some((ref if_token, ref guard)) = self.guard {
3560 if_token.to_tokens(tokens);
3561 guard.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003562 }
David Tolnaydfb91432018-03-31 19:19:44 +02003563 self.fat_arrow_token.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003564 self.body.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003565 self.comma.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003566 }
3567 }
3568
Michael Layzell734adb42017-06-07 16:58:31 -04003569 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003570 impl ToTokens for PatWild {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003571 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003572 self.underscore_token.to_tokens(tokens);
3573 }
3574 }
3575
Michael Layzell734adb42017-06-07 16:58:31 -04003576 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003577 impl ToTokens for PatIdent {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003578 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay24237fb2017-12-29 02:15:26 -05003579 self.by_ref.to_tokens(tokens);
David Tolnayefc96fb2017-12-29 02:03:15 -05003580 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003581 self.ident.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003582 if let Some((ref at_token, ref subpat)) = self.subpat {
3583 at_token.to_tokens(tokens);
3584 subpat.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003585 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003586 }
3587 }
3588
Michael Layzell734adb42017-06-07 16:58:31 -04003589 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003590 impl ToTokens for PatStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003591 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003592 self.path.to_tokens(tokens);
3593 self.brace_token.surround(tokens, |tokens| {
3594 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003595 // NOTE: We need a comma before the dot2 token if it is present.
3596 if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003597 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003598 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003599 self.dot2_token.to_tokens(tokens);
3600 });
3601 }
3602 }
3603
Michael Layzell734adb42017-06-07 16:58:31 -04003604 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003605 impl ToTokens for PatTupleStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003606 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003607 self.path.to_tokens(tokens);
3608 self.pat.to_tokens(tokens);
3609 }
3610 }
3611
Michael Layzell734adb42017-06-07 16:58:31 -04003612 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003613 impl ToTokens for PatPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003614 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003615 ::PathTokens(&self.qself, &self.path).to_tokens(tokens);
3616 }
3617 }
3618
Michael Layzell734adb42017-06-07 16:58:31 -04003619 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003620 impl ToTokens for PatTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003621 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003622 self.paren_token.surround(tokens, |tokens| {
David Tolnay41871922017-12-29 01:53:45 -05003623 self.front.to_tokens(tokens);
3624 if let Some(ref dot2_token) = self.dot2_token {
3625 if !self.front.empty_or_trailing() {
3626 // Ensure there is a comma before the .. token.
David Tolnayf8db7ba2017-11-11 22:52:16 -08003627 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003628 }
David Tolnay41871922017-12-29 01:53:45 -05003629 dot2_token.to_tokens(tokens);
3630 self.comma_token.to_tokens(tokens);
3631 if self.comma_token.is_none() && !self.back.is_empty() {
3632 // Ensure there is a comma after the .. token.
3633 <Token![,]>::default().to_tokens(tokens);
3634 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07003635 }
David Tolnay41871922017-12-29 01:53:45 -05003636 self.back.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003637 });
3638 }
3639 }
3640
Michael Layzell734adb42017-06-07 16:58:31 -04003641 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003642 impl ToTokens for PatBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003643 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003644 self.box_token.to_tokens(tokens);
3645 self.pat.to_tokens(tokens);
3646 }
3647 }
3648
Michael Layzell734adb42017-06-07 16:58:31 -04003649 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003650 impl ToTokens for PatRef {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003651 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003652 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003653 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003654 self.pat.to_tokens(tokens);
3655 }
3656 }
3657
Michael Layzell734adb42017-06-07 16:58:31 -04003658 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003659 impl ToTokens for PatLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003660 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003661 self.expr.to_tokens(tokens);
3662 }
3663 }
3664
Michael Layzell734adb42017-06-07 16:58:31 -04003665 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003666 impl ToTokens for PatRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003667 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003668 self.lo.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003669 match self.limits {
3670 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
David Tolnay7ac699c2018-08-24 14:00:58 -04003671 RangeLimits::Closed(ref t) => Token![...](t.spans).to_tokens(tokens),
David Tolnay475288a2017-12-19 22:59:44 -08003672 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003673 self.hi.to_tokens(tokens);
3674 }
3675 }
3676
Michael Layzell734adb42017-06-07 16:58:31 -04003677 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003678 impl ToTokens for PatSlice {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003679 fn to_tokens(&self, tokens: &mut TokenStream) {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003680 // XXX: This is a mess, and it will be so easy to screw it up. How
3681 // do we make this correct itself better?
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003682 self.bracket_token.surround(tokens, |tokens| {
3683 self.front.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003684
3685 // If we need a comma before the middle or standalone .. token,
3686 // then make sure it's present.
David Tolnay51382052017-12-27 13:46:21 -05003687 if !self.front.empty_or_trailing()
3688 && (self.middle.is_some() || self.dot2_token.is_some())
Michael Layzell3936ceb2017-07-08 00:28:36 -04003689 {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003690 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003691 }
3692
3693 // If we have an identifier, we always need a .. token.
3694 if self.middle.is_some() {
3695 self.middle.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -07003696 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003697 } else if self.dot2_token.is_some() {
3698 self.dot2_token.to_tokens(tokens);
3699 }
3700
3701 // Make sure we have a comma before the back half.
3702 if !self.back.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07003703 TokensOrDefault(&self.comma_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003704 self.back.to_tokens(tokens);
3705 } else {
3706 self.comma_token.to_tokens(tokens);
3707 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003708 })
David Tolnayb4ad3b52016-10-01 21:58:13 -07003709 }
3710 }
3711
Michael Layzell734adb42017-06-07 16:58:31 -04003712 #[cfg(feature = "full")]
David Tolnay323279a2017-12-29 11:26:32 -05003713 impl ToTokens for PatMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003714 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay323279a2017-12-29 11:26:32 -05003715 self.mac.to_tokens(tokens);
3716 }
3717 }
3718
3719 #[cfg(feature = "full")]
David Tolnay2ae520a2017-12-29 11:19:50 -05003720 impl ToTokens for PatVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003721 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003722 self.tts.to_tokens(tokens);
3723 }
3724 }
3725
3726 #[cfg(feature = "full")]
David Tolnay8d9e81a2016-10-03 22:36:32 -07003727 impl ToTokens for FieldPat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003728 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay5d7098a2017-12-29 01:35:24 -05003729 if let Some(ref colon_token) = self.colon_token {
David Tolnay85b69a42017-12-27 20:43:10 -05003730 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003731 colon_token.to_tokens(tokens);
David Tolnay8d9e81a2016-10-03 22:36:32 -07003732 }
3733 self.pat.to_tokens(tokens);
3734 }
3735 }
3736
Michael Layzell734adb42017-06-07 16:58:31 -04003737 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003738 impl ToTokens for Block {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003739 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003740 self.brace_token.surround(tokens, |tokens| {
3741 tokens.append_all(&self.stmts);
3742 });
David Tolnay42602292016-10-01 22:25:45 -07003743 }
3744 }
3745
Michael Layzell734adb42017-06-07 16:58:31 -04003746 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003747 impl ToTokens for Stmt {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003748 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay42602292016-10-01 22:25:45 -07003749 match *self {
David Tolnay191e0582016-10-02 18:31:09 -07003750 Stmt::Local(ref local) => local.to_tokens(tokens),
David Tolnay42602292016-10-01 22:25:45 -07003751 Stmt::Item(ref item) => item.to_tokens(tokens),
3752 Stmt::Expr(ref expr) => expr.to_tokens(tokens),
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003753 Stmt::Semi(ref expr, ref semi) => {
David Tolnay42602292016-10-01 22:25:45 -07003754 expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003755 semi.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -07003756 }
David Tolnay42602292016-10-01 22:25:45 -07003757 }
3758 }
3759 }
David Tolnay191e0582016-10-02 18:31:09 -07003760
Michael Layzell734adb42017-06-07 16:58:31 -04003761 #[cfg(feature = "full")]
David Tolnay191e0582016-10-02 18:31:09 -07003762 impl ToTokens for Local {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003763 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003764 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003765 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003766 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003767 if let Some((ref colon_token, ref ty)) = self.ty {
3768 colon_token.to_tokens(tokens);
3769 ty.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003770 }
David Tolnay8b4d3022017-12-29 12:11:10 -05003771 if let Some((ref eq_token, ref init)) = self.init {
3772 eq_token.to_tokens(tokens);
3773 init.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003774 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003775 self.semi_token.to_tokens(tokens);
David Tolnay191e0582016-10-02 18:31:09 -07003776 }
3777 }
David Tolnayf4bbbd92016-09-23 14:41:55 -07003778}