blob: 1caa04969816f4c57f32066aba975dc58a13a71a [file] [log] [blame]
David Tolnayf4bbbd92016-09-23 14:41:55 -07001use super::*;
David Tolnaye303b7c2018-05-20 16:46:35 -07002use proc_macro2::{Span, TokenStream};
David Tolnay94d2b792018-04-29 12:26:10 -07003use punctuated::Punctuated;
David Tolnay14982012017-12-29 00:49:51 -05004#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -05005use std::hash::{Hash, Hasher};
David Tolnay631dca62018-09-01 02:46:25 -07006#[cfg(all(feature = "parsing", feature = "full"))]
David Tolnay2ae520a2017-12-29 11:19:50 -05007use std::mem;
David Tolnay94d2b792018-04-29 12:26:10 -07008#[cfg(feature = "extra-traits")]
9use tt::TokenStreamHelper;
David Tolnayf4bbbd92016-09-23 14:41:55 -070010
Alex Crichton62a0a592017-05-22 13:58:53 -070011ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -080012 /// A Rust expression.
David Tolnay614a0142018-01-07 10:25:43 -080013 ///
David Tolnay461d98e2018-01-07 11:07:19 -080014 /// *This type is available if Syn is built with the `"derive"` or `"full"`
15 /// feature.*
16 ///
David Tolnay614a0142018-01-07 10:25:43 -080017 /// # Syntax tree enums
18 ///
19 /// This type is a syntax tree enum. In Syn this and other syntax tree enums
20 /// are designed to be traversed using the following rebinding idiom.
21 ///
David Tolnay95989db2019-01-01 15:05:57 -050022 /// ```edition2018
David Tolnay614a0142018-01-07 10:25:43 -080023 /// # use syn::Expr;
24 /// #
25 /// # fn example(expr: Expr) {
26 /// # const IGNORE: &str = stringify! {
27 /// let expr: Expr = /* ... */;
28 /// # };
29 /// match expr {
30 /// Expr::MethodCall(expr) => {
31 /// /* ... */
32 /// }
33 /// Expr::Cast(expr) => {
34 /// /* ... */
35 /// }
David Tolnay9c119122018-09-01 18:47:02 -070036 /// Expr::If(expr) => {
David Tolnay614a0142018-01-07 10:25:43 -080037 /// /* ... */
38 /// }
David Tolnay65336072019-04-22 23:10:52 -070039 ///
David Tolnay614a0142018-01-07 10:25:43 -080040 /// /* ... */
41 /// # _ => {}
David Tolnay65336072019-04-22 23:10:52 -070042 /// # }
David Tolnay614a0142018-01-07 10:25:43 -080043 /// # }
44 /// ```
45 ///
46 /// We begin with a variable `expr` of type `Expr` that has no fields
47 /// (because it is an enum), and by matching on it and rebinding a variable
48 /// with the same name `expr` we effectively imbue our variable with all of
49 /// the data fields provided by the variant that it turned out to be. So for
50 /// example above if we ended up in the `MethodCall` case then we get to use
David Tolnay9c119122018-09-01 18:47:02 -070051 /// `expr.receiver`, `expr.args` etc; if we ended up in the `If` case we get
52 /// to use `expr.cond`, `expr.then_branch`, `expr.else_branch`.
David Tolnay614a0142018-01-07 10:25:43 -080053 ///
David Tolnay614a0142018-01-07 10:25:43 -080054 /// This approach avoids repeating the variant names twice on every line.
55 ///
David Tolnay95989db2019-01-01 15:05:57 -050056 /// ```edition2018
David Tolnay614a0142018-01-07 10:25:43 -080057 /// # use syn::{Expr, ExprMethodCall};
58 /// #
59 /// # fn example(expr: Expr) {
David Tolnay65336072019-04-22 23:10:52 -070060 /// // Repetitive; recommend not doing this.
61 /// match expr {
62 /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => {
David Tolnay614a0142018-01-07 10:25:43 -080063 /// # }
64 /// # _ => {}
65 /// # }
66 /// # }
67 /// ```
68 ///
69 /// In general, the name to which a syntax tree enum variant is bound should
70 /// be a suitable name for the complete syntax tree enum type.
71 ///
David Tolnay95989db2019-01-01 15:05:57 -050072 /// ```edition2018
David Tolnay614a0142018-01-07 10:25:43 -080073 /// # use syn::{Expr, ExprField};
74 /// #
David Tolnay65336072019-04-22 23:10:52 -070075 /// # fn example(discriminant: ExprField) {
David Tolnay614a0142018-01-07 10:25:43 -080076 /// // Binding is called `base` which is the name I would use if I were
77 /// // assigning `*discriminant.base` without an `if let`.
David Tolnay65336072019-04-22 23:10:52 -070078 /// if let Expr::Tuple(base) = *discriminant.base {
David Tolnay614a0142018-01-07 10:25:43 -080079 /// # }
80 /// # }
81 /// ```
82 ///
83 /// A sign that you may not be choosing the right variable names is if you
84 /// see names getting repeated in your code, like accessing
85 /// `receiver.receiver` or `pat.pat` or `cond.cond`.
David Tolnay8c91b882017-12-28 23:04:32 -050086 pub enum Expr {
David Tolnaya454c8f2018-01-07 01:01:10 -080087 /// A box expression: `box f`.
David Tolnay461d98e2018-01-07 11:07:19 -080088 ///
89 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -040090 pub Box(ExprBox #full {
David Tolnay8c91b882017-12-28 23:04:32 -050091 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -080092 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -050093 pub expr: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -070094 }),
Clar Charrd22b5702017-03-10 15:24:56 -050095
David Tolnaya454c8f2018-01-07 01:01:10 -080096 /// A placement expression: `place <- value`.
David Tolnay461d98e2018-01-07 11:07:19 -080097 ///
98 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -040099 pub InPlace(ExprInPlace #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500100 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700101 pub place: Box<Expr>,
David Tolnay8701a5c2017-12-28 23:31:10 -0500102 pub arrow_token: Token![<-],
Alex Crichton62a0a592017-05-22 13:58:53 -0700103 pub value: Box<Expr>,
104 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500105
David Tolnaya454c8f2018-01-07 01:01:10 -0800106 /// A slice literal expression: `[a, b, c, d]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800107 ///
108 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400109 pub Array(ExprArray #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500110 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500111 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500112 pub elems: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700113 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500114
David Tolnaya454c8f2018-01-07 01:01:10 -0800115 /// A function call expression: `invoke(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800116 ///
117 /// *This type is available if Syn is built with the `"derive"` or
118 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700119 pub Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -0500120 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700121 pub func: Box<Expr>,
David Tolnay32954ef2017-12-26 22:43:16 -0500122 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500123 pub args: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700124 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500125
David Tolnaya454c8f2018-01-07 01:01:10 -0800126 /// A method call expression: `x.foo::<T>(a, b)`.
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 MethodCall(ExprMethodCall #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500130 pub attrs: Vec<Attribute>,
David Tolnay76418512017-12-28 23:47:47 -0500131 pub receiver: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800132 pub dot_token: Token![.],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500133 pub method: Ident,
David Tolnayd60cfec2017-12-29 00:21:38 -0500134 pub turbofish: Option<MethodTurbofish>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500135 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500136 pub args: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700137 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500138
David Tolnaya454c8f2018-01-07 01:01:10 -0800139 /// A tuple expression: `(a, b, c, d)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800140 ///
141 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay05362582017-12-26 01:33:57 -0500142 pub Tuple(ExprTuple #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500143 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500144 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500145 pub elems: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700146 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500147
David Tolnaya454c8f2018-01-07 01:01:10 -0800148 /// A binary operation: `a + b`, `a * b`.
David Tolnay461d98e2018-01-07 11:07:19 -0800149 ///
150 /// *This type is available if Syn is built with the `"derive"` or
151 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700152 pub Binary(ExprBinary {
David Tolnay8c91b882017-12-28 23:04:32 -0500153 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700154 pub left: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500155 pub op: BinOp,
Alex Crichton62a0a592017-05-22 13:58:53 -0700156 pub right: Box<Expr>,
157 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500158
David Tolnaya454c8f2018-01-07 01:01:10 -0800159 /// A unary operation: `!x`, `*x`.
David Tolnay461d98e2018-01-07 11:07:19 -0800160 ///
161 /// *This type is available if Syn is built with the `"derive"` or
162 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700163 pub Unary(ExprUnary {
David Tolnay8c91b882017-12-28 23:04:32 -0500164 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700165 pub op: UnOp,
166 pub expr: Box<Expr>,
167 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500168
David Tolnaya454c8f2018-01-07 01:01:10 -0800169 /// A literal in place of an expression: `1`, `"foo"`.
David Tolnay461d98e2018-01-07 11:07:19 -0800170 ///
171 /// *This type is available if Syn is built with the `"derive"` or
172 /// `"full"` feature.*
David Tolnay8c91b882017-12-28 23:04:32 -0500173 pub Lit(ExprLit {
174 pub attrs: Vec<Attribute>,
175 pub lit: Lit,
176 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500177
David Tolnaya454c8f2018-01-07 01:01:10 -0800178 /// A cast expression: `foo as f64`.
David Tolnay461d98e2018-01-07 11:07:19 -0800179 ///
180 /// *This type is available if Syn is built with the `"derive"` or
181 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700182 pub Cast(ExprCast {
David Tolnay8c91b882017-12-28 23:04:32 -0500183 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700184 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800185 pub as_token: Token![as],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800186 pub ty: Box<Type>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700187 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500188
David Tolnaya454c8f2018-01-07 01:01:10 -0800189 /// A type ascription expression: `foo: f64`.
David Tolnay461d98e2018-01-07 11:07:19 -0800190 ///
191 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay0cf94f22017-12-28 23:46:26 -0500192 pub Type(ExprType #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500193 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700194 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800195 pub colon_token: Token![:],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800196 pub ty: Box<Type>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700197 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500198
David Tolnay9c119122018-09-01 18:47:02 -0700199 /// A `let` guard: `let Some(x) = opt`.
200 ///
201 /// *This type is available if Syn is built with the `"full"` feature.*
202 pub Let(ExprLet #full {
203 pub attrs: Vec<Attribute>,
204 pub let_token: Token![let],
205 pub pats: Punctuated<Pat, Token![|]>,
206 pub eq_token: Token![=],
207 pub expr: Box<Expr>,
208 }),
209
David Tolnaya454c8f2018-01-07 01:01:10 -0800210 /// An `if` expression with an optional `else` block: `if expr { ... }
211 /// else { ... }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700212 ///
David Tolnay9c119122018-09-01 18:47:02 -0700213 /// The `else` branch expression may only be an `If` or `Block`
214 /// expression, not any of the other types of expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800215 ///
216 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400217 pub If(ExprIf #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500218 pub attrs: Vec<Attribute>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500219 pub if_token: Token![if],
Alex Crichton62a0a592017-05-22 13:58:53 -0700220 pub cond: Box<Expr>,
David Tolnay2ccf32a2017-12-29 00:34:26 -0500221 pub then_branch: Block,
222 pub else_branch: Option<(Token![else], Box<Expr>)>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700223 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500224
David Tolnaya454c8f2018-01-07 01:01:10 -0800225 /// A while loop: `while expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800226 ///
227 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400228 pub While(ExprWhile #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500229 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500230 pub label: Option<Label>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800231 pub while_token: Token![while],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500232 pub cond: Box<Expr>,
233 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700234 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500235
David Tolnaya454c8f2018-01-07 01:01:10 -0800236 /// A for loop: `for pat in expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800237 ///
238 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400239 pub ForLoop(ExprForLoop #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500240 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500241 pub label: Option<Label>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500242 pub for_token: Token![for],
Alex Crichton62a0a592017-05-22 13:58:53 -0700243 pub pat: Box<Pat>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500244 pub in_token: Token![in],
Alex Crichton62a0a592017-05-22 13:58:53 -0700245 pub expr: Box<Expr>,
246 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700247 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500248
David Tolnaya454c8f2018-01-07 01:01:10 -0800249 /// Conditionless loop: `loop { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800250 ///
251 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400252 pub Loop(ExprLoop #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500253 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500254 pub label: Option<Label>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500255 pub loop_token: Token![loop],
256 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700257 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500258
David Tolnaya454c8f2018-01-07 01:01:10 -0800259 /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800260 ///
261 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400262 pub Match(ExprMatch #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500263 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800264 pub match_token: Token![match],
Alex Crichton62a0a592017-05-22 13:58:53 -0700265 pub expr: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500266 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700267 pub arms: Vec<Arm>,
268 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500269
David Tolnaya454c8f2018-01-07 01:01:10 -0800270 /// A closure expression: `|a, b| a + b`.
David Tolnay461d98e2018-01-07 11:07:19 -0800271 ///
272 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400273 pub Closure(ExprClosure #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500274 pub attrs: Vec<Attribute>,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +0900275 pub asyncness: Option<Token![async]>,
David Tolnay13d4c0e2018-03-31 20:53:59 +0200276 pub movability: Option<Token![static]>,
David Tolnayefc96fb2017-12-29 02:03:15 -0500277 pub capture: Option<Token![move]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800278 pub or1_token: Token![|],
David Tolnayf2cfd722017-12-31 18:02:51 -0500279 pub inputs: Punctuated<FnArg, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800280 pub or2_token: Token![|],
David Tolnay7f675742017-12-27 22:43:21 -0500281 pub output: ReturnType,
282 pub body: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700283 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500284
David Tolnaya454c8f2018-01-07 01:01:10 -0800285 /// An unsafe block: `unsafe { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800286 ///
287 /// *This type is available if Syn is built with the `"full"` feature.*
Nika Layzell640832a2017-12-04 13:37:09 -0500288 pub Unsafe(ExprUnsafe #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500289 pub attrs: Vec<Attribute>,
Nika Layzell640832a2017-12-04 13:37:09 -0500290 pub unsafe_token: Token![unsafe],
291 pub block: Block,
292 }),
293
David Tolnaya454c8f2018-01-07 01:01:10 -0800294 /// A blocked scope: `{ ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800295 ///
296 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400297 pub Block(ExprBlock #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500298 pub attrs: Vec<Attribute>,
David Tolnay1d8e9962018-08-24 19:04:20 -0400299 pub label: Option<Label>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700300 pub block: Block,
301 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700302
David Tolnaya454c8f2018-01-07 01:01:10 -0800303 /// An assignment expression: `a = compute()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800304 ///
305 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400306 pub Assign(ExprAssign #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500307 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700308 pub left: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800309 pub eq_token: Token![=],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500310 pub right: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700311 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500312
David Tolnaya454c8f2018-01-07 01:01:10 -0800313 /// A compound assignment expression: `counter += 1`.
David Tolnay461d98e2018-01-07 11:07:19 -0800314 ///
315 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400316 pub AssignOp(ExprAssignOp #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500317 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700318 pub left: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500319 pub op: BinOp,
Alex Crichton62a0a592017-05-22 13:58:53 -0700320 pub right: Box<Expr>,
321 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500322
David Tolnaya454c8f2018-01-07 01:01:10 -0800323 /// Access of a named struct field (`obj.k`) or unnamed tuple struct
David Tolnay85b69a42017-12-27 20:43:10 -0500324 /// field (`obj.0`).
David Tolnay461d98e2018-01-07 11:07:19 -0800325 ///
326 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd5147742018-06-30 10:09:52 -0700327 pub Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -0500328 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -0500329 pub base: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800330 pub dot_token: Token![.],
David Tolnay85b69a42017-12-27 20:43:10 -0500331 pub member: Member,
Alex Crichton62a0a592017-05-22 13:58:53 -0700332 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500333
David Tolnay05658502018-01-07 09:56:37 -0800334 /// A square bracketed indexing expression: `vector[2]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800335 ///
336 /// *This type is available if Syn is built with the `"derive"` or
337 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700338 pub Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -0500339 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700340 pub expr: Box<Expr>,
David Tolnay32954ef2017-12-26 22:43:16 -0500341 pub bracket_token: token::Bracket,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500342 pub index: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700343 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500344
David Tolnaya454c8f2018-01-07 01:01:10 -0800345 /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800346 ///
347 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400348 pub Range(ExprRange #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500349 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700350 pub from: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700351 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500352 pub to: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700353 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700354
David Tolnaya454c8f2018-01-07 01:01:10 -0800355 /// A path like `std::mem::replace` possibly containing generic
356 /// parameters and a qualified self-type.
Alex Crichton62a0a592017-05-22 13:58:53 -0700357 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800358 /// A plain identifier like `x` is a path of length 1.
David Tolnay461d98e2018-01-07 11:07:19 -0800359 ///
360 /// *This type is available if Syn is built with the `"derive"` or
361 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700362 pub Path(ExprPath {
David Tolnay8c91b882017-12-28 23:04:32 -0500363 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700364 pub qself: Option<QSelf>,
365 pub path: Path,
366 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700367
David Tolnaya454c8f2018-01-07 01:01:10 -0800368 /// A referencing operation: `&a` or `&mut a`.
David Tolnay461d98e2018-01-07 11:07:19 -0800369 ///
370 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay00674ba2018-03-31 18:14:11 +0200371 pub Reference(ExprReference #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500372 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800373 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500374 pub mutability: Option<Token![mut]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700375 pub expr: Box<Expr>,
376 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500377
David Tolnaya454c8f2018-01-07 01:01:10 -0800378 /// A `break`, with an optional label to break and an optional
379 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800380 ///
381 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400382 pub Break(ExprBreak #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500383 pub attrs: Vec<Attribute>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500384 pub break_token: Token![break],
David Tolnay63e3dee2017-06-03 20:13:17 -0700385 pub label: Option<Lifetime>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700386 pub expr: Option<Box<Expr>>,
387 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500388
David Tolnaya454c8f2018-01-07 01:01:10 -0800389 /// A `continue`, with an optional label.
David Tolnay461d98e2018-01-07 11:07:19 -0800390 ///
391 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400392 pub Continue(ExprContinue #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500393 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800394 pub continue_token: Token![continue],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500395 pub label: Option<Lifetime>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700396 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500397
David Tolnaya454c8f2018-01-07 01:01:10 -0800398 /// A `return`, with an optional value to be returned.
David Tolnay461d98e2018-01-07 11:07:19 -0800399 ///
400 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayc246cd32017-12-28 23:14:32 -0500401 pub Return(ExprReturn #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500402 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800403 pub return_token: Token![return],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500404 pub expr: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700405 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700406
David Tolnaya454c8f2018-01-07 01:01:10 -0800407 /// A macro invocation expression: `format!("{}", q)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800408 ///
409 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay8c91b882017-12-28 23:04:32 -0500410 pub Macro(ExprMacro #full {
411 pub attrs: Vec<Attribute>,
412 pub mac: Macro,
413 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700414
David Tolnaya454c8f2018-01-07 01:01:10 -0800415 /// A struct literal expression: `Point { x: 1, y: 1 }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700416 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800417 /// The `rest` provides the value of the remaining fields as in `S { a:
418 /// 1, b: 1, ..rest }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800419 ///
420 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400421 pub Struct(ExprStruct #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500422 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700423 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500424 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500425 pub fields: Punctuated<FieldValue, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500426 pub dot2_token: Option<Token![..]>,
427 pub rest: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700428 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700429
David Tolnaya454c8f2018-01-07 01:01:10 -0800430 /// An array literal constructed from one repeated element: `[0u8; N]`.
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 Repeat(ExprRepeat #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500434 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500435 pub bracket_token: token::Bracket,
Alex Crichton62a0a592017-05-22 13:58:53 -0700436 pub expr: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500437 pub semi_token: Token![;],
David Tolnay84d80442018-01-07 01:03:20 -0800438 pub len: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700439 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700440
David Tolnaya454c8f2018-01-07 01:01:10 -0800441 /// A parenthesized expression: `(a + b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800442 ///
443 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay9374bc02018-01-27 18:49:36 -0800444 pub Paren(ExprParen {
David Tolnay8c91b882017-12-28 23:04:32 -0500445 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500446 pub paren_token: token::Paren,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500447 pub expr: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700448 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700449
David Tolnaya454c8f2018-01-07 01:01:10 -0800450 /// An expression contained within invisible delimiters.
Michael Layzell93c36282017-06-04 20:43:14 -0400451 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800452 /// This variant is important for faithfully representing the precedence
453 /// of expressions and is related to `None`-delimited spans in a
454 /// `TokenStream`.
David Tolnay461d98e2018-01-07 11:07:19 -0800455 ///
456 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaye98775f2017-12-28 23:17:00 -0500457 pub Group(ExprGroup #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500458 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500459 pub group_token: token::Group,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500460 pub expr: Box<Expr>,
Michael Layzell93c36282017-06-04 20:43:14 -0400461 }),
462
David Tolnaya454c8f2018-01-07 01:01:10 -0800463 /// A try-expression: `expr?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800464 ///
465 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400466 pub Try(ExprTry #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500467 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700468 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800469 pub question_token: Token![?],
Alex Crichton62a0a592017-05-22 13:58:53 -0700470 }),
Arnavion02ef13f2017-04-25 00:54:31 -0700471
David Tolnay02a9c6f2018-08-24 18:58:45 -0400472 /// An async block: `async { ... }`.
473 ///
474 /// *This type is available if Syn is built with the `"full"` feature.*
475 pub Async(ExprAsync #full {
476 pub attrs: Vec<Attribute>,
477 pub async_token: Token![async],
478 pub capture: Option<Token![move]>,
479 pub block: Block,
480 }),
481
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400482 /// A try block: `try { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800483 ///
484 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400485 pub TryBlock(ExprTryBlock #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500486 pub attrs: Vec<Attribute>,
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400487 pub try_token: Token![try],
Alex Crichton62a0a592017-05-22 13:58:53 -0700488 pub block: Block,
489 }),
Alex Crichtonfe110462017-06-01 12:49:27 -0700490
David Tolnaya454c8f2018-01-07 01:01:10 -0800491 /// A yield expression: `yield expr`.
David Tolnay461d98e2018-01-07 11:07:19 -0800492 ///
493 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonfe110462017-06-01 12:49:27 -0700494 pub Yield(ExprYield #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500495 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800496 pub yield_token: Token![yield],
Alex Crichtonfe110462017-06-01 12:49:27 -0700497 pub expr: Option<Box<Expr>>,
498 }),
David Tolnay2ae520a2017-12-29 11:19:50 -0500499
David Tolnaya454c8f2018-01-07 01:01:10 -0800500 /// Tokens in expression position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800501 ///
502 /// *This type is available if Syn is built with the `"derive"` or
503 /// `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500504 pub Verbatim(ExprVerbatim #manual_extra_traits {
505 pub tts: TokenStream,
506 }),
507 }
508}
509
510#[cfg(feature = "extra-traits")]
511impl Eq for ExprVerbatim {}
512
513#[cfg(feature = "extra-traits")]
514impl PartialEq for ExprVerbatim {
515 fn eq(&self, other: &Self) -> bool {
516 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
517 }
518}
519
520#[cfg(feature = "extra-traits")]
521impl Hash for ExprVerbatim {
522 fn hash<H>(&self, state: &mut H)
523 where
524 H: Hasher,
525 {
526 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700527 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700528}
529
David Tolnay8c91b882017-12-28 23:04:32 -0500530impl Expr {
David Tolnay631dca62018-09-01 02:46:25 -0700531 #[cfg(all(feature = "parsing", feature = "full"))]
David Tolnay94f06632018-08-31 10:17:17 -0700532 fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
David Tolnay8c91b882017-12-28 23:04:32 -0500533 match *self {
David Tolnay61037c62018-01-05 16:21:03 -0800534 Expr::Box(ExprBox { ref mut attrs, .. })
535 | Expr::InPlace(ExprInPlace { ref mut attrs, .. })
536 | Expr::Array(ExprArray { ref mut attrs, .. })
537 | Expr::Call(ExprCall { ref mut attrs, .. })
538 | Expr::MethodCall(ExprMethodCall { ref mut attrs, .. })
539 | Expr::Tuple(ExprTuple { ref mut attrs, .. })
540 | Expr::Binary(ExprBinary { ref mut attrs, .. })
541 | Expr::Unary(ExprUnary { ref mut attrs, .. })
542 | Expr::Lit(ExprLit { ref mut attrs, .. })
543 | Expr::Cast(ExprCast { ref mut attrs, .. })
544 | Expr::Type(ExprType { ref mut attrs, .. })
David Tolnay9c119122018-09-01 18:47:02 -0700545 | Expr::Let(ExprLet { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800546 | Expr::If(ExprIf { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800547 | Expr::While(ExprWhile { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800548 | Expr::ForLoop(ExprForLoop { ref mut attrs, .. })
549 | Expr::Loop(ExprLoop { ref mut attrs, .. })
550 | Expr::Match(ExprMatch { ref mut attrs, .. })
551 | Expr::Closure(ExprClosure { ref mut attrs, .. })
552 | Expr::Unsafe(ExprUnsafe { ref mut attrs, .. })
553 | Expr::Block(ExprBlock { ref mut attrs, .. })
554 | Expr::Assign(ExprAssign { ref mut attrs, .. })
555 | Expr::AssignOp(ExprAssignOp { ref mut attrs, .. })
556 | Expr::Field(ExprField { ref mut attrs, .. })
557 | Expr::Index(ExprIndex { ref mut attrs, .. })
558 | Expr::Range(ExprRange { ref mut attrs, .. })
559 | Expr::Path(ExprPath { ref mut attrs, .. })
David Tolnay00674ba2018-03-31 18:14:11 +0200560 | Expr::Reference(ExprReference { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800561 | Expr::Break(ExprBreak { ref mut attrs, .. })
562 | Expr::Continue(ExprContinue { ref mut attrs, .. })
563 | Expr::Return(ExprReturn { ref mut attrs, .. })
564 | Expr::Macro(ExprMacro { ref mut attrs, .. })
565 | Expr::Struct(ExprStruct { ref mut attrs, .. })
566 | Expr::Repeat(ExprRepeat { ref mut attrs, .. })
567 | Expr::Paren(ExprParen { ref mut attrs, .. })
568 | Expr::Group(ExprGroup { ref mut attrs, .. })
569 | Expr::Try(ExprTry { ref mut attrs, .. })
David Tolnay02a9c6f2018-08-24 18:58:45 -0400570 | Expr::Async(ExprAsync { ref mut attrs, .. })
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400571 | Expr::TryBlock(ExprTryBlock { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800572 | Expr::Yield(ExprYield { ref mut attrs, .. }) => mem::replace(attrs, new),
David Tolnay10f464a2018-08-30 18:48:55 -0700573 Expr::Verbatim(_) => Vec::new(),
David Tolnay8c91b882017-12-28 23:04:32 -0500574 }
575 }
576}
577
David Tolnay85b69a42017-12-27 20:43:10 -0500578ast_enum! {
579 /// A struct or tuple struct field accessed in a struct literal or field
580 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800581 ///
582 /// *This type is available if Syn is built with the `"derive"` or `"full"`
583 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500584 pub enum Member {
585 /// A named field like `self.x`.
586 Named(Ident),
587 /// An unnamed field like `self.0`.
588 Unnamed(Index),
589 }
590}
591
David Tolnay85b69a42017-12-27 20:43:10 -0500592ast_struct! {
593 /// The index of an unnamed tuple struct field.
David Tolnay461d98e2018-01-07 11:07:19 -0800594 ///
595 /// *This type is available if Syn is built with the `"derive"` or `"full"`
596 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500597 pub struct Index #manual_extra_traits {
598 pub index: u32,
599 pub span: Span,
600 }
601}
602
David Tolnay14982012017-12-29 00:49:51 -0500603impl From<usize> for Index {
604 fn from(index: usize) -> Index {
David Tolnay34071ba2018-05-20 20:00:41 -0700605 assert!(index < u32::max_value() as usize);
David Tolnay14982012017-12-29 00:49:51 -0500606 Index {
607 index: index as u32,
Alex Crichton9a4dca22018-03-28 06:32:19 -0700608 span: Span::call_site(),
David Tolnay14982012017-12-29 00:49:51 -0500609 }
610 }
611}
612
613#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500614impl Eq for Index {}
615
David Tolnay14982012017-12-29 00:49:51 -0500616#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500617impl PartialEq for Index {
618 fn eq(&self, other: &Self) -> bool {
619 self.index == other.index
620 }
621}
622
David Tolnay14982012017-12-29 00:49:51 -0500623#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500624impl Hash for Index {
625 fn hash<H: Hasher>(&self, state: &mut H) {
626 self.index.hash(state);
627 }
628}
629
630#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700631ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800632 /// The `::<>` explicit type parameters passed to a method call:
633 /// `parse::<u64>()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800634 ///
635 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500636 pub struct MethodTurbofish {
637 pub colon2_token: Token![::],
638 pub lt_token: Token![<],
David Tolnayf2cfd722017-12-31 18:02:51 -0500639 pub args: Punctuated<GenericMethodArgument, Token![,]>,
David Tolnayd60cfec2017-12-29 00:21:38 -0500640 pub gt_token: Token![>],
641 }
642}
643
644#[cfg(feature = "full")]
645ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800646 /// An individual generic argument to a method, like `T`.
David Tolnay461d98e2018-01-07 11:07:19 -0800647 ///
648 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500649 pub enum GenericMethodArgument {
David Tolnaya454c8f2018-01-07 01:01:10 -0800650 /// A type argument.
David Tolnayd60cfec2017-12-29 00:21:38 -0500651 Type(Type),
David Tolnaya454c8f2018-01-07 01:01:10 -0800652 /// A const expression. Must be inside of a block.
David Tolnayd60cfec2017-12-29 00:21:38 -0500653 ///
654 /// NOTE: Identity expressions are represented as Type arguments, as
655 /// they are indistinguishable syntactically.
656 Const(Expr),
657 }
658}
659
660#[cfg(feature = "full")]
661ast_struct! {
Alex Crichton62a0a592017-05-22 13:58:53 -0700662 /// A field-value pair in a struct literal.
David Tolnay461d98e2018-01-07 11:07:19 -0800663 ///
664 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700665 pub struct FieldValue {
David Tolnay85b69a42017-12-27 20:43:10 -0500666 /// Attributes tagged on the field.
667 pub attrs: Vec<Attribute>,
668
669 /// Name or index of the field.
670 pub member: Member,
671
David Tolnay5d7098a2017-12-29 01:35:24 -0500672 /// The colon in `Struct { x: x }`. If written in shorthand like
673 /// `Struct { x }`, there is no colon.
David Tolnay85b69a42017-12-27 20:43:10 -0500674 pub colon_token: Option<Token![:]>,
Clar Charrd22b5702017-03-10 15:24:56 -0500675
Alex Crichton62a0a592017-05-22 13:58:53 -0700676 /// Value of the field.
677 pub expr: Expr,
Alex Crichton62a0a592017-05-22 13:58:53 -0700678 }
David Tolnay055a7042016-10-02 19:23:54 -0700679}
680
Michael Layzell734adb42017-06-07 16:58:31 -0400681#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700682ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800683 /// A lifetime labeling a `for`, `while`, or `loop`.
David Tolnay461d98e2018-01-07 11:07:19 -0800684 ///
685 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaybcd498f2017-12-29 12:02:33 -0500686 pub struct Label {
687 pub name: Lifetime,
688 pub colon_token: Token![:],
689 }
690}
691
692#[cfg(feature = "full")]
693ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800694 /// A braced block containing Rust statements.
David Tolnay461d98e2018-01-07 11:07:19 -0800695 ///
696 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700697 pub struct Block {
David Tolnay32954ef2017-12-26 22:43:16 -0500698 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700699 /// Statements in a block
700 pub stmts: Vec<Stmt>,
701 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700702}
703
Michael Layzell734adb42017-06-07 16:58:31 -0400704#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700705ast_enum! {
706 /// A statement, usually ending in a semicolon.
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 enum Stmt {
710 /// A local (let) binding.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800711 Local(Local),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700712
Alex Crichton62a0a592017-05-22 13:58:53 -0700713 /// An item definition.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800714 Item(Item),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700715
Alex Crichton62a0a592017-05-22 13:58:53 -0700716 /// Expr without trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800717 Expr(Expr),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700718
David Tolnaya454c8f2018-01-07 01:01:10 -0800719 /// Expression with trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800720 Semi(Expr, Token![;]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700721 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700722}
723
Michael Layzell734adb42017-06-07 16:58:31 -0400724#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700725ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800726 /// A local `let` binding: `let x: u64 = s.parse()?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800727 ///
728 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700729 pub struct Local {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500730 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800731 pub let_token: Token![let],
David Tolnay5b5b7d22018-03-31 21:05:00 +0200732 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500733 pub ty: Option<(Token![:], Box<Type>)>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500734 pub init: Option<(Token![=], Box<Expr>)>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500735 pub semi_token: Token![;],
Alex Crichton62a0a592017-05-22 13:58:53 -0700736 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700737}
738
Michael Layzell734adb42017-06-07 16:58:31 -0400739#[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700740ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800741 /// A pattern in a local binding, function signature, match expression, or
742 /// various other places.
David Tolnay614a0142018-01-07 10:25:43 -0800743 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800744 /// *This type is available if Syn is built with the `"full"` feature.*
745 ///
David Tolnay614a0142018-01-07 10:25:43 -0800746 /// # Syntax tree enum
747 ///
748 /// This type is a [syntax tree enum].
749 ///
750 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
Alex Crichton62a0a592017-05-22 13:58:53 -0700751 pub enum Pat {
David Tolnaya454c8f2018-01-07 01:01:10 -0800752 /// A pattern that matches any value: `_`.
David Tolnay461d98e2018-01-07 11:07:19 -0800753 ///
754 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700755 pub Wild(PatWild {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800756 pub underscore_token: Token![_],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700757 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700758
David Tolnaya454c8f2018-01-07 01:01:10 -0800759 /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
David Tolnay461d98e2018-01-07 11:07:19 -0800760 ///
761 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700762 pub Ident(PatIdent {
David Tolnay24237fb2017-12-29 02:15:26 -0500763 pub by_ref: Option<Token![ref]>,
764 pub mutability: Option<Token![mut]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700765 pub ident: Ident,
David Tolnay8b4d3022017-12-29 12:11:10 -0500766 pub subpat: Option<(Token![@], Box<Pat>)>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700767 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700768
David Tolnaya454c8f2018-01-07 01:01:10 -0800769 /// A struct or struct variant pattern: `Variant { x, y, .. }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800770 ///
771 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700772 pub Struct(PatStruct {
773 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500774 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500775 pub fields: Punctuated<FieldPat, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800776 pub dot2_token: Option<Token![..]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700777 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700778
David Tolnaya454c8f2018-01-07 01:01:10 -0800779 /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800780 ///
781 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700782 pub TupleStruct(PatTupleStruct {
783 pub path: Path,
784 pub pat: PatTuple,
785 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700786
David Tolnaya454c8f2018-01-07 01:01:10 -0800787 /// A path pattern like `Color::Red`, optionally qualified with a
788 /// self-type.
789 ///
Daniel Muellerd3d71a12019-01-28 06:10:46 -0800790 /// Unqualified path patterns can legally refer to variants, structs,
791 /// constants or associated constants. Qualified path patterns like
David Tolnaya454c8f2018-01-07 01:01:10 -0800792 /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
793 /// associated constants.
David Tolnay461d98e2018-01-07 11:07:19 -0800794 ///
795 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700796 pub Path(PatPath {
797 pub qself: Option<QSelf>,
798 pub path: Path,
799 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700800
David Tolnaya454c8f2018-01-07 01:01:10 -0800801 /// A tuple pattern: `(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800802 ///
803 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700804 pub Tuple(PatTuple {
David Tolnay32954ef2017-12-26 22:43:16 -0500805 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500806 pub front: Punctuated<Pat, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500807 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500808 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500809 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700810 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800811
812 /// A box pattern: `box v`.
David Tolnay461d98e2018-01-07 11:07:19 -0800813 ///
814 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700815 pub Box(PatBox {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800816 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500817 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700818 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800819
820 /// A reference pattern: `&mut (first, second)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800821 ///
822 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700823 pub Ref(PatRef {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800824 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500825 pub mutability: Option<Token![mut]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500826 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700827 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800828
829 /// A literal pattern: `0`.
830 ///
831 /// This holds an `Expr` rather than a `Lit` because negative numbers
832 /// are represented as an `Expr::Unary`.
David Tolnay461d98e2018-01-07 11:07:19 -0800833 ///
834 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700835 pub Lit(PatLit {
836 pub expr: Box<Expr>,
837 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800838
839 /// A range pattern: `1..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800840 ///
841 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700842 pub Range(PatRange {
843 pub lo: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700844 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500845 pub hi: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700846 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800847
848 /// A dynamically sized slice pattern: `[a, b, i.., y, z]`.
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 Slice(PatSlice {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500852 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500853 pub front: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700854 pub middle: Option<Box<Pat>>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500855 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500856 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500857 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700858 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800859
860 /// A macro in expression position.
David Tolnay461d98e2018-01-07 11:07:19 -0800861 ///
862 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay323279a2017-12-29 11:26:32 -0500863 pub Macro(PatMacro {
864 pub mac: Macro,
865 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800866
867 /// Tokens in pattern position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800868 ///
869 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500870 pub Verbatim(PatVerbatim #manual_extra_traits {
871 pub tts: TokenStream,
872 }),
873 }
874}
875
David Tolnayc43b44e2017-12-30 23:55:54 -0500876#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500877impl Eq for PatVerbatim {}
878
David Tolnayc43b44e2017-12-30 23:55:54 -0500879#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500880impl PartialEq for PatVerbatim {
881 fn eq(&self, other: &Self) -> bool {
882 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
883 }
884}
885
David Tolnayc43b44e2017-12-30 23:55:54 -0500886#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500887impl Hash for PatVerbatim {
888 fn hash<H>(&self, state: &mut H)
889 where
890 H: Hasher,
891 {
892 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700893 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700894}
895
Michael Layzell734adb42017-06-07 16:58:31 -0400896#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700897ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800898 /// One arm of a `match` expression: `0...10 => { return true; }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700899 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800900 /// As in:
Alex Crichton62a0a592017-05-22 13:58:53 -0700901 ///
David Tolnay95989db2019-01-01 15:05:57 -0500902 /// ```edition2018
David Tolnaya454c8f2018-01-07 01:01:10 -0800903 /// # fn f() -> bool {
David Tolnaybcf26022017-12-25 22:10:52 -0500904 /// # let n = 0;
Alex Crichton62a0a592017-05-22 13:58:53 -0700905 /// match n {
David Tolnaya454c8f2018-01-07 01:01:10 -0800906 /// 0...10 => {
907 /// return true;
908 /// }
909 /// // ...
David Tolnaybcf26022017-12-25 22:10:52 -0500910 /// # _ => {}
Alex Crichton62a0a592017-05-22 13:58:53 -0700911 /// }
David Tolnaya454c8f2018-01-07 01:01:10 -0800912 /// # false
David Tolnaybcf26022017-12-25 22:10:52 -0500913 /// # }
Alex Crichton62a0a592017-05-22 13:58:53 -0700914 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800915 ///
916 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700917 pub struct Arm {
918 pub attrs: Vec<Attribute>,
David Tolnay18cc4d42018-03-31 18:47:20 +0200919 pub leading_vert: Option<Token![|]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500920 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500921 pub guard: Option<(Token![if], Box<Expr>)>,
David Tolnaydfb91432018-03-31 19:19:44 +0200922 pub fat_arrow_token: Token![=>],
Alex Crichton62a0a592017-05-22 13:58:53 -0700923 pub body: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800924 pub comma: Option<Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700925 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700926}
927
Michael Layzell734adb42017-06-07 16:58:31 -0400928#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700929ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800930 /// Limit types of a range, inclusive or exclusive.
David Tolnay461d98e2018-01-07 11:07:19 -0800931 ///
932 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton2e0229c2017-05-23 09:34:50 -0700933 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700934 pub enum RangeLimits {
David Tolnaya454c8f2018-01-07 01:01:10 -0800935 /// Inclusive at the beginning, exclusive at the end.
David Tolnayf8db7ba2017-11-11 22:52:16 -0800936 HalfOpen(Token![..]),
David Tolnaya454c8f2018-01-07 01:01:10 -0800937 /// Inclusive at the beginning and end.
David Tolnaybe55d7b2017-12-17 23:41:20 -0800938 Closed(Token![..=]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700939 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700940}
941
Michael Layzell734adb42017-06-07 16:58:31 -0400942#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700943ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800944 /// A single field in a struct pattern.
Alex Crichton62a0a592017-05-22 13:58:53 -0700945 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800946 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
947 /// 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 -0800948 ///
949 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700950 pub struct FieldPat {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500951 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -0500952 pub member: Member,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500953 pub colon_token: Option<Token![:]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700954 pub pat: Box<Pat>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700955 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700956}
957
Michael Layzell3936ceb2017-07-08 00:28:36 -0400958#[cfg(any(feature = "parsing", feature = "printing"))]
959#[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -0700960fn requires_terminator(expr: &Expr) -> bool {
David Tolnay01218d12018-08-29 18:13:07 -0700961 // see https://github.com/rust-lang/rust/blob/eb8f2586e/src/libsyntax/parse/classify.rs#L17-L37
David Tolnay8c91b882017-12-28 23:04:32 -0500962 match *expr {
963 Expr::Unsafe(..)
964 | Expr::Block(..)
965 | Expr::If(..)
David Tolnay8c91b882017-12-28 23:04:32 -0500966 | Expr::Match(..)
967 | Expr::While(..)
David Tolnay8c91b882017-12-28 23:04:32 -0500968 | Expr::Loop(..)
969 | Expr::ForLoop(..)
David Tolnay02a9c6f2018-08-24 18:58:45 -0400970 | Expr::Async(..)
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400971 | Expr::TryBlock(..) => false,
Alex Crichton03b30272017-08-28 09:35:24 -0700972 _ => true,
Michael Layzell3936ceb2017-07-08 00:28:36 -0400973 }
974}
975
David Tolnayb9c8e322016-09-23 20:48:37 -0700976#[cfg(feature = "parsing")]
977pub mod parsing {
978 use super::*;
David Tolnayb9c8e322016-09-23 20:48:37 -0700979
Michael Layzell734adb42017-06-07 16:58:31 -0400980 #[cfg(feature = "full")]
David Tolnay94d304f2018-08-30 23:43:53 -0700981 use ext::IdentExt;
David Tolnay10951d52018-08-31 10:27:39 -0700982 use parse::{Parse, ParseStream, Result};
David Tolnay94d304f2018-08-30 23:43:53 -0700983 use path;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700984
David Tolnaybcf26022017-12-25 22:10:52 -0500985 // When we're parsing expressions which occur before blocks, like in an if
986 // statement's condition, we cannot parse a struct literal.
987 //
988 // Struct literals are ambiguous in certain positions
989 // https://github.com/rust-lang/rfcs/pull/92
David Tolnay9389c382018-08-27 09:13:37 -0700990 #[derive(Copy, Clone)]
991 pub struct AllowStruct(bool);
992
David Tolnay01218d12018-08-29 18:13:07 -0700993 #[derive(Copy, Clone, PartialEq, PartialOrd)]
994 enum Precedence {
995 Any,
996 Assign,
David Tolnay01218d12018-08-29 18:13:07 -0700997 Range,
998 Or,
999 And,
1000 Compare,
1001 BitOr,
1002 BitXor,
1003 BitAnd,
1004 Shift,
1005 Arithmetic,
1006 Term,
1007 Cast,
1008 }
1009
1010 impl Precedence {
1011 fn of(op: &BinOp) -> Self {
1012 match *op {
1013 BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic,
1014 BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term,
1015 BinOp::And(_) => Precedence::And,
1016 BinOp::Or(_) => Precedence::Or,
1017 BinOp::BitXor(_) => Precedence::BitXor,
1018 BinOp::BitAnd(_) => Precedence::BitAnd,
1019 BinOp::BitOr(_) => Precedence::BitOr,
1020 BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
David Tolnay73b7ca12018-08-30 21:05:13 -07001021 BinOp::Eq(_)
1022 | BinOp::Lt(_)
1023 | BinOp::Le(_)
1024 | BinOp::Ne(_)
1025 | BinOp::Ge(_)
1026 | BinOp::Gt(_) => Precedence::Compare,
1027 BinOp::AddEq(_)
1028 | BinOp::SubEq(_)
1029 | BinOp::MulEq(_)
1030 | BinOp::DivEq(_)
1031 | BinOp::RemEq(_)
1032 | BinOp::BitXorEq(_)
1033 | BinOp::BitAndEq(_)
1034 | BinOp::BitOrEq(_)
1035 | BinOp::ShlEq(_)
1036 | BinOp::ShrEq(_) => Precedence::Assign,
David Tolnay01218d12018-08-29 18:13:07 -07001037 }
1038 }
1039 }
1040
David Tolnay9389c382018-08-27 09:13:37 -07001041 impl Parse for Expr {
1042 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001043 ambiguous_expr(input, AllowStruct(true))
Alex Crichton954046c2017-05-30 21:49:42 -07001044 }
1045 }
1046
Michael Layzell734adb42017-06-07 16:58:31 -04001047 #[cfg(feature = "full")]
David Tolnay9fb0aed2018-08-27 10:23:12 -07001048 fn expr_no_struct(input: ParseStream) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001049 ambiguous_expr(input, AllowStruct(false))
David Tolnay9fb0aed2018-08-27 10:23:12 -07001050 }
David Tolnayaf2557e2016-10-24 11:52:21 -07001051
David Tolnay01218d12018-08-29 18:13:07 -07001052 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001053 fn parse_expr(
1054 input: ParseStream,
1055 mut lhs: Expr,
1056 allow_struct: AllowStruct,
1057 base: Precedence,
1058 ) -> Result<Expr> {
David Tolnay01218d12018-08-29 18:13:07 -07001059 loop {
David Tolnay73b7ca12018-08-30 21:05:13 -07001060 if input
1061 .fork()
1062 .parse::<BinOp>()
1063 .ok()
1064 .map_or(false, |op| Precedence::of(&op) >= base)
1065 {
David Tolnay01218d12018-08-29 18:13:07 -07001066 let op: BinOp = input.parse()?;
1067 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001068 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001069 loop {
1070 let next = peek_precedence(input);
1071 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001072 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001073 } else {
1074 break;
1075 }
1076 }
David Tolnay90276252018-08-31 10:50:08 -07001077 lhs = if precedence == Precedence::Assign {
1078 Expr::AssignOp(ExprAssignOp {
1079 attrs: Vec::new(),
1080 left: Box::new(lhs),
1081 op: op,
1082 right: Box::new(rhs),
1083 })
1084 } else {
1085 Expr::Binary(ExprBinary {
1086 attrs: Vec::new(),
1087 left: Box::new(lhs),
1088 op: op,
1089 right: Box::new(rhs),
1090 })
1091 };
David Tolnay73b7ca12018-08-30 21:05:13 -07001092 } else if Precedence::Assign >= base
1093 && input.peek(Token![=])
1094 && !input.peek(Token![==])
1095 && !input.peek(Token![=>])
1096 {
David Tolnay01218d12018-08-29 18:13:07 -07001097 let eq_token: Token![=] = input.parse()?;
David Tolnay7d2e1db2018-08-30 11:49:04 -07001098 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001099 loop {
1100 let next = peek_precedence(input);
1101 if next >= Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001102 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001103 } else {
1104 break;
1105 }
1106 }
1107 lhs = Expr::Assign(ExprAssign {
1108 attrs: Vec::new(),
1109 left: Box::new(lhs),
1110 eq_token: eq_token,
1111 right: Box::new(rhs),
1112 });
David Tolnay01218d12018-08-29 18:13:07 -07001113 } else if Precedence::Range >= base && input.peek(Token![..]) {
1114 let limits: RangeLimits = input.parse()?;
1115 let rhs = if input.is_empty()
1116 || input.peek(Token![,])
1117 || input.peek(Token![;])
1118 || !allow_struct.0 && input.peek(token::Brace)
1119 {
1120 None
1121 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001122 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001123 loop {
1124 let next = peek_precedence(input);
1125 if next > Precedence::Range {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001126 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001127 } else {
1128 break;
1129 }
1130 }
1131 Some(rhs)
1132 };
1133 lhs = Expr::Range(ExprRange {
1134 attrs: Vec::new(),
1135 from: Some(Box::new(lhs)),
1136 limits: limits,
1137 to: rhs.map(Box::new),
1138 });
1139 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1140 let as_token: Token![as] = input.parse()?;
1141 let ty = input.call(Type::without_plus)?;
1142 lhs = Expr::Cast(ExprCast {
1143 attrs: Vec::new(),
1144 expr: Box::new(lhs),
1145 as_token: as_token,
1146 ty: Box::new(ty),
1147 });
1148 } else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) {
1149 let colon_token: Token![:] = input.parse()?;
1150 let ty = input.call(Type::without_plus)?;
1151 lhs = Expr::Type(ExprType {
1152 attrs: Vec::new(),
1153 expr: Box::new(lhs),
1154 colon_token: colon_token,
1155 ty: Box::new(ty),
1156 });
1157 } else {
1158 break;
1159 }
1160 }
1161 Ok(lhs)
1162 }
1163
David Tolnay3e541292018-08-30 11:42:15 -07001164 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001165 fn parse_expr(
1166 input: ParseStream,
1167 mut lhs: Expr,
1168 allow_struct: AllowStruct,
1169 base: Precedence,
1170 ) -> Result<Expr> {
David Tolnay3e541292018-08-30 11:42:15 -07001171 loop {
David Tolnay73b7ca12018-08-30 21:05:13 -07001172 if input
1173 .fork()
1174 .parse::<BinOp>()
1175 .ok()
1176 .map_or(false, |op| Precedence::of(&op) >= base)
1177 {
David Tolnay3e541292018-08-30 11:42:15 -07001178 let op: BinOp = input.parse()?;
1179 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001180 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay3e541292018-08-30 11:42:15 -07001181 loop {
1182 let next = peek_precedence(input);
1183 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001184 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay3e541292018-08-30 11:42:15 -07001185 } else {
1186 break;
1187 }
1188 }
1189 lhs = Expr::Binary(ExprBinary {
1190 attrs: Vec::new(),
1191 left: Box::new(lhs),
1192 op: op,
1193 right: Box::new(rhs),
1194 });
1195 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1196 let as_token: Token![as] = input.parse()?;
1197 let ty = input.call(Type::without_plus)?;
1198 lhs = Expr::Cast(ExprCast {
1199 attrs: Vec::new(),
1200 expr: Box::new(lhs),
1201 as_token: as_token,
1202 ty: Box::new(ty),
1203 });
1204 } else {
1205 break;
1206 }
1207 }
1208 Ok(lhs)
1209 }
1210
David Tolnay01218d12018-08-29 18:13:07 -07001211 fn peek_precedence(input: ParseStream) -> Precedence {
1212 if let Ok(op) = input.fork().parse() {
1213 Precedence::of(&op)
David Tolnay3e541292018-08-30 11:42:15 -07001214 } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
David Tolnay01218d12018-08-29 18:13:07 -07001215 Precedence::Assign
David Tolnay01218d12018-08-29 18:13:07 -07001216 } else if input.peek(Token![..]) {
1217 Precedence::Range
1218 } else if input.peek(Token![as]) || input.peek(Token![:]) && !input.peek(Token![::]) {
1219 Precedence::Cast
1220 } else {
1221 Precedence::Any
1222 }
1223 }
1224
David Tolnaybcf26022017-12-25 22:10:52 -05001225 // Parse an arbitrary expression.
David Tolnay73b7ca12018-08-30 21:05:13 -07001226 fn ambiguous_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001227 let lhs = unary_expr(input, allow_struct)?;
1228 parse_expr(input, lhs, allow_struct, Precedence::Any)
Michael Layzellb78f3b52017-06-04 19:03:03 -04001229 }
1230
David Tolnaybcf26022017-12-25 22:10:52 -05001231 // <UnOp> <trailer>
1232 // & <trailer>
1233 // &mut <trailer>
1234 // box <trailer>
Michael Layzell734adb42017-06-07 16:58:31 -04001235 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001236 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay3e22c0b2019-06-23 16:58:38 -07001237 // TODO: optimize using advance_to
David Tolnay377263f2018-08-27 13:48:30 -07001238 let ahead = input.fork();
1239 ahead.call(Attribute::parse_outer)?;
1240 if ahead.peek(Token![&])
1241 || ahead.peek(Token![box])
1242 || ahead.peek(Token![*])
1243 || ahead.peek(Token![!])
1244 || ahead.peek(Token![-])
1245 {
1246 let attrs = input.call(Attribute::parse_outer)?;
1247 if input.peek(Token![&]) {
1248 Ok(Expr::Reference(ExprReference {
1249 attrs: attrs,
1250 and_token: input.parse()?,
1251 mutability: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001252 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001253 }))
1254 } else if input.peek(Token![box]) {
1255 Ok(Expr::Box(ExprBox {
1256 attrs: attrs,
1257 box_token: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001258 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001259 }))
1260 } else {
1261 Ok(Expr::Unary(ExprUnary {
1262 attrs: attrs,
1263 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001264 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001265 }))
1266 }
1267 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001268 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001269 }
1270 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001271
Michael Layzell734adb42017-06-07 16:58:31 -04001272 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001273 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay3e22c0b2019-06-23 16:58:38 -07001274 // TODO: optimize using advance_to
David Tolnay377263f2018-08-27 13:48:30 -07001275 let ahead = input.fork();
1276 ahead.call(Attribute::parse_outer)?;
1277 if ahead.peek(Token![*]) || ahead.peek(Token![!]) || ahead.peek(Token![-]) {
1278 Ok(Expr::Unary(ExprUnary {
1279 attrs: input.call(Attribute::parse_outer)?,
1280 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001281 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001282 }))
1283 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001284 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001285 }
1286 }
Michael Layzell734adb42017-06-07 16:58:31 -04001287
David Tolnaybcf26022017-12-25 22:10:52 -05001288 // <atom> (..<args>) ...
1289 // <atom> . <ident> (..<args>) ...
1290 // <atom> . <ident> ...
1291 // <atom> . <lit> ...
1292 // <atom> [ <expr> ] ...
1293 // <atom> ? ...
Michael Layzell734adb42017-06-07 16:58:31 -04001294 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001295 fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay577fd312018-09-01 02:26:40 -07001296 if input.peek(token::Group) {
1297 return input.call(expr_group).map(Expr::Group);
1298 }
David Tolnay1501f7e2018-08-27 14:21:03 -07001299
David Tolnay577fd312018-09-01 02:26:40 -07001300 let outer_attrs = input.call(Attribute::parse_outer)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001301
David Tolnay577fd312018-09-01 02:26:40 -07001302 let atom = atom_expr(input, allow_struct)?;
1303 let mut e = trailer_helper(input, atom)?;
David Tolnay01218d12018-08-29 18:13:07 -07001304
David Tolnay577fd312018-09-01 02:26:40 -07001305 let inner_attrs = e.replace_attrs(Vec::new());
1306 let attrs = private::attrs(outer_attrs, inner_attrs);
David Tolnay01218d12018-08-29 18:13:07 -07001307 e.replace_attrs(attrs);
1308 Ok(e)
1309 }
1310
1311 #[cfg(feature = "full")]
1312 fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
David Tolnay1501f7e2018-08-27 14:21:03 -07001313 loop {
1314 if input.peek(token::Paren) {
1315 let content;
1316 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001317 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001318 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001319 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001320 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001321 });
1322 } else if input.peek(Token![.]) && !input.peek(Token![..]) {
1323 let dot_token: Token![.] = input.parse()?;
1324 let member: Member = input.parse()?;
1325 let turbofish = if member.is_named() && input.peek(Token![::]) {
1326 Some(MethodTurbofish {
1327 colon2_token: input.parse()?,
1328 lt_token: input.parse()?,
1329 args: {
1330 let mut args = Punctuated::new();
1331 loop {
1332 if input.peek(Token![>]) {
1333 break;
1334 }
David Tolnay310b3262018-08-30 15:33:00 -07001335 let value = input.call(generic_method_argument)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001336 args.push_value(value);
1337 if input.peek(Token![>]) {
1338 break;
1339 }
1340 let punct = input.parse()?;
1341 args.push_punct(punct);
1342 }
1343 args
1344 },
1345 gt_token: input.parse()?,
1346 })
1347 } else {
1348 None
1349 };
1350
1351 if turbofish.is_some() || input.peek(token::Paren) {
1352 if let Member::Named(method) = member {
1353 let content;
1354 e = Expr::MethodCall(ExprMethodCall {
1355 attrs: Vec::new(),
1356 receiver: Box::new(e),
1357 dot_token: dot_token,
1358 method: method,
1359 turbofish: turbofish,
1360 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001361 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001362 });
1363 continue;
1364 }
1365 }
1366
1367 e = Expr::Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -05001368 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001369 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001370 dot_token: dot_token,
David Tolnay85b69a42017-12-27 20:43:10 -05001371 member: member,
David Tolnay1501f7e2018-08-27 14:21:03 -07001372 });
1373 } else if input.peek(token::Bracket) {
1374 let content;
1375 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001376 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001377 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001378 bracket_token: bracketed!(content in input),
1379 index: content.parse()?,
1380 });
1381 } else if input.peek(Token![?]) {
1382 e = Expr::Try(ExprTry {
David Tolnay8c91b882017-12-28 23:04:32 -05001383 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001384 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001385 question_token: input.parse()?,
1386 });
1387 } else {
1388 break;
1389 }
1390 }
David Tolnay1501f7e2018-08-27 14:21:03 -07001391 Ok(e)
1392 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001393
Michael Layzell734adb42017-06-07 16:58:31 -04001394 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001395 fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001396 let mut e = atom_expr(input, allow_struct)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001397
1398 loop {
1399 if input.peek(token::Paren) {
1400 let content;
1401 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001402 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001403 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001404 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001405 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001406 });
1407 } else if input.peek(Token![.]) {
1408 e = Expr::Field(ExprField {
David Tolnayd5147742018-06-30 10:09:52 -07001409 attrs: Vec::new(),
1410 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001411 dot_token: input.parse()?,
1412 member: input.parse()?,
1413 });
1414 } else if input.peek(token::Bracket) {
1415 let content;
1416 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001417 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001418 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001419 bracket_token: bracketed!(content in input),
1420 index: content.parse()?,
1421 });
1422 } else {
1423 break;
1424 }
1425 }
1426
1427 Ok(e)
1428 }
Michael Layzell734adb42017-06-07 16:58:31 -04001429
David Tolnaya454c8f2018-01-07 01:01:10 -08001430 // Parse all atomic expressions which don't have to worry about precedence
David Tolnaybcf26022017-12-25 22:10:52 -05001431 // interactions, as they are fully contained.
Michael Layzell734adb42017-06-07 16:58:31 -04001432 #[cfg(feature = "full")]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001433 fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001434 if input.peek(token::Group) {
David Tolnay577fd312018-09-01 02:26:40 -07001435 input.call(expr_group).map(Expr::Group)
David Tolnay6e1e5052018-08-30 10:21:48 -07001436 } else if input.peek(Lit) {
Peter Hall04f42792019-04-02 16:58:45 +02001437 input.parse().map(Expr::Lit)
David Tolnay6e1e5052018-08-30 10:21:48 -07001438 } else if input.peek(Token![async])
1439 && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
1440 {
David Tolnay577fd312018-09-01 02:26:40 -07001441 input.call(expr_async).map(Expr::Async)
David Tolnay6e1e5052018-08-30 10:21:48 -07001442 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay577fd312018-09-01 02:26:40 -07001443 input.call(expr_try_block).map(Expr::TryBlock)
David Tolnay6e1e5052018-08-30 10:21:48 -07001444 } else if input.peek(Token![|])
1445 || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1446 || input.peek(Token![static])
1447 || input.peek(Token![move])
1448 {
David Tolnay577fd312018-09-01 02:26:40 -07001449 expr_closure(input, allow_struct).map(Expr::Closure)
David Tolnay6e1e5052018-08-30 10:21:48 -07001450 } else if input.peek(Ident)
1451 || input.peek(Token![::])
1452 || input.peek(Token![<])
1453 || input.peek(Token![self])
1454 || input.peek(Token![Self])
1455 || input.peek(Token![super])
1456 || input.peek(Token![extern])
1457 || input.peek(Token![crate])
1458 {
David Tolnay577fd312018-09-01 02:26:40 -07001459 path_or_macro_or_struct(input, allow_struct)
David Tolnay6e1e5052018-08-30 10:21:48 -07001460 } else if input.peek(token::Paren) {
David Tolnay577fd312018-09-01 02:26:40 -07001461 paren_or_tuple(input)
David Tolnay6e1e5052018-08-30 10:21:48 -07001462 } else if input.peek(Token![break]) {
David Tolnay577fd312018-09-01 02:26:40 -07001463 expr_break(input, allow_struct).map(Expr::Break)
David Tolnay6e1e5052018-08-30 10:21:48 -07001464 } else if input.peek(Token![continue]) {
David Tolnay577fd312018-09-01 02:26:40 -07001465 input.call(expr_continue).map(Expr::Continue)
David Tolnay6e1e5052018-08-30 10:21:48 -07001466 } else if input.peek(Token![return]) {
David Tolnay577fd312018-09-01 02:26:40 -07001467 expr_ret(input, allow_struct).map(Expr::Return)
David Tolnay6e1e5052018-08-30 10:21:48 -07001468 } else if input.peek(token::Bracket) {
David Tolnay577fd312018-09-01 02:26:40 -07001469 array_or_repeat(input)
David Tolnay9c119122018-09-01 18:47:02 -07001470 } else if input.peek(Token![let]) {
1471 input.call(expr_let).map(Expr::Let)
David Tolnay6e1e5052018-08-30 10:21:48 -07001472 } else if input.peek(Token![if]) {
Peter Hall04f42792019-04-02 16:58:45 +02001473 input.parse().map(Expr::If)
David Tolnay6e1e5052018-08-30 10:21:48 -07001474 } else if input.peek(Token![while]) {
Peter Hall04f42792019-04-02 16:58:45 +02001475 input.parse().map(Expr::While)
David Tolnay6e1e5052018-08-30 10:21:48 -07001476 } else if input.peek(Token![for]) {
Peter Hall04f42792019-04-02 16:58:45 +02001477 input.parse().map(Expr::ForLoop)
David Tolnay6e1e5052018-08-30 10:21:48 -07001478 } else if input.peek(Token![loop]) {
Peter Hall04f42792019-04-02 16:58:45 +02001479 input.parse().map(Expr::Loop)
David Tolnay6e1e5052018-08-30 10:21:48 -07001480 } else if input.peek(Token![match]) {
Peter Hall55f00f72019-04-02 16:50:57 +02001481 input.parse().map(Expr::Match)
David Tolnay6e1e5052018-08-30 10:21:48 -07001482 } else if input.peek(Token![yield]) {
David Tolnay577fd312018-09-01 02:26:40 -07001483 input.call(expr_yield).map(Expr::Yield)
David Tolnay6e1e5052018-08-30 10:21:48 -07001484 } else if input.peek(Token![unsafe]) {
David Tolnay577fd312018-09-01 02:26:40 -07001485 input.call(expr_unsafe).map(Expr::Unsafe)
David Tolnay7d2e1db2018-08-30 11:49:04 -07001486 } else if input.peek(token::Brace) {
David Tolnay577fd312018-09-01 02:26:40 -07001487 input.call(expr_block).map(Expr::Block)
David Tolnay6e1e5052018-08-30 10:21:48 -07001488 } else if input.peek(Token![..]) {
David Tolnay577fd312018-09-01 02:26:40 -07001489 expr_range(input, allow_struct).map(Expr::Range)
David Tolnay6e1e5052018-08-30 10:21:48 -07001490 } else if input.peek(Lifetime) {
1491 let the_label: Label = input.parse()?;
1492 let mut expr = if input.peek(Token![while]) {
Peter Hall04f42792019-04-02 16:58:45 +02001493 Expr::While(input.parse()?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001494 } else if input.peek(Token![for]) {
Peter Hall04f42792019-04-02 16:58:45 +02001495 Expr::ForLoop(input.parse()?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001496 } else if input.peek(Token![loop]) {
Peter Hall04f42792019-04-02 16:58:45 +02001497 Expr::Loop(input.parse()?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001498 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001499 Expr::Block(input.call(expr_block)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001500 } else {
1501 return Err(input.error("expected loop or block expression"));
1502 };
1503 match expr {
David Tolnay9c119122018-09-01 18:47:02 -07001504 Expr::While(ExprWhile { ref mut label, .. })
David Tolnay73b7ca12018-08-30 21:05:13 -07001505 | Expr::ForLoop(ExprForLoop { ref mut label, .. })
1506 | Expr::Loop(ExprLoop { ref mut label, .. })
1507 | Expr::Block(ExprBlock { ref mut label, .. }) => *label = Some(the_label),
David Tolnay6e1e5052018-08-30 10:21:48 -07001508 _ => unreachable!(),
1509 }
David Tolnay577fd312018-09-01 02:26:40 -07001510 Ok(expr)
David Tolnay6e1e5052018-08-30 10:21:48 -07001511 } else {
David Tolnay577fd312018-09-01 02:26:40 -07001512 Err(input.error("expected expression"))
1513 }
David Tolnay6e1e5052018-08-30 10:21:48 -07001514 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001515
Michael Layzell734adb42017-06-07 16:58:31 -04001516 #[cfg(not(feature = "full"))]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001517 fn atom_expr(input: ParseStream, _allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001518 if input.peek(Lit) {
Peter Hall04f42792019-04-02 16:58:45 +02001519 input.parse().map(Expr::Lit)
David Tolnay6e1e5052018-08-30 10:21:48 -07001520 } else if input.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07001521 input.call(expr_paren).map(Expr::Paren)
David Tolnay6e1e5052018-08-30 10:21:48 -07001522 } else if input.peek(Ident)
1523 || input.peek(Token![::])
1524 || input.peek(Token![<])
1525 || input.peek(Token![self])
1526 || input.peek(Token![Self])
1527 || input.peek(Token![super])
1528 || input.peek(Token![extern])
1529 || input.peek(Token![crate])
1530 {
1531 input.parse().map(Expr::Path)
1532 } else {
1533 Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
1534 }
1535 }
1536
1537 #[cfg(feature = "full")]
1538 fn path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1539 let expr: ExprPath = input.parse()?;
1540 if expr.qself.is_some() {
1541 return Ok(Expr::Path(expr));
1542 }
1543
1544 if input.peek(Token![!]) && !input.peek(Token![!=]) {
1545 let mut contains_arguments = false;
1546 for segment in &expr.path.segments {
1547 match segment.arguments {
1548 PathArguments::None => {}
1549 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
1550 contains_arguments = true;
1551 }
1552 }
1553 }
1554
1555 if !contains_arguments {
1556 let bang_token: Token![!] = input.parse()?;
1557 let (delimiter, tts) = mac::parse_delimiter(input)?;
1558 return Ok(Expr::Macro(ExprMacro {
1559 attrs: Vec::new(),
1560 mac: Macro {
1561 path: expr.path,
1562 bang_token: bang_token,
1563 delimiter: delimiter,
1564 tts: tts,
1565 },
1566 }));
1567 }
1568 }
1569
1570 if allow_struct.0 && input.peek(token::Brace) {
1571 let outer_attrs = Vec::new();
1572 expr_struct_helper(input, outer_attrs, expr.path).map(Expr::Struct)
1573 } else {
1574 Ok(Expr::Path(expr))
1575 }
1576 }
1577
1578 #[cfg(feature = "full")]
1579 fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
1580 let content;
1581 let paren_token = parenthesized!(content in input);
1582 let inner_attrs = content.call(Attribute::parse_inner)?;
1583 if content.is_empty() {
1584 return Ok(Expr::Tuple(ExprTuple {
1585 attrs: inner_attrs,
1586 paren_token: paren_token,
1587 elems: Punctuated::new(),
1588 }));
1589 }
1590
1591 let first: Expr = content.parse()?;
1592 if content.is_empty() {
1593 return Ok(Expr::Paren(ExprParen {
1594 attrs: inner_attrs,
1595 paren_token: paren_token,
1596 expr: Box::new(first),
1597 }));
1598 }
1599
1600 let mut elems = Punctuated::new();
1601 elems.push_value(first);
1602 while !content.is_empty() {
1603 let punct = content.parse()?;
1604 elems.push_punct(punct);
1605 if content.is_empty() {
1606 break;
1607 }
1608 let value = content.parse()?;
1609 elems.push_value(value);
1610 }
1611 Ok(Expr::Tuple(ExprTuple {
1612 attrs: inner_attrs,
1613 paren_token: paren_token,
1614 elems: elems,
1615 }))
1616 }
1617
1618 #[cfg(feature = "full")]
1619 fn array_or_repeat(input: ParseStream) -> Result<Expr> {
1620 let content;
1621 let bracket_token = bracketed!(content in input);
1622 let inner_attrs = content.call(Attribute::parse_inner)?;
1623 if content.is_empty() {
1624 return Ok(Expr::Array(ExprArray {
1625 attrs: inner_attrs,
1626 bracket_token: bracket_token,
1627 elems: Punctuated::new(),
1628 }));
1629 }
1630
1631 let first: Expr = content.parse()?;
1632 if content.is_empty() || content.peek(Token![,]) {
1633 let mut elems = Punctuated::new();
1634 elems.push_value(first);
1635 while !content.is_empty() {
1636 let punct = content.parse()?;
1637 elems.push_punct(punct);
1638 if content.is_empty() {
1639 break;
1640 }
1641 let value = content.parse()?;
1642 elems.push_value(value);
1643 }
1644 Ok(Expr::Array(ExprArray {
1645 attrs: inner_attrs,
1646 bracket_token: bracket_token,
1647 elems: elems,
1648 }))
1649 } else if content.peek(Token![;]) {
1650 let semi_token: Token![;] = content.parse()?;
1651 let len: Expr = content.parse()?;
1652 Ok(Expr::Repeat(ExprRepeat {
1653 attrs: inner_attrs,
1654 bracket_token: bracket_token,
1655 expr: Box::new(first),
1656 semi_token: semi_token,
1657 len: Box::new(len),
1658 }))
1659 } else {
1660 Err(content.error("expected `,` or `;`"))
1661 }
1662 }
Michael Layzell734adb42017-06-07 16:58:31 -04001663
Michael Layzell734adb42017-06-07 16:58:31 -04001664 #[cfg(feature = "full")]
David Tolnay01218d12018-08-29 18:13:07 -07001665 fn expr_early(input: ParseStream) -> Result<Expr> {
1666 let mut attrs = input.call(Attribute::parse_outer)?;
1667 let mut expr = if input.peek(Token![if]) {
Peter Hall04f42792019-04-02 16:58:45 +02001668 Expr::If(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001669 } else if input.peek(Token![while]) {
Peter Hall04f42792019-04-02 16:58:45 +02001670 Expr::While(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001671 } else if input.peek(Token![for]) {
Peter Hall04f42792019-04-02 16:58:45 +02001672 Expr::ForLoop(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001673 } else if input.peek(Token![loop]) {
Peter Hall04f42792019-04-02 16:58:45 +02001674 Expr::Loop(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001675 } else if input.peek(Token![match]) {
Peter Hall55f00f72019-04-02 16:50:57 +02001676 Expr::Match(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001677 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001678 Expr::TryBlock(input.call(expr_try_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001679 } else if input.peek(Token![unsafe]) {
David Tolnay310b3262018-08-30 15:33:00 -07001680 Expr::Unsafe(input.call(expr_unsafe)?)
David Tolnay01218d12018-08-29 18:13:07 -07001681 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001682 Expr::Block(input.call(expr_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001683 } else {
1684 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001685 let mut expr = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001686
1687 attrs.extend(expr.replace_attrs(Vec::new()));
1688 expr.replace_attrs(attrs);
1689
David Tolnay7d2e1db2018-08-30 11:49:04 -07001690 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001691 };
1692
1693 if input.peek(Token![.]) || input.peek(Token![?]) {
1694 expr = trailer_helper(input, expr)?;
1695
1696 attrs.extend(expr.replace_attrs(Vec::new()));
1697 expr.replace_attrs(attrs);
1698
1699 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001700 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001701 }
1702
1703 attrs.extend(expr.replace_attrs(Vec::new()));
1704 expr.replace_attrs(attrs);
1705 Ok(expr)
1706 }
Michael Layzell35418782017-06-07 09:20:25 -04001707
Peter Hall04f42792019-04-02 16:58:45 +02001708 impl Parse for ExprLit {
1709 fn parse(input: ParseStream) -> Result<Self> {
1710 Ok(ExprLit {
1711 attrs: Vec::new(),
1712 lit: input.parse()?,
1713 })
1714 }
David Tolnay8c91b882017-12-28 23:04:32 -05001715 }
1716
1717 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001718 fn expr_group(input: ParseStream) -> Result<ExprGroup> {
David Tolnay10951d52018-08-31 10:27:39 -07001719 let group = private::parse_group(input)?;
David Tolnay310b3262018-08-30 15:33:00 -07001720 Ok(ExprGroup {
1721 attrs: Vec::new(),
David Tolnayf57f76f2018-08-31 10:23:17 -07001722 group_token: group.token,
1723 expr: group.content.parse()?,
David Tolnay310b3262018-08-30 15:33:00 -07001724 })
1725 }
1726
1727 #[cfg(not(feature = "full"))]
1728 fn expr_paren(input: ParseStream) -> Result<ExprParen> {
1729 let content;
1730 Ok(ExprParen {
1731 attrs: Vec::new(),
1732 paren_token: parenthesized!(content in input),
1733 expr: content.parse()?,
1734 })
David Tolnay8c91b882017-12-28 23:04:32 -05001735 }
1736
David Tolnaye98775f2017-12-28 23:17:00 -05001737 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001738 fn generic_method_argument(input: ParseStream) -> Result<GenericMethodArgument> {
David Tolnayd60cfec2017-12-29 00:21:38 -05001739 // TODO parse const generics as well
David Tolnay8db2d662018-08-30 17:40:59 -07001740 input.parse().map(GenericMethodArgument::Type)
David Tolnayd60cfec2017-12-29 00:21:38 -05001741 }
1742
1743 #[cfg(feature = "full")]
David Tolnay9c119122018-09-01 18:47:02 -07001744 fn expr_let(input: ParseStream) -> Result<ExprLet> {
1745 Ok(ExprLet {
David Tolnay310b3262018-08-30 15:33:00 -07001746 attrs: Vec::new(),
David Tolnay310b3262018-08-30 15:33:00 -07001747 let_token: input.parse()?,
1748 pats: {
1749 let mut pats = Punctuated::new();
David Tolnaye2a6ffa2019-01-15 20:57:02 -08001750 input.parse::<Option<Token![|]>>()?;
David Tolnay310b3262018-08-30 15:33:00 -07001751 let value: Pat = input.parse()?;
1752 pats.push_value(value);
David Tolnay73b7ca12018-08-30 21:05:13 -07001753 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
David Tolnay310b3262018-08-30 15:33:00 -07001754 let punct = input.parse()?;
1755 pats.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07001756 let value: Pat = input.parse()?;
1757 pats.push_value(value);
David Tolnay310b3262018-08-30 15:33:00 -07001758 }
1759 pats
1760 },
1761 eq_token: input.parse()?,
1762 expr: Box::new(input.call(expr_no_struct)?),
David Tolnay310b3262018-08-30 15:33:00 -07001763 })
David Tolnay29f9ce12016-10-02 20:58:40 -07001764 }
1765
Michael Layzell734adb42017-06-07 16:58:31 -04001766 #[cfg(feature = "full")]
Peter Hall04f42792019-04-02 16:58:45 +02001767 impl Parse for ExprIf {
1768 fn parse(input: ParseStream) -> Result<Self> {
1769 Ok(ExprIf {
1770 attrs: Vec::new(),
1771 if_token: input.parse()?,
1772 cond: Box::new(input.call(expr_no_struct)?),
1773 then_branch: input.parse()?,
1774 else_branch: {
1775 if input.peek(Token![else]) {
1776 Some(input.call(else_block)?)
1777 } else {
1778 None
1779 }
1780 },
1781 })
1782 }
Alex Crichton954046c2017-05-30 21:49:42 -07001783 }
David Tolnaybb6feae2016-10-02 21:25:20 -07001784
Michael Layzell734adb42017-06-07 16:58:31 -04001785 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001786 fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
1787 let else_token: Token![else] = input.parse()?;
1788
1789 let lookahead = input.lookahead1();
1790 let else_branch = if input.peek(Token![if]) {
Peter Hall04f42792019-04-02 16:58:45 +02001791 input.parse().map(Expr::If)?
David Tolnay60291082018-08-28 09:54:49 -07001792 } else if input.peek(token::Brace) {
1793 Expr::Block(ExprBlock {
1794 attrs: Vec::new(),
1795 label: None,
1796 block: input.parse()?,
1797 })
1798 } else {
1799 return Err(lookahead.error());
1800 };
1801
1802 Ok((else_token, Box::new(else_branch)))
1803 }
David Tolnay939766a2016-09-23 23:48:12 -07001804
Michael Layzell734adb42017-06-07 16:58:31 -04001805 #[cfg(feature = "full")]
Peter Hall04f42792019-04-02 16:58:45 +02001806 impl Parse for ExprForLoop {
1807 fn parse(input: ParseStream) -> Result<Self> {
1808 let label: Option<Label> = input.parse()?;
1809 let for_token: Token![for] = input.parse()?;
1810 let pat: Pat = input.parse()?;
1811 let in_token: Token![in] = input.parse()?;
1812 let expr: Expr = input.call(expr_no_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07001813
Peter Hall04f42792019-04-02 16:58:45 +02001814 let content;
1815 let brace_token = braced!(content in input);
1816 let inner_attrs = content.call(Attribute::parse_inner)?;
1817 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07001818
Peter Hall04f42792019-04-02 16:58:45 +02001819 Ok(ExprForLoop {
1820 attrs: inner_attrs,
1821 label: label,
1822 for_token: for_token,
1823 pat: Box::new(pat),
1824 in_token: in_token,
1825 expr: Box::new(expr),
1826 body: Block {
1827 brace_token: brace_token,
1828 stmts: stmts,
1829 },
1830 })
1831 }
Alex Crichton954046c2017-05-30 21:49:42 -07001832 }
David Tolnay1978c672016-10-27 22:05:52 -07001833
Michael Layzell734adb42017-06-07 16:58:31 -04001834 #[cfg(feature = "full")]
Peter Hall04f42792019-04-02 16:58:45 +02001835 impl Parse for ExprLoop {
1836 fn parse(input: ParseStream) -> Result<Self> {
1837 let label: Option<Label> = input.parse()?;
1838 let loop_token: Token![loop] = input.parse()?;
David Tolnay310b3262018-08-30 15:33:00 -07001839
Peter Hall04f42792019-04-02 16:58:45 +02001840 let content;
1841 let brace_token = braced!(content in input);
1842 let inner_attrs = content.call(Attribute::parse_inner)?;
1843 let stmts = content.call(Block::parse_within)?;
David Tolnay310b3262018-08-30 15:33:00 -07001844
Peter Hall04f42792019-04-02 16:58:45 +02001845 Ok(ExprLoop {
1846 attrs: inner_attrs,
1847 label: label,
1848 loop_token: loop_token,
1849 body: Block {
1850 brace_token: brace_token,
1851 stmts: stmts,
1852 },
1853 })
1854 }
Alex Crichton954046c2017-05-30 21:49:42 -07001855 }
Arnavion02ef13f2017-04-25 00:54:31 -07001856
Michael Layzell734adb42017-06-07 16:58:31 -04001857 #[cfg(feature = "full")]
Peter Hall55f00f72019-04-02 16:50:57 +02001858 impl Parse for ExprMatch {
1859 fn parse(input: ParseStream) -> Result<Self> {
1860 let match_token: Token![match] = input.parse()?;
1861 let expr = expr_no_struct(input)?;
David Tolnay310b3262018-08-30 15:33:00 -07001862
Peter Hall55f00f72019-04-02 16:50:57 +02001863 let content;
1864 let brace_token = braced!(content in input);
1865 let inner_attrs = content.call(Attribute::parse_inner)?;
David Tolnay310b3262018-08-30 15:33:00 -07001866
Peter Hall55f00f72019-04-02 16:50:57 +02001867 let mut arms = Vec::new();
1868 while !content.is_empty() {
1869 arms.push(content.call(Arm::parse)?);
1870 }
1871
1872 Ok(ExprMatch {
1873 attrs: inner_attrs,
1874 match_token: match_token,
1875 expr: Box::new(expr),
1876 brace_token: brace_token,
1877 arms: arms,
1878 })
David Tolnay310b3262018-08-30 15:33:00 -07001879 }
David Tolnay310b3262018-08-30 15:33:00 -07001880 }
1881
David Tolnaye52022b2019-05-25 00:26:54 -07001882 #[cfg(all(feature = "full", feature = "printing"))]
1883 impl Parse for ExprInPlace {
1884 fn parse(input: ParseStream) -> Result<Self> {
1885 let msg = "placement expression has been removed from Rust and is no longer parsed";
1886 Err(input.error(msg))
1887 }
1888 }
1889
bstriecde20e62019-05-05 13:29:15 -04001890 macro_rules! impl_by_parsing_expr {
David Tolnaye957eb62019-05-07 22:02:51 -07001891 (
1892 $(
1893 $expr_type:ty, $variant:ident, $msg:expr,
1894 )*
1895 ) => {
1896 $(
1897 #[cfg(all(feature = "full", feature = "printing"))]
1898 impl Parse for $expr_type {
1899 fn parse(input: ParseStream) -> Result<Self> {
1900 let mut expr: Expr = input.parse()?;
1901 loop {
1902 match expr {
1903 Expr::$variant(inner) => return Ok(inner),
1904 Expr::Group(next) => expr = *next.expr,
1905 _ => return Err(Error::new_spanned(expr, $msg)),
1906 }
bstrie1626c372019-05-05 13:44:57 -04001907 }
bstrieb7f8aaf2019-04-30 20:20:25 -04001908 }
1909 }
David Tolnaye957eb62019-05-07 22:02:51 -07001910 )*
David Tolnaya58223d2019-05-07 21:58:15 -07001911 };
bstrie7b4f52d2019-04-30 18:44:21 -04001912 }
1913
David Tolnaye957eb62019-05-07 22:02:51 -07001914 impl_by_parsing_expr! {
1915 ExprBox, Box, "expected box expression",
David Tolnaye957eb62019-05-07 22:02:51 -07001916 ExprArray, Array, "expected slice literal expression",
1917 ExprCall, Call, "expected function call expression",
1918 ExprMethodCall, MethodCall, "expected method call expression",
1919 ExprTuple, Tuple, "expected tuple expression",
1920 ExprBinary, Binary, "expected binary operation",
1921 ExprUnary, Unary, "expected unary operation",
1922 ExprCast, Cast, "expected cast expression",
1923 ExprType, Type, "expected type ascription expression",
1924 ExprLet, Let, "expected let guard",
1925 ExprClosure, Closure, "expected closure expression",
1926 ExprUnsafe, Unsafe, "expected unsafe block",
1927 ExprBlock, Block, "expected blocked scope",
1928 ExprAssign, Assign, "expected assignment expression",
1929 ExprAssignOp, AssignOp, "expected compound assignment expression",
1930 ExprField, Field, "expected struct field access",
1931 ExprIndex, Index, "expected indexing expression",
1932 ExprRange, Range, "expected range expression",
1933 ExprReference, Reference, "expected referencing operation",
1934 ExprBreak, Break, "expected break expression",
1935 ExprContinue, Continue, "expected continue expression",
1936 ExprReturn, Return, "expected return expression",
1937 ExprMacro, Macro, "expected macro invocation expression",
1938 ExprStruct, Struct, "expected struct literal expression",
1939 ExprRepeat, Repeat, "expected array literal constructed from one repeated element",
1940 ExprParen, Paren, "expected parenthesized expression",
1941 ExprTry, Try, "expected try expression",
1942 ExprAsync, Async, "expected async block",
1943 ExprTryBlock, TryBlock, "expected try block",
1944 ExprYield, Yield, "expected yield expression",
1945 }
bstrieb7f8aaf2019-04-30 20:20:25 -04001946
David Tolnay310b3262018-08-30 15:33:00 -07001947 #[cfg(feature = "full")]
1948 fn expr_try_block(input: ParseStream) -> Result<ExprTryBlock> {
1949 Ok(ExprTryBlock {
1950 attrs: Vec::new(),
1951 try_token: input.parse()?,
1952 block: input.parse()?,
1953 })
1954 }
1955
1956 #[cfg(feature = "full")]
1957 fn expr_yield(input: ParseStream) -> Result<ExprYield> {
1958 Ok(ExprYield {
1959 attrs: Vec::new(),
1960 yield_token: input.parse()?,
1961 expr: {
1962 if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
1963 Some(input.parse()?)
1964 } else {
1965 None
1966 }
1967 },
1968 })
1969 }
1970
1971 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001972 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
David Tolnay60291082018-08-28 09:54:49 -07001973 let asyncness: Option<Token![async]> = input.parse()?;
1974 let movability: Option<Token![static]> = if asyncness.is_none() {
1975 input.parse()?
1976 } else {
1977 None
1978 };
1979 let capture: Option<Token![move]> = input.parse()?;
1980 let or1_token: Token![|] = input.parse()?;
1981
1982 let mut inputs = Punctuated::new();
1983 loop {
1984 if input.peek(Token![|]) {
1985 break;
1986 }
1987 let value = fn_arg(input)?;
1988 inputs.push_value(value);
1989 if input.peek(Token![|]) {
1990 break;
1991 }
1992 let punct: Token![,] = input.parse()?;
1993 inputs.push_punct(punct);
1994 }
1995
1996 let or2_token: Token![|] = input.parse()?;
1997
1998 let (output, body) = if input.peek(Token![->]) {
1999 let arrow_token: Token![->] = input.parse()?;
2000 let ty: Type = input.parse()?;
2001 let body: Block = input.parse()?;
2002 let output = ReturnType::Type(arrow_token, Box::new(ty));
2003 let block = Expr::Block(ExprBlock {
2004 attrs: Vec::new(),
2005 label: None,
2006 block: body,
2007 });
2008 (output, block)
2009 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002010 let body = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002011 (ReturnType::Default, body)
2012 };
2013
2014 Ok(ExprClosure {
David Tolnay310b3262018-08-30 15:33:00 -07002015 attrs: Vec::new(),
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002016 asyncness: asyncness,
2017 movability: movability,
2018 capture: capture,
David Tolnay60291082018-08-28 09:54:49 -07002019 or1_token: or1_token,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002020 inputs: inputs,
David Tolnay60291082018-08-28 09:54:49 -07002021 or2_token: or2_token,
2022 output: output,
2023 body: Box::new(body),
2024 })
David Tolnay02a9c6f2018-08-24 18:58:45 -04002025 }
Yusuke Sasaki851062f2018-08-01 06:28:28 +09002026
2027 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002028 fn expr_async(input: ParseStream) -> Result<ExprAsync> {
2029 Ok(ExprAsync {
2030 attrs: Vec::new(),
2031 async_token: input.parse()?,
2032 capture: input.parse()?,
2033 block: input.parse()?,
2034 })
David Tolnay60291082018-08-28 09:54:49 -07002035 }
Gregory Katz3e562cc2016-09-28 18:33:02 -04002036
Michael Layzell734adb42017-06-07 16:58:31 -04002037 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002038 fn fn_arg(input: ParseStream) -> Result<FnArg> {
2039 let pat: Pat = input.parse()?;
2040
2041 if input.peek(Token![:]) {
2042 Ok(FnArg::Captured(ArgCaptured {
2043 pat: pat,
2044 colon_token: input.parse()?,
2045 ty: input.parse()?,
2046 }))
2047 } else {
2048 Ok(FnArg::Inferred(pat))
2049 }
2050 }
2051
2052 #[cfg(feature = "full")]
Peter Hall04f42792019-04-02 16:58:45 +02002053 impl Parse for ExprWhile {
2054 fn parse(input: ParseStream) -> Result<Self> {
2055 let label: Option<Label> = input.parse()?;
2056 let while_token: Token![while] = input.parse()?;
2057 let cond = expr_no_struct(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002058
Peter Hall04f42792019-04-02 16:58:45 +02002059 let content;
2060 let brace_token = braced!(content in input);
2061 let inner_attrs = content.call(Attribute::parse_inner)?;
2062 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002063
Peter Hall04f42792019-04-02 16:58:45 +02002064 Ok(ExprWhile {
2065 attrs: inner_attrs,
2066 label: label,
2067 while_token: while_token,
2068 cond: Box::new(cond),
2069 body: Block {
2070 brace_token: brace_token,
2071 stmts: stmts,
2072 },
2073 })
2074 }
Alex Crichton954046c2017-05-30 21:49:42 -07002075 }
2076
Michael Layzell734adb42017-06-07 16:58:31 -04002077 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002078 impl Parse for Label {
2079 fn parse(input: ParseStream) -> Result<Self> {
2080 Ok(Label {
2081 name: input.parse()?,
2082 colon_token: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04002083 })
David Tolnay60291082018-08-28 09:54:49 -07002084 }
Alex Crichton954046c2017-05-30 21:49:42 -07002085 }
2086
Michael Layzell734adb42017-06-07 16:58:31 -04002087 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002088 impl Parse for Option<Label> {
2089 fn parse(input: ParseStream) -> Result<Self> {
2090 if input.peek(Lifetime) {
2091 input.parse().map(Some)
2092 } else {
2093 Ok(None)
2094 }
2095 }
2096 }
2097
2098 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002099 fn expr_continue(input: ParseStream) -> Result<ExprContinue> {
2100 Ok(ExprContinue {
2101 attrs: Vec::new(),
2102 continue_token: input.parse()?,
2103 label: input.parse()?,
2104 })
Alex Crichton954046c2017-05-30 21:49:42 -07002105 }
Gregory Katzfd6935d2016-09-30 22:51:25 -04002106
Michael Layzell734adb42017-06-07 16:58:31 -04002107 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002108 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2109 Ok(ExprBreak {
David Tolnay310b3262018-08-30 15:33:00 -07002110 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002111 break_token: input.parse()?,
2112 label: input.parse()?,
2113 expr: {
2114 if input.is_empty()
2115 || input.peek(Token![,])
2116 || input.peek(Token![;])
2117 || !allow_struct.0 && input.peek(token::Brace)
2118 {
2119 None
2120 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002121 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002122 Some(Box::new(expr))
Michael Layzell92639a52017-06-01 00:07:44 -04002123 }
David Tolnay60291082018-08-28 09:54:49 -07002124 },
2125 })
Alex Crichton954046c2017-05-30 21:49:42 -07002126 }
2127
Michael Layzell734adb42017-06-07 16:58:31 -04002128 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002129 fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
2130 Ok(ExprReturn {
David Tolnay310b3262018-08-30 15:33:00 -07002131 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002132 return_token: input.parse()?,
2133 expr: {
2134 if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
2135 None
2136 } else {
2137 // NOTE: return is greedy and eats blocks after it even when in a
2138 // position where structs are not allowed, such as in if statement
2139 // conditions. For example:
2140 //
2141 // if return { println!("A") } {} // Prints "A"
David Tolnay7d2e1db2018-08-30 11:49:04 -07002142 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002143 Some(Box::new(expr))
2144 }
2145 },
2146 })
2147 }
2148
2149 #[cfg(feature = "full")]
David Tolnaya7aa4ee2018-09-02 12:15:00 -07002150 impl Parse for FieldValue {
2151 fn parse(input: ParseStream) -> Result<Self> {
2152 let member: Member = input.parse()?;
2153 let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
2154 let colon_token: Token![:] = input.parse()?;
2155 let value: Expr = input.parse()?;
2156 (Some(colon_token), value)
2157 } else if let Member::Named(ref ident) = member {
2158 let value = Expr::Path(ExprPath {
2159 attrs: Vec::new(),
2160 qself: None,
2161 path: Path::from(ident.clone()),
2162 });
2163 (None, value)
2164 } else {
2165 unreachable!()
2166 };
2167
2168 Ok(FieldValue {
2169 attrs: Vec::new(),
2170 member: member,
2171 colon_token: colon_token,
2172 expr: value,
2173 })
2174 }
2175 }
2176
2177 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07002178 fn expr_struct_helper(
2179 input: ParseStream,
2180 outer_attrs: Vec<Attribute>,
2181 path: Path,
2182 ) -> Result<ExprStruct> {
David Tolnay6e1e5052018-08-30 10:21:48 -07002183 let content;
2184 let brace_token = braced!(content in input);
2185 let inner_attrs = content.call(Attribute::parse_inner)?;
David Tolnay60291082018-08-28 09:54:49 -07002186
David Tolnay6e1e5052018-08-30 10:21:48 -07002187 let mut fields = Punctuated::new();
2188 loop {
2189 let attrs = content.call(Attribute::parse_outer)?;
David Tolnay3e22c0b2019-06-23 16:58:38 -07002190 // TODO: optimize using advance_to
David Tolnay6e1e5052018-08-30 10:21:48 -07002191 if content.fork().parse::<Member>().is_err() {
2192 if attrs.is_empty() {
David Tolnay60291082018-08-28 09:54:49 -07002193 break;
David Tolnay6e1e5052018-08-30 10:21:48 -07002194 } else {
2195 return Err(content.error("expected struct field"));
David Tolnay60291082018-08-28 09:54:49 -07002196 }
David Tolnay60291082018-08-28 09:54:49 -07002197 }
2198
David Tolnay6e1e5052018-08-30 10:21:48 -07002199 fields.push(FieldValue {
2200 attrs: attrs,
David Tolnaya7aa4ee2018-09-02 12:15:00 -07002201 ..content.parse()?
David Tolnay6e1e5052018-08-30 10:21:48 -07002202 });
2203
2204 if !content.peek(Token![,]) {
2205 break;
2206 }
2207 let punct: Token![,] = content.parse()?;
2208 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002209 }
David Tolnay6e1e5052018-08-30 10:21:48 -07002210
2211 let (dot2_token, rest) = if fields.empty_or_trailing() && content.peek(Token![..]) {
2212 let dot2_token: Token![..] = content.parse()?;
2213 let rest: Expr = content.parse()?;
2214 (Some(dot2_token), Some(Box::new(rest)))
2215 } else {
2216 (None, None)
2217 };
2218
2219 Ok(ExprStruct {
David Tolnayb5f6fc02018-09-01 02:18:50 -07002220 attrs: private::attrs(outer_attrs, inner_attrs),
David Tolnay6e1e5052018-08-30 10:21:48 -07002221 brace_token: brace_token,
2222 path: path,
2223 fields: fields,
2224 dot2_token: dot2_token,
2225 rest: rest,
2226 })
Alex Crichton954046c2017-05-30 21:49:42 -07002227 }
David Tolnay055a7042016-10-02 19:23:54 -07002228
Michael Layzell734adb42017-06-07 16:58:31 -04002229 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002230 fn expr_unsafe(input: ParseStream) -> Result<ExprUnsafe> {
2231 let unsafe_token: Token![unsafe] = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002232
David Tolnay310b3262018-08-30 15:33:00 -07002233 let content;
2234 let brace_token = braced!(content in input);
2235 let inner_attrs = content.call(Attribute::parse_inner)?;
2236 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002237
David Tolnay310b3262018-08-30 15:33:00 -07002238 Ok(ExprUnsafe {
2239 attrs: inner_attrs,
2240 unsafe_token: unsafe_token,
2241 block: Block {
2242 brace_token: brace_token,
2243 stmts: stmts,
2244 },
2245 })
Alex Crichton954046c2017-05-30 21:49:42 -07002246 }
David Tolnay055a7042016-10-02 19:23:54 -07002247
Michael Layzell734adb42017-06-07 16:58:31 -04002248 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002249 pub fn expr_block(input: ParseStream) -> Result<ExprBlock> {
2250 let label: Option<Label> = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002251
David Tolnay310b3262018-08-30 15:33:00 -07002252 let content;
2253 let brace_token = braced!(content in input);
2254 let inner_attrs = content.call(Attribute::parse_inner)?;
2255 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002256
David Tolnay310b3262018-08-30 15:33:00 -07002257 Ok(ExprBlock {
2258 attrs: inner_attrs,
2259 label: label,
2260 block: Block {
2261 brace_token: brace_token,
2262 stmts: stmts,
2263 },
2264 })
Alex Crichton954046c2017-05-30 21:49:42 -07002265 }
David Tolnay89e05672016-10-02 14:39:42 -07002266
Michael Layzell734adb42017-06-07 16:58:31 -04002267 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002268 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2269 Ok(ExprRange {
David Tolnay8c91b882017-12-28 23:04:32 -05002270 attrs: Vec::new(),
2271 from: None,
David Tolnay60291082018-08-28 09:54:49 -07002272 limits: input.parse()?,
2273 to: {
2274 if input.is_empty()
2275 || input.peek(Token![,])
2276 || input.peek(Token![;])
2277 || !allow_struct.0 && input.peek(token::Brace)
2278 {
2279 None
2280 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002281 let to = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002282 Some(Box::new(to))
2283 }
2284 },
2285 })
2286 }
David Tolnay438c9052016-10-07 23:24:48 -07002287
Michael Layzell734adb42017-06-07 16:58:31 -04002288 #[cfg(feature = "full")]
David Tolnayc4c631e2018-08-27 10:44:37 -07002289 impl Parse for RangeLimits {
2290 fn parse(input: ParseStream) -> Result<Self> {
2291 let lookahead = input.lookahead1();
2292 if lookahead.peek(Token![..=]) {
2293 input.parse().map(RangeLimits::Closed)
2294 } else if lookahead.peek(Token![...]) {
2295 let dot3: Token![...] = input.parse()?;
2296 Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2297 } else if lookahead.peek(Token![..]) {
2298 input.parse().map(RangeLimits::HalfOpen)
2299 } else {
2300 Err(lookahead.error())
2301 }
2302 }
Alex Crichton954046c2017-05-30 21:49:42 -07002303 }
David Tolnay438c9052016-10-07 23:24:48 -07002304
David Tolnay60291082018-08-28 09:54:49 -07002305 impl Parse for ExprPath {
2306 fn parse(input: ParseStream) -> Result<Self> {
2307 #[cfg(not(feature = "full"))]
2308 let attrs = Vec::new();
2309 #[cfg(feature = "full")]
2310 let attrs = input.call(Attribute::parse_outer)?;
David Tolnayeb981bb2018-07-21 19:31:38 -07002311
David Tolnay60291082018-08-28 09:54:49 -07002312 let (qself, path) = path::parsing::qpath(input, true)?;
2313
2314 Ok(ExprPath {
David Tolnay73c9b522018-07-21 15:58:40 -07002315 attrs: attrs,
David Tolnay60291082018-08-28 09:54:49 -07002316 qself: qself,
2317 path: path,
Michael Layzell92639a52017-06-01 00:07:44 -04002318 })
David Tolnay60291082018-08-28 09:54:49 -07002319 }
Alex Crichton954046c2017-05-30 21:49:42 -07002320 }
David Tolnay42602292016-10-01 22:25:45 -07002321
Michael Layzell734adb42017-06-07 16:58:31 -04002322 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002323 impl Parse for Block {
2324 fn parse(input: ParseStream) -> Result<Self> {
2325 let content;
2326 Ok(Block {
2327 brace_token: braced!(content in input),
2328 stmts: content.call(Block::parse_within)?,
Michael Layzell92639a52017-06-01 00:07:44 -04002329 })
David Tolnay60291082018-08-28 09:54:49 -07002330 }
Alex Crichton954046c2017-05-30 21:49:42 -07002331 }
David Tolnay939766a2016-09-23 23:48:12 -07002332
Michael Layzell734adb42017-06-07 16:58:31 -04002333 #[cfg(feature = "full")]
Alex Crichton954046c2017-05-30 21:49:42 -07002334 impl Block {
David Tolnay6b457252018-09-01 15:55:47 -07002335 /// Parse the body of a block as zero or more statements, possibly
2336 /// including one trailing expression.
2337 ///
David Tolnay206edfb2018-09-01 16:02:20 -07002338 /// *This function is available if Syn is built with the `"parsing"`
2339 /// feature.*
2340 ///
David Tolnay6b457252018-09-01 15:55:47 -07002341 /// # Example
2342 ///
David Tolnay95989db2019-01-01 15:05:57 -05002343 /// ```edition2018
David Tolnayfd5b1172018-12-31 17:54:36 -05002344 /// use syn::{braced, token, Attribute, Block, Ident, Result, Stmt, Token};
David Tolnay67fea042018-11-24 14:50:20 -08002345 /// use syn::parse::{Parse, ParseStream};
David Tolnay6b457252018-09-01 15:55:47 -07002346 ///
2347 /// // Parse a function with no generics or parameter list.
David Tolnaye7ea1652018-09-02 09:11:54 -07002348 /// //
2349 /// // fn playground {
2350 /// // let mut x = 1;
2351 /// // x += 1;
2352 /// // println!("{}", x);
2353 /// // }
David Tolnay6b457252018-09-01 15:55:47 -07002354 /// struct MiniFunction {
2355 /// attrs: Vec<Attribute>,
2356 /// fn_token: Token![fn],
2357 /// name: Ident,
2358 /// brace_token: token::Brace,
2359 /// stmts: Vec<Stmt>,
2360 /// }
2361 ///
2362 /// impl Parse for MiniFunction {
2363 /// fn parse(input: ParseStream) -> Result<Self> {
2364 /// let outer_attrs = input.call(Attribute::parse_outer)?;
2365 /// let fn_token: Token![fn] = input.parse()?;
2366 /// let name: Ident = input.parse()?;
2367 ///
2368 /// let content;
2369 /// let brace_token = braced!(content in input);
2370 /// let inner_attrs = content.call(Attribute::parse_inner)?;
2371 /// let stmts = content.call(Block::parse_within)?;
2372 ///
2373 /// Ok(MiniFunction {
2374 /// attrs: {
2375 /// let mut attrs = outer_attrs;
2376 /// attrs.extend(inner_attrs);
2377 /// attrs
2378 /// },
2379 /// fn_token: fn_token,
2380 /// name: name,
2381 /// brace_token: brace_token,
2382 /// stmts: stmts,
2383 /// })
2384 /// }
2385 /// }
David Tolnay6b457252018-09-01 15:55:47 -07002386 /// ```
David Tolnay9389c382018-08-27 09:13:37 -07002387 pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002388 let mut stmts = Vec::new();
David Tolnay7158c5f2018-08-30 17:28:34 -07002389 loop {
2390 while input.peek(Token![;]) {
2391 input.parse::<Token![;]>()?;
Michael Layzell92639a52017-06-01 00:07:44 -04002392 }
David Tolnay7158c5f2018-08-30 17:28:34 -07002393 if input.is_empty() {
2394 break;
2395 }
2396 let s = parse_stmt(input, true)?;
2397 let requires_semicolon = if let Stmt::Expr(ref s) = s {
2398 requires_terminator(s)
2399 } else {
2400 false
2401 };
David Tolnaye532d6b2018-08-30 16:55:01 -07002402 stmts.push(s);
David Tolnay7158c5f2018-08-30 17:28:34 -07002403 if input.is_empty() {
2404 break;
2405 } else if requires_semicolon {
2406 return Err(input.error("unexpected token"));
2407 }
David Tolnaye532d6b2018-08-30 16:55:01 -07002408 }
2409 Ok(stmts)
2410 }
Alex Crichton954046c2017-05-30 21:49:42 -07002411 }
2412
Michael Layzell734adb42017-06-07 16:58:31 -04002413 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002414 impl Parse for Stmt {
2415 fn parse(input: ParseStream) -> Result<Self> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002416 parse_stmt(input, false)
2417 }
2418 }
David Tolnay939766a2016-09-23 23:48:12 -07002419
David Tolnaye532d6b2018-08-30 16:55:01 -07002420 #[cfg(feature = "full")]
2421 fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
David Tolnay3e22c0b2019-06-23 16:58:38 -07002422 // TODO: optimize using advance_to
David Tolnaye532d6b2018-08-30 16:55:01 -07002423 let ahead = input.fork();
2424 ahead.call(Attribute::parse_outer)?;
2425
David Tolnaye532d6b2018-08-30 16:55:01 -07002426 if {
2427 let ahead = ahead.fork();
2428 // Only parse braces here; paren and bracket will get parsed as
2429 // expression statements
2430 ahead.call(Path::parse_mod_style).is_ok()
2431 && ahead.parse::<Token![!]>().is_ok()
2432 && (ahead.peek(token::Brace) || ahead.peek(Ident))
2433 } {
2434 stmt_mac(input)
2435 } else if ahead.peek(Token![let]) {
2436 stmt_local(input).map(Stmt::Local)
2437 } else if ahead.peek(Token![pub])
2438 || ahead.peek(Token![crate]) && !ahead.peek2(Token![::])
2439 || ahead.peek(Token![extern]) && !ahead.peek2(Token![::])
2440 || ahead.peek(Token![use])
2441 || ahead.peek(Token![static]) && (ahead.peek2(Token![mut]) || ahead.peek2(Ident))
2442 || ahead.peek(Token![const])
2443 || ahead.peek(Token![unsafe]) && !ahead.peek2(token::Brace)
2444 || ahead.peek(Token![async]) && (ahead.peek2(Token![extern]) || ahead.peek2(Token![fn]))
2445 || ahead.peek(Token![fn])
2446 || ahead.peek(Token![mod])
2447 || ahead.peek(Token![type])
2448 || ahead.peek(Token![existential]) && ahead.peek2(Token![type])
2449 || ahead.peek(Token![struct])
2450 || ahead.peek(Token![enum])
2451 || ahead.peek(Token![union]) && ahead.peek2(Ident)
2452 || ahead.peek(Token![auto]) && ahead.peek2(Token![trait])
2453 || ahead.peek(Token![trait])
David Tolnay73b7ca12018-08-30 21:05:13 -07002454 || ahead.peek(Token![default])
David Tolnay2beee042019-04-03 08:36:59 -07002455 && (ahead.peek2(Token![unsafe]) || ahead.peek2(Token![impl]))
2456 || ahead.peek(Token![impl])
David Tolnaye532d6b2018-08-30 16:55:01 -07002457 || ahead.peek(Token![macro])
2458 {
2459 input.parse().map(Stmt::Item)
2460 } else {
2461 stmt_expr(input, allow_nosemi)
David Tolnay60291082018-08-28 09:54:49 -07002462 }
Alex Crichton954046c2017-05-30 21:49:42 -07002463 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07002464
Michael Layzell734adb42017-06-07 16:58:31 -04002465 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002466 fn stmt_mac(input: ParseStream) -> Result<Stmt> {
2467 let attrs = input.call(Attribute::parse_outer)?;
2468 let path = input.call(Path::parse_mod_style)?;
2469 let bang_token: Token![!] = input.parse()?;
2470 let ident: Option<Ident> = input.parse()?;
2471 let (delimiter, tts) = mac::parse_delimiter(input)?;
2472 let semi_token: Option<Token![;]> = input.parse()?;
2473
2474 Ok(Stmt::Item(Item::Macro(ItemMacro {
2475 attrs: attrs,
2476 ident: ident,
2477 mac: Macro {
2478 path: path,
2479 bang_token: bang_token,
2480 delimiter: delimiter,
2481 tts: tts,
2482 },
2483 semi_token: semi_token,
2484 })))
Alex Crichton954046c2017-05-30 21:49:42 -07002485 }
David Tolnay84aa0752016-10-02 23:01:13 -07002486
Michael Layzell734adb42017-06-07 16:58:31 -04002487 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002488 fn stmt_local(input: ParseStream) -> Result<Local> {
2489 Ok(Local {
2490 attrs: input.call(Attribute::parse_outer)?,
2491 let_token: input.parse()?,
2492 pats: {
2493 let mut pats = Punctuated::new();
2494 let value: Pat = input.parse()?;
2495 pats.push_value(value);
2496 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2497 let punct = input.parse()?;
2498 pats.push_punct(punct);
2499 let value: Pat = input.parse()?;
2500 pats.push_value(value);
2501 }
2502 pats
2503 },
2504 ty: {
2505 if input.peek(Token![:]) {
2506 let colon_token: Token![:] = input.parse()?;
2507 let ty: Type = input.parse()?;
2508 Some((colon_token, Box::new(ty)))
2509 } else {
2510 None
2511 }
2512 },
2513 init: {
2514 if input.peek(Token![=]) {
2515 let eq_token: Token![=] = input.parse()?;
2516 let init: Expr = input.parse()?;
2517 Some((eq_token, Box::new(init)))
2518 } else {
2519 None
2520 }
2521 },
2522 semi_token: input.parse()?,
2523 })
2524 }
2525
2526 #[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -07002527 fn stmt_expr(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
David Tolnay60291082018-08-28 09:54:49 -07002528 let mut attrs = input.call(Attribute::parse_outer)?;
David Tolnay01218d12018-08-29 18:13:07 -07002529 let mut e = expr_early(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002530
2531 attrs.extend(e.replace_attrs(Vec::new()));
2532 e.replace_attrs(attrs);
2533
2534 if input.peek(Token![;]) {
David Tolnay01218d12018-08-29 18:13:07 -07002535 return Ok(Stmt::Semi(e, input.parse()?));
David Tolnay60291082018-08-28 09:54:49 -07002536 }
David Tolnay60291082018-08-28 09:54:49 -07002537
David Tolnayf00a2762018-08-30 17:22:22 -07002538 if allow_nosemi || !requires_terminator(&e) {
David Tolnaye532d6b2018-08-30 16:55:01 -07002539 Ok(Stmt::Expr(e))
2540 } else {
2541 Err(input.error("expected semicolon"))
David Tolnay01218d12018-08-29 18:13:07 -07002542 }
David Tolnay60291082018-08-28 09:54:49 -07002543 }
2544
2545 #[cfg(feature = "full")]
2546 impl Parse for Pat {
2547 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay60291082018-08-28 09:54:49 -07002548 let lookahead = input.lookahead1();
2549 if lookahead.peek(Token![_]) {
David Tolnay310b3262018-08-30 15:33:00 -07002550 input.call(pat_wild).map(Pat::Wild)
David Tolnay60291082018-08-28 09:54:49 -07002551 } else if lookahead.peek(Token![box]) {
David Tolnay310b3262018-08-30 15:33:00 -07002552 input.call(pat_box).map(Pat::Box)
David Tolnay8d534b02018-09-02 09:46:05 -07002553 } else if lookahead.peek(Token![-]) || lookahead.peek(Lit) {
2554 pat_lit_or_range(input)
2555 } else if input.peek(Ident)
2556 && ({
2557 input.peek2(Token![::])
2558 || input.peek2(Token![!])
2559 || input.peek2(token::Brace)
2560 || input.peek2(token::Paren)
David Tolnaye614f282018-10-27 22:50:12 -07002561 || input.peek2(Token![..])
2562 && !{
2563 let ahead = input.fork();
2564 ahead.parse::<Ident>()?;
2565 ahead.parse::<RangeLimits>()?;
2566 ahead.is_empty() || ahead.peek(Token![,])
2567 }
David Tolnay8d534b02018-09-02 09:46:05 -07002568 })
Michael Bradshaw7531e152018-10-19 22:26:56 -07002569 || input.peek(Token![self]) && input.peek2(Token![::])
David Tolnay8d534b02018-09-02 09:46:05 -07002570 || input.peek(Token![::])
2571 || input.peek(Token![<])
David Tolnay8d534b02018-09-02 09:46:05 -07002572 || input.peek(Token![Self])
2573 || input.peek(Token![super])
2574 || input.peek(Token![extern])
2575 || input.peek(Token![crate])
2576 {
2577 pat_path_or_macro_or_struct_or_range(input)
Michael Bradshaw7531e152018-10-19 22:26:56 -07002578 } else if input.peek(Token![ref])
2579 || input.peek(Token![mut])
2580 || input.peek(Token![self])
2581 || input.peek(Ident)
2582 {
David Tolnay310b3262018-08-30 15:33:00 -07002583 input.call(pat_ident).map(Pat::Ident)
David Tolnay60291082018-08-28 09:54:49 -07002584 } else if lookahead.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07002585 input.call(pat_tuple).map(Pat::Tuple)
David Tolnay60291082018-08-28 09:54:49 -07002586 } else if lookahead.peek(Token![&]) {
David Tolnay310b3262018-08-30 15:33:00 -07002587 input.call(pat_ref).map(Pat::Ref)
David Tolnay60291082018-08-28 09:54:49 -07002588 } else if lookahead.peek(token::Bracket) {
David Tolnay310b3262018-08-30 15:33:00 -07002589 input.call(pat_slice).map(Pat::Slice)
David Tolnay60291082018-08-28 09:54:49 -07002590 } else {
2591 Err(lookahead.error())
2592 }
2593 }
2594 }
2595
2596 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002597 fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> {
2598 let (qself, path) = path::parsing::qpath(input, true)?;
2599
2600 if input.peek(Token![..]) {
2601 return pat_range(input, qself, path).map(Pat::Range);
2602 }
2603
2604 if qself.is_some() {
2605 return Ok(Pat::Path(PatPath {
2606 qself: qself,
2607 path: path,
2608 }));
2609 }
2610
2611 if input.peek(Token![!]) && !input.peek(Token![!=]) {
2612 let mut contains_arguments = false;
2613 for segment in &path.segments {
2614 match segment.arguments {
2615 PathArguments::None => {}
2616 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
2617 contains_arguments = true;
2618 }
2619 }
2620 }
2621
2622 if !contains_arguments {
2623 let bang_token: Token![!] = input.parse()?;
2624 let (delimiter, tts) = mac::parse_delimiter(input)?;
2625 return Ok(Pat::Macro(PatMacro {
2626 mac: Macro {
2627 path: path,
2628 bang_token: bang_token,
2629 delimiter: delimiter,
2630 tts: tts,
2631 },
2632 }));
2633 }
2634 }
2635
2636 if input.peek(token::Brace) {
2637 pat_struct(input, path).map(Pat::Struct)
2638 } else if input.peek(token::Paren) {
2639 pat_tuple_struct(input, path).map(Pat::TupleStruct)
2640 } else if input.peek(Token![..]) {
2641 pat_range(input, qself, path).map(Pat::Range)
2642 } else {
2643 Ok(Pat::Path(PatPath {
2644 qself: qself,
2645 path: path,
2646 }))
2647 }
2648 }
2649
2650 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002651 fn pat_wild(input: ParseStream) -> Result<PatWild> {
2652 Ok(PatWild {
2653 underscore_token: input.parse()?,
2654 })
Alex Crichton954046c2017-05-30 21:49:42 -07002655 }
2656
Michael Layzell734adb42017-06-07 16:58:31 -04002657 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002658 fn pat_box(input: ParseStream) -> Result<PatBox> {
2659 Ok(PatBox {
2660 box_token: input.parse()?,
2661 pat: input.parse()?,
2662 })
David Tolnay60291082018-08-28 09:54:49 -07002663 }
2664
2665 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002666 fn pat_ident(input: ParseStream) -> Result<PatIdent> {
2667 Ok(PatIdent {
2668 by_ref: input.parse()?,
2669 mutability: input.parse()?,
David Tolnay8d534b02018-09-02 09:46:05 -07002670 ident: input.call(Ident::parse_any)?,
David Tolnay310b3262018-08-30 15:33:00 -07002671 subpat: {
2672 if input.peek(Token![@]) {
2673 let at_token: Token![@] = input.parse()?;
2674 let subpat: Pat = input.parse()?;
2675 Some((at_token, Box::new(subpat)))
2676 } else {
2677 None
2678 }
2679 },
2680 })
David Tolnay60291082018-08-28 09:54:49 -07002681 }
2682
2683 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002684 fn pat_tuple_struct(input: ParseStream, path: Path) -> Result<PatTupleStruct> {
David Tolnay310b3262018-08-30 15:33:00 -07002685 Ok(PatTupleStruct {
David Tolnay8d534b02018-09-02 09:46:05 -07002686 path: path,
David Tolnay310b3262018-08-30 15:33:00 -07002687 pat: input.call(pat_tuple)?,
2688 })
2689 }
David Tolnay60291082018-08-28 09:54:49 -07002690
David Tolnay310b3262018-08-30 15:33:00 -07002691 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002692 fn pat_struct(input: ParseStream, path: Path) -> Result<PatStruct> {
David Tolnay310b3262018-08-30 15:33:00 -07002693 let content;
2694 let brace_token = braced!(content in input);
2695
2696 let mut fields = Punctuated::new();
2697 while !content.is_empty() && !content.peek(Token![..]) {
2698 let value = content.call(field_pat)?;
2699 fields.push_value(value);
2700 if !content.peek(Token![,]) {
2701 break;
David Tolnay60291082018-08-28 09:54:49 -07002702 }
David Tolnay310b3262018-08-30 15:33:00 -07002703 let punct: Token![,] = content.parse()?;
2704 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002705 }
David Tolnay310b3262018-08-30 15:33:00 -07002706
2707 let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) {
2708 Some(content.parse()?)
2709 } else {
2710 None
2711 };
2712
2713 Ok(PatStruct {
2714 path: path,
2715 brace_token: brace_token,
2716 fields: fields,
2717 dot2_token: dot2_token,
2718 })
2719 }
2720
2721 #[cfg(feature = "full")]
2722 fn field_pat(input: ParseStream) -> Result<FieldPat> {
2723 let boxed: Option<Token![box]> = input.parse()?;
2724 let by_ref: Option<Token![ref]> = input.parse()?;
2725 let mutability: Option<Token![mut]> = input.parse()?;
2726 let member: Member = input.parse()?;
2727
2728 if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
2729 || member.is_unnamed()
2730 {
2731 return Ok(FieldPat {
2732 attrs: Vec::new(),
2733 member: member,
2734 colon_token: input.parse()?,
2735 pat: input.parse()?,
2736 });
2737 }
2738
2739 let ident = match member {
2740 Member::Named(ident) => ident,
2741 Member::Unnamed(_) => unreachable!(),
2742 };
2743
2744 let mut pat = Pat::Ident(PatIdent {
2745 by_ref: by_ref,
2746 mutability: mutability,
2747 ident: ident.clone(),
2748 subpat: None,
2749 });
2750
2751 if let Some(boxed) = boxed {
2752 pat = Pat::Box(PatBox {
2753 pat: Box::new(pat),
2754 box_token: boxed,
2755 });
2756 }
2757
2758 Ok(FieldPat {
2759 member: Member::Named(ident),
2760 pat: Box::new(pat),
2761 attrs: Vec::new(),
2762 colon_token: None,
2763 })
Alex Crichton954046c2017-05-30 21:49:42 -07002764 }
2765
David Tolnay1501f7e2018-08-27 14:21:03 -07002766 impl Parse for Member {
2767 fn parse(input: ParseStream) -> Result<Self> {
2768 if input.peek(Ident) {
2769 input.parse().map(Member::Named)
2770 } else if input.peek(LitInt) {
2771 input.parse().map(Member::Unnamed)
2772 } else {
2773 Err(input.error("expected identifier or integer"))
2774 }
2775 }
David Tolnay85b69a42017-12-27 20:43:10 -05002776 }
2777
Bastien Oriveld29ea392018-10-16 23:50:16 +02002778 #[cfg(feature = "full")]
2779 impl Parse for Arm {
2780 fn parse(input: ParseStream) -> Result<Arm> {
2781 let requires_comma;
2782 Ok(Arm {
2783 attrs: input.call(Attribute::parse_outer)?,
2784 leading_vert: input.parse()?,
2785 pats: {
2786 let mut pats = Punctuated::new();
2787 let value: Pat = input.parse()?;
2788 pats.push_value(value);
2789 loop {
2790 if !input.peek(Token![|]) {
2791 break;
2792 }
2793 let punct = input.parse()?;
2794 pats.push_punct(punct);
2795 let value: Pat = input.parse()?;
2796 pats.push_value(value);
2797 }
2798 pats
2799 },
2800 guard: {
2801 if input.peek(Token![if]) {
2802 let if_token: Token![if] = input.parse()?;
2803 let guard: Expr = input.parse()?;
2804 Some((if_token, Box::new(guard)))
2805 } else {
2806 None
2807 }
2808 },
2809 fat_arrow_token: input.parse()?,
2810 body: {
2811 let body = input.call(expr_early)?;
2812 requires_comma = requires_terminator(&body);
2813 Box::new(body)
2814 },
2815 comma: {
2816 if requires_comma && !input.is_empty() {
2817 Some(input.parse()?)
2818 } else {
2819 input.parse()?
2820 }
2821 },
2822 })
2823 }
2824 }
2825
David Tolnay1501f7e2018-08-27 14:21:03 -07002826 impl Parse for Index {
2827 fn parse(input: ParseStream) -> Result<Self> {
2828 let lit: LitInt = input.parse()?;
2829 if let IntSuffix::None = lit.suffix() {
2830 Ok(Index {
2831 index: lit.value() as u32,
2832 span: lit.span(),
2833 })
2834 } else {
David Tolnayff8c9342018-09-01 13:45:48 -07002835 Err(Error::new(lit.span(), "expected unsuffixed integer"))
David Tolnay1501f7e2018-08-27 14:21:03 -07002836 }
2837 }
David Tolnay85b69a42017-12-27 20:43:10 -05002838 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07002839
Michael Layzell734adb42017-06-07 16:58:31 -04002840 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002841 fn pat_range(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<PatRange> {
2842 Ok(PatRange {
2843 lo: Box::new(Expr::Path(ExprPath {
2844 attrs: Vec::new(),
2845 qself: qself,
2846 path: path,
2847 })),
2848 limits: input.parse()?,
2849 hi: input.call(pat_lit_expr)?,
David Tolnay310b3262018-08-30 15:33:00 -07002850 })
Alex Crichton954046c2017-05-30 21:49:42 -07002851 }
David Tolnay9636c052016-10-02 17:11:17 -07002852
Michael Layzell734adb42017-06-07 16:58:31 -04002853 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002854 fn pat_tuple(input: ParseStream) -> Result<PatTuple> {
2855 let content;
2856 let paren_token = parenthesized!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002857
David Tolnay310b3262018-08-30 15:33:00 -07002858 let mut front = Punctuated::new();
2859 let mut dot2_token = None::<Token![..]>;
2860 let mut comma_token = None::<Token![,]>;
2861 loop {
2862 if content.is_empty() {
2863 break;
David Tolnay60291082018-08-28 09:54:49 -07002864 }
David Tolnay310b3262018-08-30 15:33:00 -07002865 if content.peek(Token![..]) {
2866 dot2_token = Some(content.parse()?);
2867 comma_token = content.parse()?;
2868 break;
David Tolnay60291082018-08-28 09:54:49 -07002869 }
David Tolnay310b3262018-08-30 15:33:00 -07002870 let value: Pat = content.parse()?;
2871 front.push_value(value);
2872 if content.is_empty() {
2873 break;
2874 }
2875 let punct = content.parse()?;
2876 front.push_punct(punct);
2877 }
2878
David Tolnayf5ebc192018-08-30 18:23:46 -07002879 let mut back = Punctuated::new();
2880 while !content.is_empty() {
2881 let value: Pat = content.parse()?;
2882 back.push_value(value);
2883 if content.is_empty() {
2884 break;
2885 }
2886 let punct = content.parse()?;
2887 back.push_punct(punct);
2888 }
David Tolnay310b3262018-08-30 15:33:00 -07002889
2890 Ok(PatTuple {
2891 paren_token: paren_token,
2892 front: front,
2893 dot2_token: dot2_token,
2894 comma_token: comma_token,
2895 back: back,
2896 })
2897 }
2898
2899 #[cfg(feature = "full")]
2900 fn pat_ref(input: ParseStream) -> Result<PatRef> {
2901 Ok(PatRef {
2902 and_token: input.parse()?,
2903 mutability: input.parse()?,
2904 pat: input.parse()?,
2905 })
2906 }
2907
2908 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002909 fn pat_lit_or_range(input: ParseStream) -> Result<Pat> {
2910 let lo = input.call(pat_lit_expr)?;
2911 if input.peek(Token![..]) {
2912 Ok(Pat::Range(PatRange {
2913 lo: lo,
2914 limits: input.parse()?,
2915 hi: input.call(pat_lit_expr)?,
2916 }))
David Tolnay310b3262018-08-30 15:33:00 -07002917 } else {
David Tolnay8d534b02018-09-02 09:46:05 -07002918 Ok(Pat::Lit(PatLit { expr: lo }))
David Tolnay60291082018-08-28 09:54:49 -07002919 }
2920 }
2921
2922 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002923 fn pat_lit_expr(input: ParseStream) -> Result<Box<Expr>> {
2924 let neg: Option<Token![-]> = input.parse()?;
2925
2926 let lookahead = input.lookahead1();
2927 let expr = if lookahead.peek(Lit) {
Peter Hall04f42792019-04-02 16:58:45 +02002928 Expr::Lit(input.parse()?)
David Tolnay60291082018-08-28 09:54:49 -07002929 } else if lookahead.peek(Ident)
2930 || lookahead.peek(Token![::])
2931 || lookahead.peek(Token![<])
2932 || lookahead.peek(Token![self])
2933 || lookahead.peek(Token![Self])
2934 || lookahead.peek(Token![super])
2935 || lookahead.peek(Token![extern])
2936 || lookahead.peek(Token![crate])
2937 {
2938 Expr::Path(input.parse()?)
2939 } else {
2940 return Err(lookahead.error());
2941 };
2942
2943 Ok(Box::new(if let Some(neg) = neg {
David Tolnay8c91b882017-12-28 23:04:32 -05002944 Expr::Unary(ExprUnary {
2945 attrs: Vec::new(),
David Tolnayc29b9892017-12-27 22:58:14 -05002946 op: UnOp::Neg(neg),
David Tolnay60291082018-08-28 09:54:49 -07002947 expr: Box::new(expr),
David Tolnay3bc597f2017-12-31 02:31:11 -05002948 })
David Tolnay0ad9e9f2016-10-29 22:20:02 -07002949 } else {
David Tolnay60291082018-08-28 09:54:49 -07002950 expr
2951 }))
Alex Crichton954046c2017-05-30 21:49:42 -07002952 }
David Tolnay323279a2017-12-29 11:26:32 -05002953
2954 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002955 fn pat_slice(input: ParseStream) -> Result<PatSlice> {
2956 let content;
2957 let bracket_token = bracketed!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002958
David Tolnay310b3262018-08-30 15:33:00 -07002959 let mut front = Punctuated::new();
2960 let mut middle = None;
2961 loop {
2962 if content.is_empty() || content.peek(Token![..]) {
2963 break;
David Tolnay60291082018-08-28 09:54:49 -07002964 }
David Tolnay310b3262018-08-30 15:33:00 -07002965 let value: Pat = content.parse()?;
2966 if content.peek(Token![..]) {
2967 middle = Some(Box::new(value));
2968 break;
David Tolnay60291082018-08-28 09:54:49 -07002969 }
David Tolnay310b3262018-08-30 15:33:00 -07002970 front.push_value(value);
2971 if content.is_empty() {
2972 break;
2973 }
2974 let punct = content.parse()?;
2975 front.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002976 }
David Tolnay310b3262018-08-30 15:33:00 -07002977
2978 let dot2_token: Option<Token![..]> = content.parse()?;
2979 let mut comma_token = None::<Token![,]>;
2980 let mut back = Punctuated::new();
2981 if dot2_token.is_some() {
2982 comma_token = content.parse()?;
2983 if comma_token.is_some() {
2984 loop {
2985 if content.is_empty() {
2986 break;
2987 }
2988 let value: Pat = content.parse()?;
2989 back.push_value(value);
2990 if content.is_empty() {
2991 break;
2992 }
2993 let punct = content.parse()?;
2994 back.push_punct(punct);
2995 }
2996 }
2997 }
2998
2999 Ok(PatSlice {
3000 bracket_token: bracket_token,
3001 front: front,
3002 middle: middle,
3003 dot2_token: dot2_token,
3004 comma_token: comma_token,
3005 back: back,
3006 })
David Tolnay60291082018-08-28 09:54:49 -07003007 }
3008
3009 #[cfg(feature = "full")]
David Tolnay1501f7e2018-08-27 14:21:03 -07003010 impl Member {
3011 fn is_named(&self) -> bool {
3012 match *self {
3013 Member::Named(_) => true,
3014 Member::Unnamed(_) => false,
3015 }
3016 }
David Tolnay60291082018-08-28 09:54:49 -07003017
3018 fn is_unnamed(&self) -> bool {
3019 match *self {
3020 Member::Named(_) => false,
3021 Member::Unnamed(_) => true,
3022 }
3023 }
David Tolnay1501f7e2018-08-27 14:21:03 -07003024 }
David Tolnayb9c8e322016-09-23 20:48:37 -07003025}
3026
David Tolnayf4bbbd92016-09-23 14:41:55 -07003027#[cfg(feature = "printing")]
3028mod printing {
3029 use super::*;
David Tolnay64023912018-08-31 09:51:12 -07003030
Alex Crichtona74a1c82018-05-16 10:20:44 -07003031 use proc_macro2::{Literal, TokenStream};
3032 use quote::{ToTokens, TokenStreamExt};
David Tolnayf4bbbd92016-09-23 14:41:55 -07003033
David Tolnay64023912018-08-31 09:51:12 -07003034 #[cfg(feature = "full")]
3035 use attr::FilterAttrs;
3036 #[cfg(feature = "full")]
3037 use print::TokensOrDefault;
3038
David Tolnaybcf26022017-12-25 22:10:52 -05003039 // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
David Tolnayb6a0e7d2018-05-20 22:06:47 -07003040 // before appending it to `TokenStream`.
Michael Layzell3936ceb2017-07-08 00:28:36 -04003041 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003042 fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) {
David Tolnay8c91b882017-12-28 23:04:32 -05003043 if let Expr::Struct(_) = *e {
David Tolnay32954ef2017-12-26 22:43:16 -05003044 token::Paren::default().surround(tokens, |tokens| {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003045 e.to_tokens(tokens);
3046 });
3047 } else {
3048 e.to_tokens(tokens);
3049 }
3050 }
3051
David Tolnay8c91b882017-12-28 23:04:32 -05003052 #[cfg(feature = "full")]
David Tolnayd997aef2018-07-21 18:42:31 -07003053 fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
David Tolnay8c91b882017-12-28 23:04:32 -05003054 tokens.append_all(attrs.outer());
3055 }
Michael Layzell734adb42017-06-07 16:58:31 -04003056
David Tolnayd997aef2018-07-21 18:42:31 -07003057 #[cfg(feature = "full")]
3058 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3059 tokens.append_all(attrs.inner());
3060 }
3061
David Tolnay8c91b882017-12-28 23:04:32 -05003062 #[cfg(not(feature = "full"))]
David Tolnayd997aef2018-07-21 18:42:31 -07003063 fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3064
3065 #[cfg(not(feature = "full"))]
3066 fn inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
Alex Crichton62a0a592017-05-22 13:58:53 -07003067
Michael Layzell734adb42017-06-07 16:58:31 -04003068 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003069 impl ToTokens for ExprBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003070 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003071 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003072 self.box_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003073 self.expr.to_tokens(tokens);
3074 }
3075 }
3076
Michael Layzell734adb42017-06-07 16:58:31 -04003077 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003078 impl ToTokens for ExprInPlace {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003079 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003080 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8701a5c2017-12-28 23:31:10 -05003081 self.place.to_tokens(tokens);
3082 self.arrow_token.to_tokens(tokens);
3083 self.value.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003084 }
3085 }
3086
Michael Layzell734adb42017-06-07 16:58:31 -04003087 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003088 impl ToTokens for ExprArray {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003089 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003090 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003091 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003092 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003093 self.elems.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003094 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003095 }
3096 }
3097
3098 impl ToTokens for ExprCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003099 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003100 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003101 self.func.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003102 self.paren_token.surround(tokens, |tokens| {
3103 self.args.to_tokens(tokens);
3104 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003105 }
3106 }
3107
Michael Layzell734adb42017-06-07 16:58:31 -04003108 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003109 impl ToTokens for ExprMethodCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003110 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003111 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay76418512017-12-28 23:47:47 -05003112 self.receiver.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003113 self.dot_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003114 self.method.to_tokens(tokens);
David Tolnayd60cfec2017-12-29 00:21:38 -05003115 self.turbofish.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003116 self.paren_token.surround(tokens, |tokens| {
3117 self.args.to_tokens(tokens);
3118 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003119 }
3120 }
3121
Michael Layzell734adb42017-06-07 16:58:31 -04003122 #[cfg(feature = "full")]
David Tolnayd60cfec2017-12-29 00:21:38 -05003123 impl ToTokens for MethodTurbofish {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003124 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003125 self.colon2_token.to_tokens(tokens);
3126 self.lt_token.to_tokens(tokens);
3127 self.args.to_tokens(tokens);
3128 self.gt_token.to_tokens(tokens);
3129 }
3130 }
3131
3132 #[cfg(feature = "full")]
3133 impl ToTokens for GenericMethodArgument {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003134 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003135 match *self {
3136 GenericMethodArgument::Type(ref t) => t.to_tokens(tokens),
3137 GenericMethodArgument::Const(ref c) => c.to_tokens(tokens),
3138 }
3139 }
3140 }
3141
3142 #[cfg(feature = "full")]
David Tolnay05362582017-12-26 01:33:57 -05003143 impl ToTokens for ExprTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003144 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003145 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003146 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003147 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003148 self.elems.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003149 // If we only have one argument, we need a trailing comma to
David Tolnay05362582017-12-26 01:33:57 -05003150 // distinguish ExprTuple from ExprParen.
David Tolnaya0834b42018-01-01 21:30:02 -08003151 if self.elems.len() == 1 && !self.elems.trailing_punct() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003152 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003153 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003154 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003155 }
3156 }
3157
3158 impl ToTokens for ExprBinary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003159 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003160 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003161 self.left.to_tokens(tokens);
3162 self.op.to_tokens(tokens);
3163 self.right.to_tokens(tokens);
3164 }
3165 }
3166
3167 impl ToTokens for ExprUnary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003168 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003169 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003170 self.op.to_tokens(tokens);
3171 self.expr.to_tokens(tokens);
3172 }
3173 }
3174
David Tolnay8c91b882017-12-28 23:04:32 -05003175 impl ToTokens for ExprLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003176 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003177 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003178 self.lit.to_tokens(tokens);
3179 }
3180 }
3181
Alex Crichton62a0a592017-05-22 13:58:53 -07003182 impl ToTokens for ExprCast {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003183 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003184 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003185 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003186 self.as_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003187 self.ty.to_tokens(tokens);
3188 }
3189 }
3190
David Tolnay0cf94f22017-12-28 23:46:26 -05003191 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003192 impl ToTokens for ExprType {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003193 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003194 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003195 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003196 self.colon_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003197 self.ty.to_tokens(tokens);
3198 }
3199 }
3200
Michael Layzell734adb42017-06-07 16:58:31 -04003201 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003202 fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>) {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003203 if let Some((ref else_token, ref else_)) = *else_ {
3204 else_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003205
3206 // If we are not one of the valid expressions to exist in an else
3207 // clause, wrap ourselves in a block.
David Tolnay2ccf32a2017-12-29 00:34:26 -05003208 match **else_ {
David Tolnay9c119122018-09-01 18:47:02 -07003209 Expr::If(_) | Expr::Block(_) => {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003210 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003211 }
3212 _ => {
David Tolnay32954ef2017-12-26 22:43:16 -05003213 token::Brace::default().surround(tokens, |tokens| {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003214 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003215 });
3216 }
3217 }
3218 }
3219 }
3220
3221 #[cfg(feature = "full")]
David Tolnay9c119122018-09-01 18:47:02 -07003222 impl ToTokens for ExprLet {
3223 fn to_tokens(&self, tokens: &mut TokenStream) {
3224 outer_attrs_to_tokens(&self.attrs, tokens);
3225 self.let_token.to_tokens(tokens);
3226 self.pats.to_tokens(tokens);
3227 self.eq_token.to_tokens(tokens);
3228 wrap_bare_struct(tokens, &self.expr);
3229 }
3230 }
3231
3232 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003233 impl ToTokens for ExprIf {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003234 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003235 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003236 self.if_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003237 wrap_bare_struct(tokens, &self.cond);
David Tolnay2ccf32a2017-12-29 00:34:26 -05003238 self.then_branch.to_tokens(tokens);
3239 maybe_wrap_else(tokens, &self.else_branch);
Alex Crichton62a0a592017-05-22 13:58:53 -07003240 }
3241 }
3242
Michael Layzell734adb42017-06-07 16:58:31 -04003243 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003244 impl ToTokens for ExprWhile {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003245 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003246 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003247 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003248 self.while_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003249 wrap_bare_struct(tokens, &self.cond);
David Tolnay5d314dc2018-07-21 16:40:01 -07003250 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003251 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003252 tokens.append_all(&self.body.stmts);
3253 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003254 }
3255 }
3256
Michael Layzell734adb42017-06-07 16:58:31 -04003257 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003258 impl ToTokens for ExprForLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003259 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003260 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003261 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003262 self.for_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003263 self.pat.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003264 self.in_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003265 wrap_bare_struct(tokens, &self.expr);
David Tolnay5d314dc2018-07-21 16:40:01 -07003266 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003267 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003268 tokens.append_all(&self.body.stmts);
3269 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003270 }
3271 }
3272
Michael Layzell734adb42017-06-07 16:58:31 -04003273 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003274 impl ToTokens for ExprLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003275 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003276 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003277 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003278 self.loop_token.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003279 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003280 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003281 tokens.append_all(&self.body.stmts);
3282 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003283 }
3284 }
3285
Michael Layzell734adb42017-06-07 16:58:31 -04003286 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003287 impl ToTokens for ExprMatch {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003288 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003289 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003290 self.match_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003291 wrap_bare_struct(tokens, &self.expr);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003292 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003293 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay51382052017-12-27 13:46:21 -05003294 for (i, arm) in self.arms.iter().enumerate() {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003295 arm.to_tokens(tokens);
3296 // Ensure that we have a comma after a non-block arm, except
3297 // for the last one.
3298 let is_last = i == self.arms.len() - 1;
David Tolnaye532d6b2018-08-30 16:55:01 -07003299 if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003300 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003301 }
3302 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003303 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003304 }
3305 }
3306
Michael Layzell734adb42017-06-07 16:58:31 -04003307 #[cfg(feature = "full")]
David Tolnay02a9c6f2018-08-24 18:58:45 -04003308 impl ToTokens for ExprAsync {
3309 fn to_tokens(&self, tokens: &mut TokenStream) {
3310 outer_attrs_to_tokens(&self.attrs, tokens);
3311 self.async_token.to_tokens(tokens);
3312 self.capture.to_tokens(tokens);
3313 self.block.to_tokens(tokens);
3314 }
3315 }
3316
3317 #[cfg(feature = "full")]
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003318 impl ToTokens for ExprTryBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003319 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003320 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003321 self.try_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003322 self.block.to_tokens(tokens);
3323 }
3324 }
3325
Michael Layzell734adb42017-06-07 16:58:31 -04003326 #[cfg(feature = "full")]
Alex Crichtonfe110462017-06-01 12:49:27 -07003327 impl ToTokens for ExprYield {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003328 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003329 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonfe110462017-06-01 12:49:27 -07003330 self.yield_token.to_tokens(tokens);
3331 self.expr.to_tokens(tokens);
3332 }
3333 }
3334
3335 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003336 impl ToTokens for ExprClosure {
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);
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09003339 self.asyncness.to_tokens(tokens);
David Tolnay13d4c0e2018-03-31 20:53:59 +02003340 self.movability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003341 self.capture.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003342 self.or1_token.to_tokens(tokens);
David Tolnay56080682018-01-06 14:01:52 -08003343 for input in self.inputs.pairs() {
3344 match **input.value() {
David Tolnay51382052017-12-27 13:46:21 -05003345 FnArg::Captured(ArgCaptured {
3346 ref pat,
3347 ty: Type::Infer(_),
3348 ..
3349 }) => {
Alex Crichton62a0a592017-05-22 13:58:53 -07003350 pat.to_tokens(tokens);
David Tolnay9636c052016-10-02 17:11:17 -07003351 }
David Tolnay56080682018-01-06 14:01:52 -08003352 _ => input.value().to_tokens(tokens),
David Tolnay3c2467c2016-10-02 17:55:08 -07003353 }
David Tolnayf2cfd722017-12-31 18:02:51 -05003354 input.punct().to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003355 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003356 self.or2_token.to_tokens(tokens);
David Tolnay7f675742017-12-27 22:43:21 -05003357 self.output.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003358 self.body.to_tokens(tokens);
3359 }
3360 }
3361
Michael Layzell734adb42017-06-07 16:58:31 -04003362 #[cfg(feature = "full")]
Nika Layzell640832a2017-12-04 13:37:09 -05003363 impl ToTokens for ExprUnsafe {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003364 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003365 outer_attrs_to_tokens(&self.attrs, tokens);
Nika Layzell640832a2017-12-04 13:37:09 -05003366 self.unsafe_token.to_tokens(tokens);
David Tolnayc4be3512018-08-27 06:25:44 -07003367 self.block.brace_token.surround(tokens, |tokens| {
3368 inner_attrs_to_tokens(&self.attrs, tokens);
3369 tokens.append_all(&self.block.stmts);
3370 });
Nika Layzell640832a2017-12-04 13:37:09 -05003371 }
3372 }
3373
3374 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003375 impl ToTokens for ExprBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003376 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003377 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay1d8e9962018-08-24 19:04:20 -04003378 self.label.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003379 self.block.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003380 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003381 tokens.append_all(&self.block.stmts);
3382 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003383 }
3384 }
3385
Michael Layzell734adb42017-06-07 16:58:31 -04003386 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003387 impl ToTokens for ExprAssign {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003388 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003389 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003390 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003391 self.eq_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003392 self.right.to_tokens(tokens);
3393 }
3394 }
3395
Michael Layzell734adb42017-06-07 16:58:31 -04003396 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003397 impl ToTokens for ExprAssignOp {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003398 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003399 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003400 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003401 self.op.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003402 self.right.to_tokens(tokens);
3403 }
3404 }
3405
3406 impl ToTokens for ExprField {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003407 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003408 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003409 self.base.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003410 self.dot_token.to_tokens(tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003411 self.member.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003412 }
3413 }
3414
David Tolnay85b69a42017-12-27 20:43:10 -05003415 impl ToTokens for Member {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003416 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay85b69a42017-12-27 20:43:10 -05003417 match *self {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003418 Member::Named(ref ident) => ident.to_tokens(tokens),
David Tolnay85b69a42017-12-27 20:43:10 -05003419 Member::Unnamed(ref index) => index.to_tokens(tokens),
3420 }
3421 }
3422 }
3423
David Tolnay85b69a42017-12-27 20:43:10 -05003424 impl ToTokens for Index {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003425 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichton9a4dca22018-03-28 06:32:19 -07003426 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
3427 lit.set_span(self.span);
3428 tokens.append(lit);
Alex Crichton62a0a592017-05-22 13:58:53 -07003429 }
3430 }
3431
3432 impl ToTokens for ExprIndex {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003433 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003434 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003435 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003436 self.bracket_token.surround(tokens, |tokens| {
3437 self.index.to_tokens(tokens);
3438 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003439 }
3440 }
3441
Michael Layzell734adb42017-06-07 16:58:31 -04003442 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003443 impl ToTokens for ExprRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003444 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003445 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003446 self.from.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003447 match self.limits {
3448 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
3449 RangeLimits::Closed(ref t) => t.to_tokens(tokens),
3450 }
Alex Crichton62a0a592017-05-22 13:58:53 -07003451 self.to.to_tokens(tokens);
3452 }
3453 }
3454
3455 impl ToTokens for ExprPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003456 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003457 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay12f3b6f2018-09-01 16:10:53 -07003458 private::print_path(tokens, &self.qself, &self.path);
Alex Crichton62a0a592017-05-22 13:58:53 -07003459 }
3460 }
3461
Michael Layzell734adb42017-06-07 16:58:31 -04003462 #[cfg(feature = "full")]
David Tolnay00674ba2018-03-31 18:14:11 +02003463 impl ToTokens for ExprReference {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003464 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003465 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003466 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003467 self.mutability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003468 self.expr.to_tokens(tokens);
3469 }
3470 }
3471
Michael Layzell734adb42017-06-07 16:58:31 -04003472 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003473 impl ToTokens for ExprBreak {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003474 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003475 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003476 self.break_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003477 self.label.to_tokens(tokens);
3478 self.expr.to_tokens(tokens);
3479 }
3480 }
3481
Michael Layzell734adb42017-06-07 16:58:31 -04003482 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003483 impl ToTokens for ExprContinue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003484 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003485 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003486 self.continue_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003487 self.label.to_tokens(tokens);
3488 }
3489 }
3490
Michael Layzell734adb42017-06-07 16:58:31 -04003491 #[cfg(feature = "full")]
David Tolnayc246cd32017-12-28 23:14:32 -05003492 impl ToTokens for ExprReturn {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003493 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003494 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003495 self.return_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003496 self.expr.to_tokens(tokens);
3497 }
3498 }
3499
Michael Layzell734adb42017-06-07 16:58:31 -04003500 #[cfg(feature = "full")]
David Tolnay8c91b882017-12-28 23:04:32 -05003501 impl ToTokens for ExprMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003502 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003503 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003504 self.mac.to_tokens(tokens);
3505 }
3506 }
3507
3508 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003509 impl ToTokens for ExprStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003510 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003511 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003512 self.path.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003513 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003514 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003515 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003516 if self.rest.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -07003517 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003518 self.rest.to_tokens(tokens);
3519 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003520 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003521 }
3522 }
3523
Michael Layzell734adb42017-06-07 16:58:31 -04003524 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003525 impl ToTokens for ExprRepeat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003526 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003527 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003528 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003529 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003530 self.expr.to_tokens(tokens);
3531 self.semi_token.to_tokens(tokens);
David Tolnay84d80442018-01-07 01:03:20 -08003532 self.len.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003533 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003534 }
3535 }
3536
David Tolnaye98775f2017-12-28 23:17:00 -05003537 #[cfg(feature = "full")]
Michael Layzell93c36282017-06-04 20:43:14 -04003538 impl ToTokens for ExprGroup {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003539 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003540 outer_attrs_to_tokens(&self.attrs, tokens);
Michael Layzell93c36282017-06-04 20:43:14 -04003541 self.group_token.surround(tokens, |tokens| {
3542 self.expr.to_tokens(tokens);
3543 });
3544 }
3545 }
3546
Alex Crichton62a0a592017-05-22 13:58:53 -07003547 impl ToTokens for ExprParen {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003548 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003549 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003550 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003551 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003552 self.expr.to_tokens(tokens);
3553 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003554 }
3555 }
3556
Michael Layzell734adb42017-06-07 16:58:31 -04003557 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003558 impl ToTokens for ExprTry {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003559 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003560 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003561 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003562 self.question_token.to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003563 }
3564 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07003565
David Tolnay2ae520a2017-12-29 11:19:50 -05003566 impl ToTokens for ExprVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003567 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003568 self.tts.to_tokens(tokens);
3569 }
3570 }
3571
Michael Layzell734adb42017-06-07 16:58:31 -04003572 #[cfg(feature = "full")]
David Tolnaybcd498f2017-12-29 12:02:33 -05003573 impl ToTokens for Label {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003574 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaybcd498f2017-12-29 12:02:33 -05003575 self.name.to_tokens(tokens);
3576 self.colon_token.to_tokens(tokens);
3577 }
3578 }
3579
3580 #[cfg(feature = "full")]
David Tolnay055a7042016-10-02 19:23:54 -07003581 impl ToTokens for FieldValue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003582 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003583 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003584 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003585 if let Some(ref colon_token) = self.colon_token {
3586 colon_token.to_tokens(tokens);
David Tolnay276690f2016-10-30 12:06:59 -07003587 self.expr.to_tokens(tokens);
3588 }
David Tolnay055a7042016-10-02 19:23:54 -07003589 }
3590 }
3591
Michael Layzell734adb42017-06-07 16:58:31 -04003592 #[cfg(feature = "full")]
David Tolnayb4ad3b52016-10-01 21:58:13 -07003593 impl ToTokens for Arm {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003594 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003595 tokens.append_all(&self.attrs);
David Tolnay18cc4d42018-03-31 18:47:20 +02003596 self.leading_vert.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003597 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003598 if let Some((ref if_token, ref guard)) = self.guard {
3599 if_token.to_tokens(tokens);
3600 guard.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003601 }
David Tolnaydfb91432018-03-31 19:19:44 +02003602 self.fat_arrow_token.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003603 self.body.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003604 self.comma.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003605 }
3606 }
3607
Michael Layzell734adb42017-06-07 16:58:31 -04003608 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003609 impl ToTokens for PatWild {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003610 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003611 self.underscore_token.to_tokens(tokens);
3612 }
3613 }
3614
Michael Layzell734adb42017-06-07 16:58:31 -04003615 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003616 impl ToTokens for PatIdent {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003617 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay24237fb2017-12-29 02:15:26 -05003618 self.by_ref.to_tokens(tokens);
David Tolnayefc96fb2017-12-29 02:03:15 -05003619 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003620 self.ident.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003621 if let Some((ref at_token, ref subpat)) = self.subpat {
3622 at_token.to_tokens(tokens);
3623 subpat.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003624 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003625 }
3626 }
3627
Michael Layzell734adb42017-06-07 16:58:31 -04003628 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003629 impl ToTokens for PatStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003630 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003631 self.path.to_tokens(tokens);
3632 self.brace_token.surround(tokens, |tokens| {
3633 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003634 // NOTE: We need a comma before the dot2 token if it is present.
3635 if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003636 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003637 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003638 self.dot2_token.to_tokens(tokens);
3639 });
3640 }
3641 }
3642
Michael Layzell734adb42017-06-07 16:58:31 -04003643 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003644 impl ToTokens for PatTupleStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003645 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003646 self.path.to_tokens(tokens);
3647 self.pat.to_tokens(tokens);
3648 }
3649 }
3650
Michael Layzell734adb42017-06-07 16:58:31 -04003651 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003652 impl ToTokens for PatPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003653 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay12f3b6f2018-09-01 16:10:53 -07003654 private::print_path(tokens, &self.qself, &self.path);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003655 }
3656 }
3657
Michael Layzell734adb42017-06-07 16:58:31 -04003658 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003659 impl ToTokens for PatTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003660 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003661 self.paren_token.surround(tokens, |tokens| {
David Tolnay41871922017-12-29 01:53:45 -05003662 self.front.to_tokens(tokens);
3663 if let Some(ref dot2_token) = self.dot2_token {
3664 if !self.front.empty_or_trailing() {
3665 // Ensure there is a comma before the .. token.
David Tolnayf8db7ba2017-11-11 22:52:16 -08003666 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003667 }
David Tolnay41871922017-12-29 01:53:45 -05003668 dot2_token.to_tokens(tokens);
3669 self.comma_token.to_tokens(tokens);
3670 if self.comma_token.is_none() && !self.back.is_empty() {
3671 // Ensure there is a comma after the .. token.
3672 <Token![,]>::default().to_tokens(tokens);
3673 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07003674 }
David Tolnay41871922017-12-29 01:53:45 -05003675 self.back.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003676 });
3677 }
3678 }
3679
Michael Layzell734adb42017-06-07 16:58:31 -04003680 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003681 impl ToTokens for PatBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003682 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003683 self.box_token.to_tokens(tokens);
3684 self.pat.to_tokens(tokens);
3685 }
3686 }
3687
Michael Layzell734adb42017-06-07 16:58:31 -04003688 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003689 impl ToTokens for PatRef {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003690 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003691 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003692 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003693 self.pat.to_tokens(tokens);
3694 }
3695 }
3696
Michael Layzell734adb42017-06-07 16:58:31 -04003697 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003698 impl ToTokens for PatLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003699 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003700 self.expr.to_tokens(tokens);
3701 }
3702 }
3703
Michael Layzell734adb42017-06-07 16:58:31 -04003704 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003705 impl ToTokens for PatRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003706 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003707 self.lo.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003708 match self.limits {
3709 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
Jeb Rosen918e8de2019-06-19 18:42:43 -07003710 RangeLimits::Closed(ref t) => t.to_tokens(tokens),
David Tolnay475288a2017-12-19 22:59:44 -08003711 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003712 self.hi.to_tokens(tokens);
3713 }
3714 }
3715
Michael Layzell734adb42017-06-07 16:58:31 -04003716 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003717 impl ToTokens for PatSlice {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003718 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003719 self.bracket_token.surround(tokens, |tokens| {
3720 self.front.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003721
3722 // If we need a comma before the middle or standalone .. token,
3723 // then make sure it's present.
David Tolnay51382052017-12-27 13:46:21 -05003724 if !self.front.empty_or_trailing()
3725 && (self.middle.is_some() || self.dot2_token.is_some())
Michael Layzell3936ceb2017-07-08 00:28:36 -04003726 {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003727 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003728 }
3729
3730 // If we have an identifier, we always need a .. token.
3731 if self.middle.is_some() {
3732 self.middle.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -07003733 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003734 } else if self.dot2_token.is_some() {
3735 self.dot2_token.to_tokens(tokens);
3736 }
3737
3738 // Make sure we have a comma before the back half.
3739 if !self.back.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07003740 TokensOrDefault(&self.comma_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003741 self.back.to_tokens(tokens);
3742 } else {
3743 self.comma_token.to_tokens(tokens);
3744 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003745 })
David Tolnayb4ad3b52016-10-01 21:58:13 -07003746 }
3747 }
3748
Michael Layzell734adb42017-06-07 16:58:31 -04003749 #[cfg(feature = "full")]
David Tolnay323279a2017-12-29 11:26:32 -05003750 impl ToTokens for PatMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003751 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay323279a2017-12-29 11:26:32 -05003752 self.mac.to_tokens(tokens);
3753 }
3754 }
3755
3756 #[cfg(feature = "full")]
David Tolnay2ae520a2017-12-29 11:19:50 -05003757 impl ToTokens for PatVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003758 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003759 self.tts.to_tokens(tokens);
3760 }
3761 }
3762
3763 #[cfg(feature = "full")]
David Tolnay8d9e81a2016-10-03 22:36:32 -07003764 impl ToTokens for FieldPat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003765 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay5d7098a2017-12-29 01:35:24 -05003766 if let Some(ref colon_token) = self.colon_token {
David Tolnay85b69a42017-12-27 20:43:10 -05003767 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003768 colon_token.to_tokens(tokens);
David Tolnay8d9e81a2016-10-03 22:36:32 -07003769 }
3770 self.pat.to_tokens(tokens);
3771 }
3772 }
3773
Michael Layzell734adb42017-06-07 16:58:31 -04003774 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003775 impl ToTokens for Block {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003776 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003777 self.brace_token.surround(tokens, |tokens| {
3778 tokens.append_all(&self.stmts);
3779 });
David Tolnay42602292016-10-01 22:25:45 -07003780 }
3781 }
3782
Michael Layzell734adb42017-06-07 16:58:31 -04003783 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003784 impl ToTokens for Stmt {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003785 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay42602292016-10-01 22:25:45 -07003786 match *self {
David Tolnay191e0582016-10-02 18:31:09 -07003787 Stmt::Local(ref local) => local.to_tokens(tokens),
David Tolnay42602292016-10-01 22:25:45 -07003788 Stmt::Item(ref item) => item.to_tokens(tokens),
3789 Stmt::Expr(ref expr) => expr.to_tokens(tokens),
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003790 Stmt::Semi(ref expr, ref semi) => {
David Tolnay42602292016-10-01 22:25:45 -07003791 expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003792 semi.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -07003793 }
David Tolnay42602292016-10-01 22:25:45 -07003794 }
3795 }
3796 }
David Tolnay191e0582016-10-02 18:31:09 -07003797
Michael Layzell734adb42017-06-07 16:58:31 -04003798 #[cfg(feature = "full")]
David Tolnay191e0582016-10-02 18:31:09 -07003799 impl ToTokens for Local {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003800 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003801 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003802 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003803 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003804 if let Some((ref colon_token, ref ty)) = self.ty {
3805 colon_token.to_tokens(tokens);
3806 ty.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003807 }
David Tolnay8b4d3022017-12-29 12:11:10 -05003808 if let Some((ref eq_token, ref init)) = self.init {
3809 eq_token.to_tokens(tokens);
3810 init.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003811 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003812 self.semi_token.to_tokens(tokens);
David Tolnay191e0582016-10-02 18:31:09 -07003813 }
3814 }
David Tolnayf4bbbd92016-09-23 14:41:55 -07003815}