blob: 76c7e278dced30e9abae9995f4bd71ab0df2b3af [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,
997 Placement,
998 Range,
999 Or,
1000 And,
1001 Compare,
1002 BitOr,
1003 BitXor,
1004 BitAnd,
1005 Shift,
1006 Arithmetic,
1007 Term,
1008 Cast,
1009 }
1010
1011 impl Precedence {
1012 fn of(op: &BinOp) -> Self {
1013 match *op {
1014 BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic,
1015 BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term,
1016 BinOp::And(_) => Precedence::And,
1017 BinOp::Or(_) => Precedence::Or,
1018 BinOp::BitXor(_) => Precedence::BitXor,
1019 BinOp::BitAnd(_) => Precedence::BitAnd,
1020 BinOp::BitOr(_) => Precedence::BitOr,
1021 BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
David Tolnay73b7ca12018-08-30 21:05:13 -07001022 BinOp::Eq(_)
1023 | BinOp::Lt(_)
1024 | BinOp::Le(_)
1025 | BinOp::Ne(_)
1026 | BinOp::Ge(_)
1027 | BinOp::Gt(_) => Precedence::Compare,
1028 BinOp::AddEq(_)
1029 | BinOp::SubEq(_)
1030 | BinOp::MulEq(_)
1031 | BinOp::DivEq(_)
1032 | BinOp::RemEq(_)
1033 | BinOp::BitXorEq(_)
1034 | BinOp::BitAndEq(_)
1035 | BinOp::BitOrEq(_)
1036 | BinOp::ShlEq(_)
1037 | BinOp::ShrEq(_) => Precedence::Assign,
David Tolnay01218d12018-08-29 18:13:07 -07001038 }
1039 }
1040 }
1041
David Tolnay9389c382018-08-27 09:13:37 -07001042 impl Parse for Expr {
1043 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001044 ambiguous_expr(input, AllowStruct(true))
Alex Crichton954046c2017-05-30 21:49:42 -07001045 }
1046 }
1047
Michael Layzell734adb42017-06-07 16:58:31 -04001048 #[cfg(feature = "full")]
David Tolnay9fb0aed2018-08-27 10:23:12 -07001049 fn expr_no_struct(input: ParseStream) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001050 ambiguous_expr(input, AllowStruct(false))
David Tolnay9fb0aed2018-08-27 10:23:12 -07001051 }
David Tolnayaf2557e2016-10-24 11:52:21 -07001052
David Tolnay01218d12018-08-29 18:13:07 -07001053 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001054 fn parse_expr(
1055 input: ParseStream,
1056 mut lhs: Expr,
1057 allow_struct: AllowStruct,
1058 base: Precedence,
1059 ) -> Result<Expr> {
David Tolnay01218d12018-08-29 18:13:07 -07001060 loop {
David Tolnay73b7ca12018-08-30 21:05:13 -07001061 if input
1062 .fork()
1063 .parse::<BinOp>()
1064 .ok()
1065 .map_or(false, |op| Precedence::of(&op) >= base)
1066 {
David Tolnay01218d12018-08-29 18:13:07 -07001067 let op: BinOp = input.parse()?;
1068 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001069 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001070 loop {
1071 let next = peek_precedence(input);
1072 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001073 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001074 } else {
1075 break;
1076 }
1077 }
David Tolnay90276252018-08-31 10:50:08 -07001078 lhs = if precedence == Precedence::Assign {
1079 Expr::AssignOp(ExprAssignOp {
1080 attrs: Vec::new(),
1081 left: Box::new(lhs),
1082 op: op,
1083 right: Box::new(rhs),
1084 })
1085 } else {
1086 Expr::Binary(ExprBinary {
1087 attrs: Vec::new(),
1088 left: Box::new(lhs),
1089 op: op,
1090 right: Box::new(rhs),
1091 })
1092 };
David Tolnay73b7ca12018-08-30 21:05:13 -07001093 } else if Precedence::Assign >= base
1094 && input.peek(Token![=])
1095 && !input.peek(Token![==])
1096 && !input.peek(Token![=>])
1097 {
David Tolnay01218d12018-08-29 18:13:07 -07001098 let eq_token: Token![=] = input.parse()?;
David Tolnay7d2e1db2018-08-30 11:49:04 -07001099 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001100 loop {
1101 let next = peek_precedence(input);
1102 if next >= Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001103 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001104 } else {
1105 break;
1106 }
1107 }
1108 lhs = Expr::Assign(ExprAssign {
1109 attrs: Vec::new(),
1110 left: Box::new(lhs),
1111 eq_token: eq_token,
1112 right: Box::new(rhs),
1113 });
1114 } else if Precedence::Placement >= base && input.peek(Token![<-]) {
1115 let arrow_token: Token![<-] = input.parse()?;
David Tolnay7d2e1db2018-08-30 11:49:04 -07001116 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001117 loop {
1118 let next = peek_precedence(input);
1119 if next > Precedence::Placement {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001120 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001121 } else {
1122 break;
1123 }
1124 }
1125 lhs = Expr::InPlace(ExprInPlace {
1126 attrs: Vec::new(),
1127 place: Box::new(lhs),
1128 arrow_token: arrow_token,
1129 value: Box::new(rhs),
1130 });
1131 } else if Precedence::Range >= base && input.peek(Token![..]) {
1132 let limits: RangeLimits = input.parse()?;
1133 let rhs = if input.is_empty()
1134 || input.peek(Token![,])
1135 || input.peek(Token![;])
1136 || !allow_struct.0 && input.peek(token::Brace)
1137 {
1138 None
1139 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001140 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001141 loop {
1142 let next = peek_precedence(input);
1143 if next > Precedence::Range {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001144 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001145 } else {
1146 break;
1147 }
1148 }
1149 Some(rhs)
1150 };
1151 lhs = Expr::Range(ExprRange {
1152 attrs: Vec::new(),
1153 from: Some(Box::new(lhs)),
1154 limits: limits,
1155 to: rhs.map(Box::new),
1156 });
1157 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1158 let as_token: Token![as] = input.parse()?;
1159 let ty = input.call(Type::without_plus)?;
1160 lhs = Expr::Cast(ExprCast {
1161 attrs: Vec::new(),
1162 expr: Box::new(lhs),
1163 as_token: as_token,
1164 ty: Box::new(ty),
1165 });
1166 } else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) {
1167 let colon_token: Token![:] = input.parse()?;
1168 let ty = input.call(Type::without_plus)?;
1169 lhs = Expr::Type(ExprType {
1170 attrs: Vec::new(),
1171 expr: Box::new(lhs),
1172 colon_token: colon_token,
1173 ty: Box::new(ty),
1174 });
1175 } else {
1176 break;
1177 }
1178 }
1179 Ok(lhs)
1180 }
1181
David Tolnay3e541292018-08-30 11:42:15 -07001182 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001183 fn parse_expr(
1184 input: ParseStream,
1185 mut lhs: Expr,
1186 allow_struct: AllowStruct,
1187 base: Precedence,
1188 ) -> Result<Expr> {
David Tolnay3e541292018-08-30 11:42:15 -07001189 loop {
David Tolnay73b7ca12018-08-30 21:05:13 -07001190 if input
1191 .fork()
1192 .parse::<BinOp>()
1193 .ok()
1194 .map_or(false, |op| Precedence::of(&op) >= base)
1195 {
David Tolnay3e541292018-08-30 11:42:15 -07001196 let op: BinOp = input.parse()?;
1197 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001198 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay3e541292018-08-30 11:42:15 -07001199 loop {
1200 let next = peek_precedence(input);
1201 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001202 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay3e541292018-08-30 11:42:15 -07001203 } else {
1204 break;
1205 }
1206 }
1207 lhs = Expr::Binary(ExprBinary {
1208 attrs: Vec::new(),
1209 left: Box::new(lhs),
1210 op: op,
1211 right: Box::new(rhs),
1212 });
1213 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1214 let as_token: Token![as] = input.parse()?;
1215 let ty = input.call(Type::without_plus)?;
1216 lhs = Expr::Cast(ExprCast {
1217 attrs: Vec::new(),
1218 expr: Box::new(lhs),
1219 as_token: as_token,
1220 ty: Box::new(ty),
1221 });
1222 } else {
1223 break;
1224 }
1225 }
1226 Ok(lhs)
1227 }
1228
David Tolnay01218d12018-08-29 18:13:07 -07001229 fn peek_precedence(input: ParseStream) -> Precedence {
1230 if let Ok(op) = input.fork().parse() {
1231 Precedence::of(&op)
David Tolnay3e541292018-08-30 11:42:15 -07001232 } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
David Tolnay01218d12018-08-29 18:13:07 -07001233 Precedence::Assign
1234 } else if input.peek(Token![<-]) {
1235 Precedence::Placement
1236 } else if input.peek(Token![..]) {
1237 Precedence::Range
1238 } else if input.peek(Token![as]) || input.peek(Token![:]) && !input.peek(Token![::]) {
1239 Precedence::Cast
1240 } else {
1241 Precedence::Any
1242 }
1243 }
1244
David Tolnaybcf26022017-12-25 22:10:52 -05001245 // Parse an arbitrary expression.
David Tolnay73b7ca12018-08-30 21:05:13 -07001246 fn ambiguous_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001247 let lhs = unary_expr(input, allow_struct)?;
1248 parse_expr(input, lhs, allow_struct, Precedence::Any)
Michael Layzellb78f3b52017-06-04 19:03:03 -04001249 }
1250
David Tolnaybcf26022017-12-25 22:10:52 -05001251 // <UnOp> <trailer>
1252 // & <trailer>
1253 // &mut <trailer>
1254 // box <trailer>
Michael Layzell734adb42017-06-07 16:58:31 -04001255 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001256 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001257 let ahead = input.fork();
1258 ahead.call(Attribute::parse_outer)?;
1259 if ahead.peek(Token![&])
1260 || ahead.peek(Token![box])
1261 || ahead.peek(Token![*])
1262 || ahead.peek(Token![!])
1263 || ahead.peek(Token![-])
1264 {
1265 let attrs = input.call(Attribute::parse_outer)?;
1266 if input.peek(Token![&]) {
1267 Ok(Expr::Reference(ExprReference {
1268 attrs: attrs,
1269 and_token: input.parse()?,
1270 mutability: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001271 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001272 }))
1273 } else if input.peek(Token![box]) {
1274 Ok(Expr::Box(ExprBox {
1275 attrs: attrs,
1276 box_token: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001277 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001278 }))
1279 } else {
1280 Ok(Expr::Unary(ExprUnary {
1281 attrs: attrs,
1282 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001283 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001284 }))
1285 }
1286 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001287 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001288 }
1289 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001290
Michael Layzell734adb42017-06-07 16:58:31 -04001291 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001292 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001293 let ahead = input.fork();
1294 ahead.call(Attribute::parse_outer)?;
1295 if ahead.peek(Token![*]) || ahead.peek(Token![!]) || ahead.peek(Token![-]) {
1296 Ok(Expr::Unary(ExprUnary {
1297 attrs: input.call(Attribute::parse_outer)?,
1298 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001299 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001300 }))
1301 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001302 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001303 }
1304 }
Michael Layzell734adb42017-06-07 16:58:31 -04001305
David Tolnaybcf26022017-12-25 22:10:52 -05001306 // <atom> (..<args>) ...
1307 // <atom> . <ident> (..<args>) ...
1308 // <atom> . <ident> ...
1309 // <atom> . <lit> ...
1310 // <atom> [ <expr> ] ...
1311 // <atom> ? ...
Michael Layzell734adb42017-06-07 16:58:31 -04001312 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001313 fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay577fd312018-09-01 02:26:40 -07001314 if input.peek(token::Group) {
1315 return input.call(expr_group).map(Expr::Group);
1316 }
David Tolnay1501f7e2018-08-27 14:21:03 -07001317
David Tolnay577fd312018-09-01 02:26:40 -07001318 let outer_attrs = input.call(Attribute::parse_outer)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001319
David Tolnay577fd312018-09-01 02:26:40 -07001320 let atom = atom_expr(input, allow_struct)?;
1321 let mut e = trailer_helper(input, atom)?;
David Tolnay01218d12018-08-29 18:13:07 -07001322
David Tolnay577fd312018-09-01 02:26:40 -07001323 let inner_attrs = e.replace_attrs(Vec::new());
1324 let attrs = private::attrs(outer_attrs, inner_attrs);
David Tolnay01218d12018-08-29 18:13:07 -07001325 e.replace_attrs(attrs);
1326 Ok(e)
1327 }
1328
1329 #[cfg(feature = "full")]
1330 fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
David Tolnay1501f7e2018-08-27 14:21:03 -07001331 loop {
1332 if input.peek(token::Paren) {
1333 let content;
1334 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001335 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001336 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001337 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001338 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001339 });
1340 } else if input.peek(Token![.]) && !input.peek(Token![..]) {
1341 let dot_token: Token![.] = input.parse()?;
1342 let member: Member = input.parse()?;
1343 let turbofish = if member.is_named() && input.peek(Token![::]) {
1344 Some(MethodTurbofish {
1345 colon2_token: input.parse()?,
1346 lt_token: input.parse()?,
1347 args: {
1348 let mut args = Punctuated::new();
1349 loop {
1350 if input.peek(Token![>]) {
1351 break;
1352 }
David Tolnay310b3262018-08-30 15:33:00 -07001353 let value = input.call(generic_method_argument)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001354 args.push_value(value);
1355 if input.peek(Token![>]) {
1356 break;
1357 }
1358 let punct = input.parse()?;
1359 args.push_punct(punct);
1360 }
1361 args
1362 },
1363 gt_token: input.parse()?,
1364 })
1365 } else {
1366 None
1367 };
1368
1369 if turbofish.is_some() || input.peek(token::Paren) {
1370 if let Member::Named(method) = member {
1371 let content;
1372 e = Expr::MethodCall(ExprMethodCall {
1373 attrs: Vec::new(),
1374 receiver: Box::new(e),
1375 dot_token: dot_token,
1376 method: method,
1377 turbofish: turbofish,
1378 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001379 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001380 });
1381 continue;
1382 }
1383 }
1384
1385 e = Expr::Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -05001386 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001387 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001388 dot_token: dot_token,
David Tolnay85b69a42017-12-27 20:43:10 -05001389 member: member,
David Tolnay1501f7e2018-08-27 14:21:03 -07001390 });
1391 } else if input.peek(token::Bracket) {
1392 let content;
1393 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001394 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001395 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001396 bracket_token: bracketed!(content in input),
1397 index: content.parse()?,
1398 });
1399 } else if input.peek(Token![?]) {
1400 e = Expr::Try(ExprTry {
David Tolnay8c91b882017-12-28 23:04:32 -05001401 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001402 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001403 question_token: input.parse()?,
1404 });
1405 } else {
1406 break;
1407 }
1408 }
David Tolnay1501f7e2018-08-27 14:21:03 -07001409 Ok(e)
1410 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001411
Michael Layzell734adb42017-06-07 16:58:31 -04001412 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001413 fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001414 let mut e = atom_expr(input, allow_struct)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001415
1416 loop {
1417 if input.peek(token::Paren) {
1418 let content;
1419 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001420 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001421 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001422 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001423 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001424 });
1425 } else if input.peek(Token![.]) {
1426 e = Expr::Field(ExprField {
David Tolnayd5147742018-06-30 10:09:52 -07001427 attrs: Vec::new(),
1428 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001429 dot_token: input.parse()?,
1430 member: input.parse()?,
1431 });
1432 } else if input.peek(token::Bracket) {
1433 let content;
1434 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001435 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001436 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001437 bracket_token: bracketed!(content in input),
1438 index: content.parse()?,
1439 });
1440 } else {
1441 break;
1442 }
1443 }
1444
1445 Ok(e)
1446 }
Michael Layzell734adb42017-06-07 16:58:31 -04001447
David Tolnaya454c8f2018-01-07 01:01:10 -08001448 // Parse all atomic expressions which don't have to worry about precedence
David Tolnaybcf26022017-12-25 22:10:52 -05001449 // interactions, as they are fully contained.
Michael Layzell734adb42017-06-07 16:58:31 -04001450 #[cfg(feature = "full")]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001451 fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001452 if input.peek(token::Group) {
David Tolnay577fd312018-09-01 02:26:40 -07001453 input.call(expr_group).map(Expr::Group)
David Tolnay6e1e5052018-08-30 10:21:48 -07001454 } else if input.peek(Lit) {
Peter Hall04f42792019-04-02 16:58:45 +02001455 input.parse().map(Expr::Lit)
David Tolnay6e1e5052018-08-30 10:21:48 -07001456 } else if input.peek(Token![async])
1457 && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
1458 {
David Tolnay577fd312018-09-01 02:26:40 -07001459 input.call(expr_async).map(Expr::Async)
David Tolnay6e1e5052018-08-30 10:21:48 -07001460 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay577fd312018-09-01 02:26:40 -07001461 input.call(expr_try_block).map(Expr::TryBlock)
David Tolnay6e1e5052018-08-30 10:21:48 -07001462 } else if input.peek(Token![|])
1463 || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1464 || input.peek(Token![static])
1465 || input.peek(Token![move])
1466 {
David Tolnay577fd312018-09-01 02:26:40 -07001467 expr_closure(input, allow_struct).map(Expr::Closure)
David Tolnay6e1e5052018-08-30 10:21:48 -07001468 } else if input.peek(Ident)
1469 || input.peek(Token![::])
1470 || input.peek(Token![<])
1471 || input.peek(Token![self])
1472 || input.peek(Token![Self])
1473 || input.peek(Token![super])
1474 || input.peek(Token![extern])
1475 || input.peek(Token![crate])
1476 {
David Tolnay577fd312018-09-01 02:26:40 -07001477 path_or_macro_or_struct(input, allow_struct)
David Tolnay6e1e5052018-08-30 10:21:48 -07001478 } else if input.peek(token::Paren) {
David Tolnay577fd312018-09-01 02:26:40 -07001479 paren_or_tuple(input)
David Tolnay6e1e5052018-08-30 10:21:48 -07001480 } else if input.peek(Token![break]) {
David Tolnay577fd312018-09-01 02:26:40 -07001481 expr_break(input, allow_struct).map(Expr::Break)
David Tolnay6e1e5052018-08-30 10:21:48 -07001482 } else if input.peek(Token![continue]) {
David Tolnay577fd312018-09-01 02:26:40 -07001483 input.call(expr_continue).map(Expr::Continue)
David Tolnay6e1e5052018-08-30 10:21:48 -07001484 } else if input.peek(Token![return]) {
David Tolnay577fd312018-09-01 02:26:40 -07001485 expr_ret(input, allow_struct).map(Expr::Return)
David Tolnay6e1e5052018-08-30 10:21:48 -07001486 } else if input.peek(token::Bracket) {
David Tolnay577fd312018-09-01 02:26:40 -07001487 array_or_repeat(input)
David Tolnay9c119122018-09-01 18:47:02 -07001488 } else if input.peek(Token![let]) {
1489 input.call(expr_let).map(Expr::Let)
David Tolnay6e1e5052018-08-30 10:21:48 -07001490 } else if input.peek(Token![if]) {
Peter Hall04f42792019-04-02 16:58:45 +02001491 input.parse().map(Expr::If)
David Tolnay6e1e5052018-08-30 10:21:48 -07001492 } else if input.peek(Token![while]) {
Peter Hall04f42792019-04-02 16:58:45 +02001493 input.parse().map(Expr::While)
David Tolnay6e1e5052018-08-30 10:21:48 -07001494 } else if input.peek(Token![for]) {
Peter Hall04f42792019-04-02 16:58:45 +02001495 input.parse().map(Expr::ForLoop)
David Tolnay6e1e5052018-08-30 10:21:48 -07001496 } else if input.peek(Token![loop]) {
Peter Hall04f42792019-04-02 16:58:45 +02001497 input.parse().map(Expr::Loop)
David Tolnay6e1e5052018-08-30 10:21:48 -07001498 } else if input.peek(Token![match]) {
Peter Hall55f00f72019-04-02 16:50:57 +02001499 input.parse().map(Expr::Match)
David Tolnay6e1e5052018-08-30 10:21:48 -07001500 } else if input.peek(Token![yield]) {
David Tolnay577fd312018-09-01 02:26:40 -07001501 input.call(expr_yield).map(Expr::Yield)
David Tolnay6e1e5052018-08-30 10:21:48 -07001502 } else if input.peek(Token![unsafe]) {
David Tolnay577fd312018-09-01 02:26:40 -07001503 input.call(expr_unsafe).map(Expr::Unsafe)
David Tolnay7d2e1db2018-08-30 11:49:04 -07001504 } else if input.peek(token::Brace) {
David Tolnay577fd312018-09-01 02:26:40 -07001505 input.call(expr_block).map(Expr::Block)
David Tolnay6e1e5052018-08-30 10:21:48 -07001506 } else if input.peek(Token![..]) {
David Tolnay577fd312018-09-01 02:26:40 -07001507 expr_range(input, allow_struct).map(Expr::Range)
David Tolnay6e1e5052018-08-30 10:21:48 -07001508 } else if input.peek(Lifetime) {
1509 let the_label: Label = input.parse()?;
1510 let mut expr = if input.peek(Token![while]) {
Peter Hall04f42792019-04-02 16:58:45 +02001511 Expr::While(input.parse()?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001512 } else if input.peek(Token![for]) {
Peter Hall04f42792019-04-02 16:58:45 +02001513 Expr::ForLoop(input.parse()?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001514 } else if input.peek(Token![loop]) {
Peter Hall04f42792019-04-02 16:58:45 +02001515 Expr::Loop(input.parse()?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001516 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001517 Expr::Block(input.call(expr_block)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001518 } else {
1519 return Err(input.error("expected loop or block expression"));
1520 };
1521 match expr {
David Tolnay9c119122018-09-01 18:47:02 -07001522 Expr::While(ExprWhile { ref mut label, .. })
David Tolnay73b7ca12018-08-30 21:05:13 -07001523 | Expr::ForLoop(ExprForLoop { ref mut label, .. })
1524 | Expr::Loop(ExprLoop { ref mut label, .. })
1525 | Expr::Block(ExprBlock { ref mut label, .. }) => *label = Some(the_label),
David Tolnay6e1e5052018-08-30 10:21:48 -07001526 _ => unreachable!(),
1527 }
David Tolnay577fd312018-09-01 02:26:40 -07001528 Ok(expr)
David Tolnay6e1e5052018-08-30 10:21:48 -07001529 } else {
David Tolnay577fd312018-09-01 02:26:40 -07001530 Err(input.error("expected expression"))
1531 }
David Tolnay6e1e5052018-08-30 10:21:48 -07001532 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001533
Michael Layzell734adb42017-06-07 16:58:31 -04001534 #[cfg(not(feature = "full"))]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001535 fn atom_expr(input: ParseStream, _allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001536 if input.peek(Lit) {
Peter Hall04f42792019-04-02 16:58:45 +02001537 input.parse().map(Expr::Lit)
David Tolnay6e1e5052018-08-30 10:21:48 -07001538 } else if input.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07001539 input.call(expr_paren).map(Expr::Paren)
David Tolnay6e1e5052018-08-30 10:21:48 -07001540 } else if input.peek(Ident)
1541 || input.peek(Token![::])
1542 || input.peek(Token![<])
1543 || input.peek(Token![self])
1544 || input.peek(Token![Self])
1545 || input.peek(Token![super])
1546 || input.peek(Token![extern])
1547 || input.peek(Token![crate])
1548 {
1549 input.parse().map(Expr::Path)
1550 } else {
1551 Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
1552 }
1553 }
1554
1555 #[cfg(feature = "full")]
1556 fn path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1557 let expr: ExprPath = input.parse()?;
1558 if expr.qself.is_some() {
1559 return Ok(Expr::Path(expr));
1560 }
1561
1562 if input.peek(Token![!]) && !input.peek(Token![!=]) {
1563 let mut contains_arguments = false;
1564 for segment in &expr.path.segments {
1565 match segment.arguments {
1566 PathArguments::None => {}
1567 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
1568 contains_arguments = true;
1569 }
1570 }
1571 }
1572
1573 if !contains_arguments {
1574 let bang_token: Token![!] = input.parse()?;
1575 let (delimiter, tts) = mac::parse_delimiter(input)?;
1576 return Ok(Expr::Macro(ExprMacro {
1577 attrs: Vec::new(),
1578 mac: Macro {
1579 path: expr.path,
1580 bang_token: bang_token,
1581 delimiter: delimiter,
1582 tts: tts,
1583 },
1584 }));
1585 }
1586 }
1587
1588 if allow_struct.0 && input.peek(token::Brace) {
1589 let outer_attrs = Vec::new();
1590 expr_struct_helper(input, outer_attrs, expr.path).map(Expr::Struct)
1591 } else {
1592 Ok(Expr::Path(expr))
1593 }
1594 }
1595
1596 #[cfg(feature = "full")]
1597 fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
1598 let content;
1599 let paren_token = parenthesized!(content in input);
1600 let inner_attrs = content.call(Attribute::parse_inner)?;
1601 if content.is_empty() {
1602 return Ok(Expr::Tuple(ExprTuple {
1603 attrs: inner_attrs,
1604 paren_token: paren_token,
1605 elems: Punctuated::new(),
1606 }));
1607 }
1608
1609 let first: Expr = content.parse()?;
1610 if content.is_empty() {
1611 return Ok(Expr::Paren(ExprParen {
1612 attrs: inner_attrs,
1613 paren_token: paren_token,
1614 expr: Box::new(first),
1615 }));
1616 }
1617
1618 let mut elems = Punctuated::new();
1619 elems.push_value(first);
1620 while !content.is_empty() {
1621 let punct = content.parse()?;
1622 elems.push_punct(punct);
1623 if content.is_empty() {
1624 break;
1625 }
1626 let value = content.parse()?;
1627 elems.push_value(value);
1628 }
1629 Ok(Expr::Tuple(ExprTuple {
1630 attrs: inner_attrs,
1631 paren_token: paren_token,
1632 elems: elems,
1633 }))
1634 }
1635
1636 #[cfg(feature = "full")]
1637 fn array_or_repeat(input: ParseStream) -> Result<Expr> {
1638 let content;
1639 let bracket_token = bracketed!(content in input);
1640 let inner_attrs = content.call(Attribute::parse_inner)?;
1641 if content.is_empty() {
1642 return Ok(Expr::Array(ExprArray {
1643 attrs: inner_attrs,
1644 bracket_token: bracket_token,
1645 elems: Punctuated::new(),
1646 }));
1647 }
1648
1649 let first: Expr = content.parse()?;
1650 if content.is_empty() || content.peek(Token![,]) {
1651 let mut elems = Punctuated::new();
1652 elems.push_value(first);
1653 while !content.is_empty() {
1654 let punct = content.parse()?;
1655 elems.push_punct(punct);
1656 if content.is_empty() {
1657 break;
1658 }
1659 let value = content.parse()?;
1660 elems.push_value(value);
1661 }
1662 Ok(Expr::Array(ExprArray {
1663 attrs: inner_attrs,
1664 bracket_token: bracket_token,
1665 elems: elems,
1666 }))
1667 } else if content.peek(Token![;]) {
1668 let semi_token: Token![;] = content.parse()?;
1669 let len: Expr = content.parse()?;
1670 Ok(Expr::Repeat(ExprRepeat {
1671 attrs: inner_attrs,
1672 bracket_token: bracket_token,
1673 expr: Box::new(first),
1674 semi_token: semi_token,
1675 len: Box::new(len),
1676 }))
1677 } else {
1678 Err(content.error("expected `,` or `;`"))
1679 }
1680 }
Michael Layzell734adb42017-06-07 16:58:31 -04001681
Michael Layzell734adb42017-06-07 16:58:31 -04001682 #[cfg(feature = "full")]
David Tolnay01218d12018-08-29 18:13:07 -07001683 fn expr_early(input: ParseStream) -> Result<Expr> {
1684 let mut attrs = input.call(Attribute::parse_outer)?;
1685 let mut expr = if input.peek(Token![if]) {
Peter Hall04f42792019-04-02 16:58:45 +02001686 Expr::If(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001687 } else if input.peek(Token![while]) {
Peter Hall04f42792019-04-02 16:58:45 +02001688 Expr::While(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001689 } else if input.peek(Token![for]) {
Peter Hall04f42792019-04-02 16:58:45 +02001690 Expr::ForLoop(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001691 } else if input.peek(Token![loop]) {
Peter Hall04f42792019-04-02 16:58:45 +02001692 Expr::Loop(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001693 } else if input.peek(Token![match]) {
Peter Hall55f00f72019-04-02 16:50:57 +02001694 Expr::Match(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001695 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001696 Expr::TryBlock(input.call(expr_try_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001697 } else if input.peek(Token![unsafe]) {
David Tolnay310b3262018-08-30 15:33:00 -07001698 Expr::Unsafe(input.call(expr_unsafe)?)
David Tolnay01218d12018-08-29 18:13:07 -07001699 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001700 Expr::Block(input.call(expr_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001701 } else {
1702 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001703 let mut expr = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001704
1705 attrs.extend(expr.replace_attrs(Vec::new()));
1706 expr.replace_attrs(attrs);
1707
David Tolnay7d2e1db2018-08-30 11:49:04 -07001708 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001709 };
1710
1711 if input.peek(Token![.]) || input.peek(Token![?]) {
1712 expr = trailer_helper(input, expr)?;
1713
1714 attrs.extend(expr.replace_attrs(Vec::new()));
1715 expr.replace_attrs(attrs);
1716
1717 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001718 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001719 }
1720
1721 attrs.extend(expr.replace_attrs(Vec::new()));
1722 expr.replace_attrs(attrs);
1723 Ok(expr)
1724 }
Michael Layzell35418782017-06-07 09:20:25 -04001725
Peter Hall04f42792019-04-02 16:58:45 +02001726 impl Parse for ExprLit {
1727 fn parse(input: ParseStream) -> Result<Self> {
1728 Ok(ExprLit {
1729 attrs: Vec::new(),
1730 lit: input.parse()?,
1731 })
1732 }
David Tolnay8c91b882017-12-28 23:04:32 -05001733 }
1734
1735 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001736 fn expr_group(input: ParseStream) -> Result<ExprGroup> {
David Tolnay10951d52018-08-31 10:27:39 -07001737 let group = private::parse_group(input)?;
David Tolnay310b3262018-08-30 15:33:00 -07001738 Ok(ExprGroup {
1739 attrs: Vec::new(),
David Tolnayf57f76f2018-08-31 10:23:17 -07001740 group_token: group.token,
1741 expr: group.content.parse()?,
David Tolnay310b3262018-08-30 15:33:00 -07001742 })
1743 }
1744
1745 #[cfg(not(feature = "full"))]
1746 fn expr_paren(input: ParseStream) -> Result<ExprParen> {
1747 let content;
1748 Ok(ExprParen {
1749 attrs: Vec::new(),
1750 paren_token: parenthesized!(content in input),
1751 expr: content.parse()?,
1752 })
David Tolnay8c91b882017-12-28 23:04:32 -05001753 }
1754
David Tolnaye98775f2017-12-28 23:17:00 -05001755 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001756 fn generic_method_argument(input: ParseStream) -> Result<GenericMethodArgument> {
David Tolnayd60cfec2017-12-29 00:21:38 -05001757 // TODO parse const generics as well
David Tolnay8db2d662018-08-30 17:40:59 -07001758 input.parse().map(GenericMethodArgument::Type)
David Tolnayd60cfec2017-12-29 00:21:38 -05001759 }
1760
1761 #[cfg(feature = "full")]
David Tolnay9c119122018-09-01 18:47:02 -07001762 fn expr_let(input: ParseStream) -> Result<ExprLet> {
1763 Ok(ExprLet {
David Tolnay310b3262018-08-30 15:33:00 -07001764 attrs: Vec::new(),
David Tolnay310b3262018-08-30 15:33:00 -07001765 let_token: input.parse()?,
1766 pats: {
1767 let mut pats = Punctuated::new();
David Tolnaye2a6ffa2019-01-15 20:57:02 -08001768 input.parse::<Option<Token![|]>>()?;
David Tolnay310b3262018-08-30 15:33:00 -07001769 let value: Pat = input.parse()?;
1770 pats.push_value(value);
David Tolnay73b7ca12018-08-30 21:05:13 -07001771 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
David Tolnay310b3262018-08-30 15:33:00 -07001772 let punct = input.parse()?;
1773 pats.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07001774 let value: Pat = input.parse()?;
1775 pats.push_value(value);
David Tolnay310b3262018-08-30 15:33:00 -07001776 }
1777 pats
1778 },
1779 eq_token: input.parse()?,
1780 expr: Box::new(input.call(expr_no_struct)?),
David Tolnay310b3262018-08-30 15:33:00 -07001781 })
David Tolnay29f9ce12016-10-02 20:58:40 -07001782 }
1783
Michael Layzell734adb42017-06-07 16:58:31 -04001784 #[cfg(feature = "full")]
Peter Hall04f42792019-04-02 16:58:45 +02001785 impl Parse for ExprIf {
1786 fn parse(input: ParseStream) -> Result<Self> {
1787 Ok(ExprIf {
1788 attrs: Vec::new(),
1789 if_token: input.parse()?,
1790 cond: Box::new(input.call(expr_no_struct)?),
1791 then_branch: input.parse()?,
1792 else_branch: {
1793 if input.peek(Token![else]) {
1794 Some(input.call(else_block)?)
1795 } else {
1796 None
1797 }
1798 },
1799 })
1800 }
Alex Crichton954046c2017-05-30 21:49:42 -07001801 }
David Tolnaybb6feae2016-10-02 21:25:20 -07001802
Michael Layzell734adb42017-06-07 16:58:31 -04001803 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001804 fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
1805 let else_token: Token![else] = input.parse()?;
1806
1807 let lookahead = input.lookahead1();
1808 let else_branch = if input.peek(Token![if]) {
Peter Hall04f42792019-04-02 16:58:45 +02001809 input.parse().map(Expr::If)?
David Tolnay60291082018-08-28 09:54:49 -07001810 } else if input.peek(token::Brace) {
1811 Expr::Block(ExprBlock {
1812 attrs: Vec::new(),
1813 label: None,
1814 block: input.parse()?,
1815 })
1816 } else {
1817 return Err(lookahead.error());
1818 };
1819
1820 Ok((else_token, Box::new(else_branch)))
1821 }
David Tolnay939766a2016-09-23 23:48:12 -07001822
Michael Layzell734adb42017-06-07 16:58:31 -04001823 #[cfg(feature = "full")]
Peter Hall04f42792019-04-02 16:58:45 +02001824 impl Parse for ExprForLoop {
1825 fn parse(input: ParseStream) -> Result<Self> {
1826 let label: Option<Label> = input.parse()?;
1827 let for_token: Token![for] = input.parse()?;
1828 let pat: Pat = input.parse()?;
1829 let in_token: Token![in] = input.parse()?;
1830 let expr: Expr = input.call(expr_no_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07001831
Peter Hall04f42792019-04-02 16:58:45 +02001832 let content;
1833 let brace_token = braced!(content in input);
1834 let inner_attrs = content.call(Attribute::parse_inner)?;
1835 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07001836
Peter Hall04f42792019-04-02 16:58:45 +02001837 Ok(ExprForLoop {
1838 attrs: inner_attrs,
1839 label: label,
1840 for_token: for_token,
1841 pat: Box::new(pat),
1842 in_token: in_token,
1843 expr: Box::new(expr),
1844 body: Block {
1845 brace_token: brace_token,
1846 stmts: stmts,
1847 },
1848 })
1849 }
Alex Crichton954046c2017-05-30 21:49:42 -07001850 }
David Tolnay1978c672016-10-27 22:05:52 -07001851
Michael Layzell734adb42017-06-07 16:58:31 -04001852 #[cfg(feature = "full")]
Peter Hall04f42792019-04-02 16:58:45 +02001853 impl Parse for ExprLoop {
1854 fn parse(input: ParseStream) -> Result<Self> {
1855 let label: Option<Label> = input.parse()?;
1856 let loop_token: Token![loop] = input.parse()?;
David Tolnay310b3262018-08-30 15:33:00 -07001857
Peter Hall04f42792019-04-02 16:58:45 +02001858 let content;
1859 let brace_token = braced!(content in input);
1860 let inner_attrs = content.call(Attribute::parse_inner)?;
1861 let stmts = content.call(Block::parse_within)?;
David Tolnay310b3262018-08-30 15:33:00 -07001862
Peter Hall04f42792019-04-02 16:58:45 +02001863 Ok(ExprLoop {
1864 attrs: inner_attrs,
1865 label: label,
1866 loop_token: loop_token,
1867 body: Block {
1868 brace_token: brace_token,
1869 stmts: stmts,
1870 },
1871 })
1872 }
Alex Crichton954046c2017-05-30 21:49:42 -07001873 }
Arnavion02ef13f2017-04-25 00:54:31 -07001874
Michael Layzell734adb42017-06-07 16:58:31 -04001875 #[cfg(feature = "full")]
Peter Hall55f00f72019-04-02 16:50:57 +02001876 impl Parse for ExprMatch {
1877 fn parse(input: ParseStream) -> Result<Self> {
1878 let match_token: Token![match] = input.parse()?;
1879 let expr = expr_no_struct(input)?;
David Tolnay310b3262018-08-30 15:33:00 -07001880
Peter Hall55f00f72019-04-02 16:50:57 +02001881 let content;
1882 let brace_token = braced!(content in input);
1883 let inner_attrs = content.call(Attribute::parse_inner)?;
David Tolnay310b3262018-08-30 15:33:00 -07001884
Peter Hall55f00f72019-04-02 16:50:57 +02001885 let mut arms = Vec::new();
1886 while !content.is_empty() {
1887 arms.push(content.call(Arm::parse)?);
1888 }
1889
1890 Ok(ExprMatch {
1891 attrs: inner_attrs,
1892 match_token: match_token,
1893 expr: Box::new(expr),
1894 brace_token: brace_token,
1895 arms: arms,
1896 })
David Tolnay310b3262018-08-30 15:33:00 -07001897 }
David Tolnay310b3262018-08-30 15:33:00 -07001898 }
1899
bstriecde20e62019-05-05 13:29:15 -04001900 macro_rules! impl_by_parsing_expr {
David Tolnaya58223d2019-05-07 21:58:15 -07001901 ($expr_type:ty, $variant:ident, $msg:expr) => {
bstrie6c50fdb2019-05-01 16:29:13 -04001902 #[cfg(all(feature = "full", feature = "printing"))]
bstrieb7f8aaf2019-04-30 20:20:25 -04001903 impl Parse for $expr_type {
1904 fn parse(input: ParseStream) -> Result<Self> {
bstrie1626c372019-05-05 13:44:57 -04001905 let mut expr: Expr = input.parse()?;
1906 loop {
1907 match expr {
1908 Expr::$variant(inner) => return Ok(inner),
1909 Expr::Group(ExprGroup { expr: next, .. }) => expr = *next,
David Tolnaya58223d2019-05-07 21:58:15 -07001910 _ => return Err(Error::new_spanned(expr, $msg)),
bstrie1626c372019-05-05 13:44:57 -04001911 }
bstrieb7f8aaf2019-04-30 20:20:25 -04001912 }
1913 }
bstrie7b4f52d2019-04-30 18:44:21 -04001914 }
David Tolnaya58223d2019-05-07 21:58:15 -07001915 };
bstrie7b4f52d2019-04-30 18:44:21 -04001916 }
1917
bstriecde20e62019-05-05 13:29:15 -04001918 impl_by_parsing_expr!(ExprBox, Box, "expected box expression");
1919 impl_by_parsing_expr!(ExprInPlace, InPlace, "expected placement expression");
1920 impl_by_parsing_expr!(ExprArray, Array, "expected slice literal expression");
1921 impl_by_parsing_expr!(ExprCall, Call, "expected function call expression");
1922 impl_by_parsing_expr!(ExprMethodCall, MethodCall, "expected method call expression");
1923 impl_by_parsing_expr!(ExprTuple, Tuple, "expected tuple expression");
1924 impl_by_parsing_expr!(ExprBinary, Binary, "expected binary operation");
1925 impl_by_parsing_expr!(ExprUnary, Unary, "expected unary operation");
1926 impl_by_parsing_expr!(ExprCast, Cast, "expected cast expression");
1927 impl_by_parsing_expr!(ExprType, Type, "expected type ascription expression");
1928 impl_by_parsing_expr!(ExprLet, Let, "expected let guard");
1929 impl_by_parsing_expr!(ExprClosure, Closure, "expected closure expression");
1930 impl_by_parsing_expr!(ExprUnsafe, Unsafe, "expected unsafe block");
1931 impl_by_parsing_expr!(ExprBlock, Block, "expected blocked scope");
1932 impl_by_parsing_expr!(ExprAssign, Assign, "expected assignment expression");
1933 impl_by_parsing_expr!(ExprAssignOp, AssignOp, "expected compound assignment expression");
1934 impl_by_parsing_expr!(ExprField, Field, "expected struct field access");
1935 impl_by_parsing_expr!(ExprIndex, Index, "expected indexing expression");
1936 impl_by_parsing_expr!(ExprRange, Range, "expected range expression");
1937 impl_by_parsing_expr!(ExprReference, Reference, "expected referencing operation");
1938 impl_by_parsing_expr!(ExprBreak, Break, "expected break expression");
1939 impl_by_parsing_expr!(ExprContinue, Continue, "expected continue expression");
1940 impl_by_parsing_expr!(ExprReturn, Return, "expected return expression");
1941 impl_by_parsing_expr!(ExprMacro, Macro, "expected macro invocation expression");
1942 impl_by_parsing_expr!(ExprStruct, Struct, "expected struct literal expression");
1943 impl_by_parsing_expr!(ExprRepeat, Repeat, "expected array literal constructed from one repeated element");
1944 impl_by_parsing_expr!(ExprParen, Paren, "expected parenthesized expression");
1945 impl_by_parsing_expr!(ExprTry, Try, "expected try expression");
1946 impl_by_parsing_expr!(ExprAsync, Async, "expected async block");
1947 impl_by_parsing_expr!(ExprTryBlock, TryBlock, "expected try block");
1948 impl_by_parsing_expr!(ExprYield, Yield, "expected yield expression");
bstrieb7f8aaf2019-04-30 20:20:25 -04001949
David Tolnay310b3262018-08-30 15:33:00 -07001950 #[cfg(feature = "full")]
1951 fn expr_try_block(input: ParseStream) -> Result<ExprTryBlock> {
1952 Ok(ExprTryBlock {
1953 attrs: Vec::new(),
1954 try_token: input.parse()?,
1955 block: input.parse()?,
1956 })
1957 }
1958
1959 #[cfg(feature = "full")]
1960 fn expr_yield(input: ParseStream) -> Result<ExprYield> {
1961 Ok(ExprYield {
1962 attrs: Vec::new(),
1963 yield_token: input.parse()?,
1964 expr: {
1965 if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
1966 Some(input.parse()?)
1967 } else {
1968 None
1969 }
1970 },
1971 })
1972 }
1973
1974 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001975 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
David Tolnay60291082018-08-28 09:54:49 -07001976 let asyncness: Option<Token![async]> = input.parse()?;
1977 let movability: Option<Token![static]> = if asyncness.is_none() {
1978 input.parse()?
1979 } else {
1980 None
1981 };
1982 let capture: Option<Token![move]> = input.parse()?;
1983 let or1_token: Token![|] = input.parse()?;
1984
1985 let mut inputs = Punctuated::new();
1986 loop {
1987 if input.peek(Token![|]) {
1988 break;
1989 }
1990 let value = fn_arg(input)?;
1991 inputs.push_value(value);
1992 if input.peek(Token![|]) {
1993 break;
1994 }
1995 let punct: Token![,] = input.parse()?;
1996 inputs.push_punct(punct);
1997 }
1998
1999 let or2_token: Token![|] = input.parse()?;
2000
2001 let (output, body) = if input.peek(Token![->]) {
2002 let arrow_token: Token![->] = input.parse()?;
2003 let ty: Type = input.parse()?;
2004 let body: Block = input.parse()?;
2005 let output = ReturnType::Type(arrow_token, Box::new(ty));
2006 let block = Expr::Block(ExprBlock {
2007 attrs: Vec::new(),
2008 label: None,
2009 block: body,
2010 });
2011 (output, block)
2012 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002013 let body = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002014 (ReturnType::Default, body)
2015 };
2016
2017 Ok(ExprClosure {
David Tolnay310b3262018-08-30 15:33:00 -07002018 attrs: Vec::new(),
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002019 asyncness: asyncness,
2020 movability: movability,
2021 capture: capture,
David Tolnay60291082018-08-28 09:54:49 -07002022 or1_token: or1_token,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002023 inputs: inputs,
David Tolnay60291082018-08-28 09:54:49 -07002024 or2_token: or2_token,
2025 output: output,
2026 body: Box::new(body),
2027 })
David Tolnay02a9c6f2018-08-24 18:58:45 -04002028 }
Yusuke Sasaki851062f2018-08-01 06:28:28 +09002029
2030 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002031 fn expr_async(input: ParseStream) -> Result<ExprAsync> {
2032 Ok(ExprAsync {
2033 attrs: Vec::new(),
2034 async_token: input.parse()?,
2035 capture: input.parse()?,
2036 block: input.parse()?,
2037 })
David Tolnay60291082018-08-28 09:54:49 -07002038 }
Gregory Katz3e562cc2016-09-28 18:33:02 -04002039
Michael Layzell734adb42017-06-07 16:58:31 -04002040 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002041 fn fn_arg(input: ParseStream) -> Result<FnArg> {
2042 let pat: Pat = input.parse()?;
2043
2044 if input.peek(Token![:]) {
2045 Ok(FnArg::Captured(ArgCaptured {
2046 pat: pat,
2047 colon_token: input.parse()?,
2048 ty: input.parse()?,
2049 }))
2050 } else {
2051 Ok(FnArg::Inferred(pat))
2052 }
2053 }
2054
2055 #[cfg(feature = "full")]
Peter Hall04f42792019-04-02 16:58:45 +02002056 impl Parse for ExprWhile {
2057 fn parse(input: ParseStream) -> Result<Self> {
2058 let label: Option<Label> = input.parse()?;
2059 let while_token: Token![while] = input.parse()?;
2060 let cond = expr_no_struct(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002061
Peter Hall04f42792019-04-02 16:58:45 +02002062 let content;
2063 let brace_token = braced!(content in input);
2064 let inner_attrs = content.call(Attribute::parse_inner)?;
2065 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002066
Peter Hall04f42792019-04-02 16:58:45 +02002067 Ok(ExprWhile {
2068 attrs: inner_attrs,
2069 label: label,
2070 while_token: while_token,
2071 cond: Box::new(cond),
2072 body: Block {
2073 brace_token: brace_token,
2074 stmts: stmts,
2075 },
2076 })
2077 }
Alex Crichton954046c2017-05-30 21:49:42 -07002078 }
2079
Michael Layzell734adb42017-06-07 16:58:31 -04002080 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002081 impl Parse for Label {
2082 fn parse(input: ParseStream) -> Result<Self> {
2083 Ok(Label {
2084 name: input.parse()?,
2085 colon_token: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04002086 })
David Tolnay60291082018-08-28 09:54:49 -07002087 }
Alex Crichton954046c2017-05-30 21:49:42 -07002088 }
2089
Michael Layzell734adb42017-06-07 16:58:31 -04002090 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002091 impl Parse for Option<Label> {
2092 fn parse(input: ParseStream) -> Result<Self> {
2093 if input.peek(Lifetime) {
2094 input.parse().map(Some)
2095 } else {
2096 Ok(None)
2097 }
2098 }
2099 }
2100
2101 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002102 fn expr_continue(input: ParseStream) -> Result<ExprContinue> {
2103 Ok(ExprContinue {
2104 attrs: Vec::new(),
2105 continue_token: input.parse()?,
2106 label: input.parse()?,
2107 })
Alex Crichton954046c2017-05-30 21:49:42 -07002108 }
Gregory Katzfd6935d2016-09-30 22:51:25 -04002109
Michael Layzell734adb42017-06-07 16:58:31 -04002110 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002111 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2112 Ok(ExprBreak {
David Tolnay310b3262018-08-30 15:33:00 -07002113 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002114 break_token: input.parse()?,
2115 label: input.parse()?,
2116 expr: {
2117 if input.is_empty()
2118 || input.peek(Token![,])
2119 || input.peek(Token![;])
2120 || !allow_struct.0 && input.peek(token::Brace)
2121 {
2122 None
2123 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002124 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002125 Some(Box::new(expr))
Michael Layzell92639a52017-06-01 00:07:44 -04002126 }
David Tolnay60291082018-08-28 09:54:49 -07002127 },
2128 })
Alex Crichton954046c2017-05-30 21:49:42 -07002129 }
2130
Michael Layzell734adb42017-06-07 16:58:31 -04002131 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002132 fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
2133 Ok(ExprReturn {
David Tolnay310b3262018-08-30 15:33:00 -07002134 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002135 return_token: input.parse()?,
2136 expr: {
2137 if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
2138 None
2139 } else {
2140 // NOTE: return is greedy and eats blocks after it even when in a
2141 // position where structs are not allowed, such as in if statement
2142 // conditions. For example:
2143 //
2144 // if return { println!("A") } {} // Prints "A"
David Tolnay7d2e1db2018-08-30 11:49:04 -07002145 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002146 Some(Box::new(expr))
2147 }
2148 },
2149 })
2150 }
2151
2152 #[cfg(feature = "full")]
David Tolnaya7aa4ee2018-09-02 12:15:00 -07002153 impl Parse for FieldValue {
2154 fn parse(input: ParseStream) -> Result<Self> {
2155 let member: Member = input.parse()?;
2156 let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
2157 let colon_token: Token![:] = input.parse()?;
2158 let value: Expr = input.parse()?;
2159 (Some(colon_token), value)
2160 } else if let Member::Named(ref ident) = member {
2161 let value = Expr::Path(ExprPath {
2162 attrs: Vec::new(),
2163 qself: None,
2164 path: Path::from(ident.clone()),
2165 });
2166 (None, value)
2167 } else {
2168 unreachable!()
2169 };
2170
2171 Ok(FieldValue {
2172 attrs: Vec::new(),
2173 member: member,
2174 colon_token: colon_token,
2175 expr: value,
2176 })
2177 }
2178 }
2179
2180 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07002181 fn expr_struct_helper(
2182 input: ParseStream,
2183 outer_attrs: Vec<Attribute>,
2184 path: Path,
2185 ) -> Result<ExprStruct> {
David Tolnay6e1e5052018-08-30 10:21:48 -07002186 let content;
2187 let brace_token = braced!(content in input);
2188 let inner_attrs = content.call(Attribute::parse_inner)?;
David Tolnay60291082018-08-28 09:54:49 -07002189
David Tolnay6e1e5052018-08-30 10:21:48 -07002190 let mut fields = Punctuated::new();
2191 loop {
2192 let attrs = content.call(Attribute::parse_outer)?;
2193 if content.fork().parse::<Member>().is_err() {
2194 if attrs.is_empty() {
David Tolnay60291082018-08-28 09:54:49 -07002195 break;
David Tolnay6e1e5052018-08-30 10:21:48 -07002196 } else {
2197 return Err(content.error("expected struct field"));
David Tolnay60291082018-08-28 09:54:49 -07002198 }
David Tolnay60291082018-08-28 09:54:49 -07002199 }
2200
David Tolnay6e1e5052018-08-30 10:21:48 -07002201 fields.push(FieldValue {
2202 attrs: attrs,
David Tolnaya7aa4ee2018-09-02 12:15:00 -07002203 ..content.parse()?
David Tolnay6e1e5052018-08-30 10:21:48 -07002204 });
2205
2206 if !content.peek(Token![,]) {
2207 break;
2208 }
2209 let punct: Token![,] = content.parse()?;
2210 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002211 }
David Tolnay6e1e5052018-08-30 10:21:48 -07002212
2213 let (dot2_token, rest) = if fields.empty_or_trailing() && content.peek(Token![..]) {
2214 let dot2_token: Token![..] = content.parse()?;
2215 let rest: Expr = content.parse()?;
2216 (Some(dot2_token), Some(Box::new(rest)))
2217 } else {
2218 (None, None)
2219 };
2220
2221 Ok(ExprStruct {
David Tolnayb5f6fc02018-09-01 02:18:50 -07002222 attrs: private::attrs(outer_attrs, inner_attrs),
David Tolnay6e1e5052018-08-30 10:21:48 -07002223 brace_token: brace_token,
2224 path: path,
2225 fields: fields,
2226 dot2_token: dot2_token,
2227 rest: rest,
2228 })
Alex Crichton954046c2017-05-30 21:49:42 -07002229 }
David Tolnay055a7042016-10-02 19:23:54 -07002230
Michael Layzell734adb42017-06-07 16:58:31 -04002231 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002232 fn expr_unsafe(input: ParseStream) -> Result<ExprUnsafe> {
2233 let unsafe_token: Token![unsafe] = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002234
David Tolnay310b3262018-08-30 15:33:00 -07002235 let content;
2236 let brace_token = braced!(content in input);
2237 let inner_attrs = content.call(Attribute::parse_inner)?;
2238 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002239
David Tolnay310b3262018-08-30 15:33:00 -07002240 Ok(ExprUnsafe {
2241 attrs: inner_attrs,
2242 unsafe_token: unsafe_token,
2243 block: Block {
2244 brace_token: brace_token,
2245 stmts: stmts,
2246 },
2247 })
Alex Crichton954046c2017-05-30 21:49:42 -07002248 }
David Tolnay055a7042016-10-02 19:23:54 -07002249
Michael Layzell734adb42017-06-07 16:58:31 -04002250 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002251 pub fn expr_block(input: ParseStream) -> Result<ExprBlock> {
2252 let label: Option<Label> = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002253
David Tolnay310b3262018-08-30 15:33:00 -07002254 let content;
2255 let brace_token = braced!(content in input);
2256 let inner_attrs = content.call(Attribute::parse_inner)?;
2257 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002258
David Tolnay310b3262018-08-30 15:33:00 -07002259 Ok(ExprBlock {
2260 attrs: inner_attrs,
2261 label: label,
2262 block: Block {
2263 brace_token: brace_token,
2264 stmts: stmts,
2265 },
2266 })
Alex Crichton954046c2017-05-30 21:49:42 -07002267 }
David Tolnay89e05672016-10-02 14:39:42 -07002268
Michael Layzell734adb42017-06-07 16:58:31 -04002269 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002270 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2271 Ok(ExprRange {
David Tolnay8c91b882017-12-28 23:04:32 -05002272 attrs: Vec::new(),
2273 from: None,
David Tolnay60291082018-08-28 09:54:49 -07002274 limits: input.parse()?,
2275 to: {
2276 if input.is_empty()
2277 || input.peek(Token![,])
2278 || input.peek(Token![;])
2279 || !allow_struct.0 && input.peek(token::Brace)
2280 {
2281 None
2282 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002283 let to = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002284 Some(Box::new(to))
2285 }
2286 },
2287 })
2288 }
David Tolnay438c9052016-10-07 23:24:48 -07002289
Michael Layzell734adb42017-06-07 16:58:31 -04002290 #[cfg(feature = "full")]
David Tolnayc4c631e2018-08-27 10:44:37 -07002291 impl Parse for RangeLimits {
2292 fn parse(input: ParseStream) -> Result<Self> {
2293 let lookahead = input.lookahead1();
2294 if lookahead.peek(Token![..=]) {
2295 input.parse().map(RangeLimits::Closed)
2296 } else if lookahead.peek(Token![...]) {
2297 let dot3: Token![...] = input.parse()?;
2298 Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2299 } else if lookahead.peek(Token![..]) {
2300 input.parse().map(RangeLimits::HalfOpen)
2301 } else {
2302 Err(lookahead.error())
2303 }
2304 }
Alex Crichton954046c2017-05-30 21:49:42 -07002305 }
David Tolnay438c9052016-10-07 23:24:48 -07002306
David Tolnay60291082018-08-28 09:54:49 -07002307 impl Parse for ExprPath {
2308 fn parse(input: ParseStream) -> Result<Self> {
2309 #[cfg(not(feature = "full"))]
2310 let attrs = Vec::new();
2311 #[cfg(feature = "full")]
2312 let attrs = input.call(Attribute::parse_outer)?;
David Tolnayeb981bb2018-07-21 19:31:38 -07002313
David Tolnay60291082018-08-28 09:54:49 -07002314 let (qself, path) = path::parsing::qpath(input, true)?;
2315
2316 Ok(ExprPath {
David Tolnay73c9b522018-07-21 15:58:40 -07002317 attrs: attrs,
David Tolnay60291082018-08-28 09:54:49 -07002318 qself: qself,
2319 path: path,
Michael Layzell92639a52017-06-01 00:07:44 -04002320 })
David Tolnay60291082018-08-28 09:54:49 -07002321 }
Alex Crichton954046c2017-05-30 21:49:42 -07002322 }
David Tolnay42602292016-10-01 22:25:45 -07002323
Michael Layzell734adb42017-06-07 16:58:31 -04002324 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002325 impl Parse for Block {
2326 fn parse(input: ParseStream) -> Result<Self> {
2327 let content;
2328 Ok(Block {
2329 brace_token: braced!(content in input),
2330 stmts: content.call(Block::parse_within)?,
Michael Layzell92639a52017-06-01 00:07:44 -04002331 })
David Tolnay60291082018-08-28 09:54:49 -07002332 }
Alex Crichton954046c2017-05-30 21:49:42 -07002333 }
David Tolnay939766a2016-09-23 23:48:12 -07002334
Michael Layzell734adb42017-06-07 16:58:31 -04002335 #[cfg(feature = "full")]
Alex Crichton954046c2017-05-30 21:49:42 -07002336 impl Block {
David Tolnay6b457252018-09-01 15:55:47 -07002337 /// Parse the body of a block as zero or more statements, possibly
2338 /// including one trailing expression.
2339 ///
David Tolnay206edfb2018-09-01 16:02:20 -07002340 /// *This function is available if Syn is built with the `"parsing"`
2341 /// feature.*
2342 ///
David Tolnay6b457252018-09-01 15:55:47 -07002343 /// # Example
2344 ///
David Tolnay95989db2019-01-01 15:05:57 -05002345 /// ```edition2018
David Tolnayfd5b1172018-12-31 17:54:36 -05002346 /// use syn::{braced, token, Attribute, Block, Ident, Result, Stmt, Token};
David Tolnay67fea042018-11-24 14:50:20 -08002347 /// use syn::parse::{Parse, ParseStream};
David Tolnay6b457252018-09-01 15:55:47 -07002348 ///
2349 /// // Parse a function with no generics or parameter list.
David Tolnaye7ea1652018-09-02 09:11:54 -07002350 /// //
2351 /// // fn playground {
2352 /// // let mut x = 1;
2353 /// // x += 1;
2354 /// // println!("{}", x);
2355 /// // }
David Tolnay6b457252018-09-01 15:55:47 -07002356 /// struct MiniFunction {
2357 /// attrs: Vec<Attribute>,
2358 /// fn_token: Token![fn],
2359 /// name: Ident,
2360 /// brace_token: token::Brace,
2361 /// stmts: Vec<Stmt>,
2362 /// }
2363 ///
2364 /// impl Parse for MiniFunction {
2365 /// fn parse(input: ParseStream) -> Result<Self> {
2366 /// let outer_attrs = input.call(Attribute::parse_outer)?;
2367 /// let fn_token: Token![fn] = input.parse()?;
2368 /// let name: Ident = input.parse()?;
2369 ///
2370 /// let content;
2371 /// let brace_token = braced!(content in input);
2372 /// let inner_attrs = content.call(Attribute::parse_inner)?;
2373 /// let stmts = content.call(Block::parse_within)?;
2374 ///
2375 /// Ok(MiniFunction {
2376 /// attrs: {
2377 /// let mut attrs = outer_attrs;
2378 /// attrs.extend(inner_attrs);
2379 /// attrs
2380 /// },
2381 /// fn_token: fn_token,
2382 /// name: name,
2383 /// brace_token: brace_token,
2384 /// stmts: stmts,
2385 /// })
2386 /// }
2387 /// }
David Tolnay6b457252018-09-01 15:55:47 -07002388 /// ```
David Tolnay9389c382018-08-27 09:13:37 -07002389 pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002390 let mut stmts = Vec::new();
David Tolnay7158c5f2018-08-30 17:28:34 -07002391 loop {
2392 while input.peek(Token![;]) {
2393 input.parse::<Token![;]>()?;
Michael Layzell92639a52017-06-01 00:07:44 -04002394 }
David Tolnay7158c5f2018-08-30 17:28:34 -07002395 if input.is_empty() {
2396 break;
2397 }
2398 let s = parse_stmt(input, true)?;
2399 let requires_semicolon = if let Stmt::Expr(ref s) = s {
2400 requires_terminator(s)
2401 } else {
2402 false
2403 };
David Tolnaye532d6b2018-08-30 16:55:01 -07002404 stmts.push(s);
David Tolnay7158c5f2018-08-30 17:28:34 -07002405 if input.is_empty() {
2406 break;
2407 } else if requires_semicolon {
2408 return Err(input.error("unexpected token"));
2409 }
David Tolnaye532d6b2018-08-30 16:55:01 -07002410 }
2411 Ok(stmts)
2412 }
Alex Crichton954046c2017-05-30 21:49:42 -07002413 }
2414
Michael Layzell734adb42017-06-07 16:58:31 -04002415 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002416 impl Parse for Stmt {
2417 fn parse(input: ParseStream) -> Result<Self> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002418 parse_stmt(input, false)
2419 }
2420 }
David Tolnay939766a2016-09-23 23:48:12 -07002421
David Tolnaye532d6b2018-08-30 16:55:01 -07002422 #[cfg(feature = "full")]
2423 fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
2424 let ahead = input.fork();
2425 ahead.call(Attribute::parse_outer)?;
2426
David Tolnaye532d6b2018-08-30 16:55:01 -07002427 if {
2428 let ahead = ahead.fork();
2429 // Only parse braces here; paren and bracket will get parsed as
2430 // expression statements
2431 ahead.call(Path::parse_mod_style).is_ok()
2432 && ahead.parse::<Token![!]>().is_ok()
2433 && (ahead.peek(token::Brace) || ahead.peek(Ident))
2434 } {
2435 stmt_mac(input)
2436 } else if ahead.peek(Token![let]) {
2437 stmt_local(input).map(Stmt::Local)
2438 } else if ahead.peek(Token![pub])
2439 || ahead.peek(Token![crate]) && !ahead.peek2(Token![::])
2440 || ahead.peek(Token![extern]) && !ahead.peek2(Token![::])
2441 || ahead.peek(Token![use])
2442 || ahead.peek(Token![static]) && (ahead.peek2(Token![mut]) || ahead.peek2(Ident))
2443 || ahead.peek(Token![const])
2444 || ahead.peek(Token![unsafe]) && !ahead.peek2(token::Brace)
2445 || ahead.peek(Token![async]) && (ahead.peek2(Token![extern]) || ahead.peek2(Token![fn]))
2446 || ahead.peek(Token![fn])
2447 || ahead.peek(Token![mod])
2448 || ahead.peek(Token![type])
2449 || ahead.peek(Token![existential]) && ahead.peek2(Token![type])
2450 || ahead.peek(Token![struct])
2451 || ahead.peek(Token![enum])
2452 || ahead.peek(Token![union]) && ahead.peek2(Ident)
2453 || ahead.peek(Token![auto]) && ahead.peek2(Token![trait])
2454 || ahead.peek(Token![trait])
David Tolnay73b7ca12018-08-30 21:05:13 -07002455 || ahead.peek(Token![default])
David Tolnay2beee042019-04-03 08:36:59 -07002456 && (ahead.peek2(Token![unsafe]) || ahead.peek2(Token![impl]))
2457 || ahead.peek(Token![impl])
David Tolnaye532d6b2018-08-30 16:55:01 -07002458 || ahead.peek(Token![macro])
2459 {
2460 input.parse().map(Stmt::Item)
2461 } else {
2462 stmt_expr(input, allow_nosemi)
David Tolnay60291082018-08-28 09:54:49 -07002463 }
Alex Crichton954046c2017-05-30 21:49:42 -07002464 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07002465
Michael Layzell734adb42017-06-07 16:58:31 -04002466 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002467 fn stmt_mac(input: ParseStream) -> Result<Stmt> {
2468 let attrs = input.call(Attribute::parse_outer)?;
2469 let path = input.call(Path::parse_mod_style)?;
2470 let bang_token: Token![!] = input.parse()?;
2471 let ident: Option<Ident> = input.parse()?;
2472 let (delimiter, tts) = mac::parse_delimiter(input)?;
2473 let semi_token: Option<Token![;]> = input.parse()?;
2474
2475 Ok(Stmt::Item(Item::Macro(ItemMacro {
2476 attrs: attrs,
2477 ident: ident,
2478 mac: Macro {
2479 path: path,
2480 bang_token: bang_token,
2481 delimiter: delimiter,
2482 tts: tts,
2483 },
2484 semi_token: semi_token,
2485 })))
Alex Crichton954046c2017-05-30 21:49:42 -07002486 }
David Tolnay84aa0752016-10-02 23:01:13 -07002487
Michael Layzell734adb42017-06-07 16:58:31 -04002488 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002489 fn stmt_local(input: ParseStream) -> Result<Local> {
2490 Ok(Local {
2491 attrs: input.call(Attribute::parse_outer)?,
2492 let_token: input.parse()?,
2493 pats: {
2494 let mut pats = Punctuated::new();
2495 let value: Pat = input.parse()?;
2496 pats.push_value(value);
2497 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2498 let punct = input.parse()?;
2499 pats.push_punct(punct);
2500 let value: Pat = input.parse()?;
2501 pats.push_value(value);
2502 }
2503 pats
2504 },
2505 ty: {
2506 if input.peek(Token![:]) {
2507 let colon_token: Token![:] = input.parse()?;
2508 let ty: Type = input.parse()?;
2509 Some((colon_token, Box::new(ty)))
2510 } else {
2511 None
2512 }
2513 },
2514 init: {
2515 if input.peek(Token![=]) {
2516 let eq_token: Token![=] = input.parse()?;
2517 let init: Expr = input.parse()?;
2518 Some((eq_token, Box::new(init)))
2519 } else {
2520 None
2521 }
2522 },
2523 semi_token: input.parse()?,
2524 })
2525 }
2526
2527 #[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -07002528 fn stmt_expr(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
David Tolnay60291082018-08-28 09:54:49 -07002529 let mut attrs = input.call(Attribute::parse_outer)?;
David Tolnay01218d12018-08-29 18:13:07 -07002530 let mut e = expr_early(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002531
2532 attrs.extend(e.replace_attrs(Vec::new()));
2533 e.replace_attrs(attrs);
2534
2535 if input.peek(Token![;]) {
David Tolnay01218d12018-08-29 18:13:07 -07002536 return Ok(Stmt::Semi(e, input.parse()?));
David Tolnay60291082018-08-28 09:54:49 -07002537 }
David Tolnay60291082018-08-28 09:54:49 -07002538
David Tolnayf00a2762018-08-30 17:22:22 -07002539 if allow_nosemi || !requires_terminator(&e) {
David Tolnaye532d6b2018-08-30 16:55:01 -07002540 Ok(Stmt::Expr(e))
2541 } else {
2542 Err(input.error("expected semicolon"))
David Tolnay01218d12018-08-29 18:13:07 -07002543 }
David Tolnay60291082018-08-28 09:54:49 -07002544 }
2545
2546 #[cfg(feature = "full")]
2547 impl Parse for Pat {
2548 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay60291082018-08-28 09:54:49 -07002549 let lookahead = input.lookahead1();
2550 if lookahead.peek(Token![_]) {
David Tolnay310b3262018-08-30 15:33:00 -07002551 input.call(pat_wild).map(Pat::Wild)
David Tolnay60291082018-08-28 09:54:49 -07002552 } else if lookahead.peek(Token![box]) {
David Tolnay310b3262018-08-30 15:33:00 -07002553 input.call(pat_box).map(Pat::Box)
David Tolnay8d534b02018-09-02 09:46:05 -07002554 } else if lookahead.peek(Token![-]) || lookahead.peek(Lit) {
2555 pat_lit_or_range(input)
2556 } else if input.peek(Ident)
2557 && ({
2558 input.peek2(Token![::])
2559 || input.peek2(Token![!])
2560 || input.peek2(token::Brace)
2561 || input.peek2(token::Paren)
David Tolnaye614f282018-10-27 22:50:12 -07002562 || input.peek2(Token![..])
2563 && !{
2564 let ahead = input.fork();
2565 ahead.parse::<Ident>()?;
2566 ahead.parse::<RangeLimits>()?;
2567 ahead.is_empty() || ahead.peek(Token![,])
2568 }
David Tolnay8d534b02018-09-02 09:46:05 -07002569 })
Michael Bradshaw7531e152018-10-19 22:26:56 -07002570 || input.peek(Token![self]) && input.peek2(Token![::])
David Tolnay8d534b02018-09-02 09:46:05 -07002571 || input.peek(Token![::])
2572 || input.peek(Token![<])
David Tolnay8d534b02018-09-02 09:46:05 -07002573 || input.peek(Token![Self])
2574 || input.peek(Token![super])
2575 || input.peek(Token![extern])
2576 || input.peek(Token![crate])
2577 {
2578 pat_path_or_macro_or_struct_or_range(input)
Michael Bradshaw7531e152018-10-19 22:26:56 -07002579 } else if input.peek(Token![ref])
2580 || input.peek(Token![mut])
2581 || input.peek(Token![self])
2582 || input.peek(Ident)
2583 {
David Tolnay310b3262018-08-30 15:33:00 -07002584 input.call(pat_ident).map(Pat::Ident)
David Tolnay60291082018-08-28 09:54:49 -07002585 } else if lookahead.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07002586 input.call(pat_tuple).map(Pat::Tuple)
David Tolnay60291082018-08-28 09:54:49 -07002587 } else if lookahead.peek(Token![&]) {
David Tolnay310b3262018-08-30 15:33:00 -07002588 input.call(pat_ref).map(Pat::Ref)
David Tolnay60291082018-08-28 09:54:49 -07002589 } else if lookahead.peek(token::Bracket) {
David Tolnay310b3262018-08-30 15:33:00 -07002590 input.call(pat_slice).map(Pat::Slice)
David Tolnay60291082018-08-28 09:54:49 -07002591 } else {
2592 Err(lookahead.error())
2593 }
2594 }
2595 }
2596
2597 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002598 fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> {
2599 let (qself, path) = path::parsing::qpath(input, true)?;
2600
2601 if input.peek(Token![..]) {
2602 return pat_range(input, qself, path).map(Pat::Range);
2603 }
2604
2605 if qself.is_some() {
2606 return Ok(Pat::Path(PatPath {
2607 qself: qself,
2608 path: path,
2609 }));
2610 }
2611
2612 if input.peek(Token![!]) && !input.peek(Token![!=]) {
2613 let mut contains_arguments = false;
2614 for segment in &path.segments {
2615 match segment.arguments {
2616 PathArguments::None => {}
2617 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
2618 contains_arguments = true;
2619 }
2620 }
2621 }
2622
2623 if !contains_arguments {
2624 let bang_token: Token![!] = input.parse()?;
2625 let (delimiter, tts) = mac::parse_delimiter(input)?;
2626 return Ok(Pat::Macro(PatMacro {
2627 mac: Macro {
2628 path: path,
2629 bang_token: bang_token,
2630 delimiter: delimiter,
2631 tts: tts,
2632 },
2633 }));
2634 }
2635 }
2636
2637 if input.peek(token::Brace) {
2638 pat_struct(input, path).map(Pat::Struct)
2639 } else if input.peek(token::Paren) {
2640 pat_tuple_struct(input, path).map(Pat::TupleStruct)
2641 } else if input.peek(Token![..]) {
2642 pat_range(input, qself, path).map(Pat::Range)
2643 } else {
2644 Ok(Pat::Path(PatPath {
2645 qself: qself,
2646 path: path,
2647 }))
2648 }
2649 }
2650
2651 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002652 fn pat_wild(input: ParseStream) -> Result<PatWild> {
2653 Ok(PatWild {
2654 underscore_token: input.parse()?,
2655 })
Alex Crichton954046c2017-05-30 21:49:42 -07002656 }
2657
Michael Layzell734adb42017-06-07 16:58:31 -04002658 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002659 fn pat_box(input: ParseStream) -> Result<PatBox> {
2660 Ok(PatBox {
2661 box_token: input.parse()?,
2662 pat: input.parse()?,
2663 })
David Tolnay60291082018-08-28 09:54:49 -07002664 }
2665
2666 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002667 fn pat_ident(input: ParseStream) -> Result<PatIdent> {
2668 Ok(PatIdent {
2669 by_ref: input.parse()?,
2670 mutability: input.parse()?,
David Tolnay8d534b02018-09-02 09:46:05 -07002671 ident: input.call(Ident::parse_any)?,
David Tolnay310b3262018-08-30 15:33:00 -07002672 subpat: {
2673 if input.peek(Token![@]) {
2674 let at_token: Token![@] = input.parse()?;
2675 let subpat: Pat = input.parse()?;
2676 Some((at_token, Box::new(subpat)))
2677 } else {
2678 None
2679 }
2680 },
2681 })
David Tolnay60291082018-08-28 09:54:49 -07002682 }
2683
2684 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002685 fn pat_tuple_struct(input: ParseStream, path: Path) -> Result<PatTupleStruct> {
David Tolnay310b3262018-08-30 15:33:00 -07002686 Ok(PatTupleStruct {
David Tolnay8d534b02018-09-02 09:46:05 -07002687 path: path,
David Tolnay310b3262018-08-30 15:33:00 -07002688 pat: input.call(pat_tuple)?,
2689 })
2690 }
David Tolnay60291082018-08-28 09:54:49 -07002691
David Tolnay310b3262018-08-30 15:33:00 -07002692 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002693 fn pat_struct(input: ParseStream, path: Path) -> Result<PatStruct> {
David Tolnay310b3262018-08-30 15:33:00 -07002694 let content;
2695 let brace_token = braced!(content in input);
2696
2697 let mut fields = Punctuated::new();
2698 while !content.is_empty() && !content.peek(Token![..]) {
2699 let value = content.call(field_pat)?;
2700 fields.push_value(value);
2701 if !content.peek(Token![,]) {
2702 break;
David Tolnay60291082018-08-28 09:54:49 -07002703 }
David Tolnay310b3262018-08-30 15:33:00 -07002704 let punct: Token![,] = content.parse()?;
2705 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002706 }
David Tolnay310b3262018-08-30 15:33:00 -07002707
2708 let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) {
2709 Some(content.parse()?)
2710 } else {
2711 None
2712 };
2713
2714 Ok(PatStruct {
2715 path: path,
2716 brace_token: brace_token,
2717 fields: fields,
2718 dot2_token: dot2_token,
2719 })
2720 }
2721
2722 #[cfg(feature = "full")]
2723 fn field_pat(input: ParseStream) -> Result<FieldPat> {
2724 let boxed: Option<Token![box]> = input.parse()?;
2725 let by_ref: Option<Token![ref]> = input.parse()?;
2726 let mutability: Option<Token![mut]> = input.parse()?;
2727 let member: Member = input.parse()?;
2728
2729 if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
2730 || member.is_unnamed()
2731 {
2732 return Ok(FieldPat {
2733 attrs: Vec::new(),
2734 member: member,
2735 colon_token: input.parse()?,
2736 pat: input.parse()?,
2737 });
2738 }
2739
2740 let ident = match member {
2741 Member::Named(ident) => ident,
2742 Member::Unnamed(_) => unreachable!(),
2743 };
2744
2745 let mut pat = Pat::Ident(PatIdent {
2746 by_ref: by_ref,
2747 mutability: mutability,
2748 ident: ident.clone(),
2749 subpat: None,
2750 });
2751
2752 if let Some(boxed) = boxed {
2753 pat = Pat::Box(PatBox {
2754 pat: Box::new(pat),
2755 box_token: boxed,
2756 });
2757 }
2758
2759 Ok(FieldPat {
2760 member: Member::Named(ident),
2761 pat: Box::new(pat),
2762 attrs: Vec::new(),
2763 colon_token: None,
2764 })
Alex Crichton954046c2017-05-30 21:49:42 -07002765 }
2766
David Tolnay1501f7e2018-08-27 14:21:03 -07002767 impl Parse for Member {
2768 fn parse(input: ParseStream) -> Result<Self> {
2769 if input.peek(Ident) {
2770 input.parse().map(Member::Named)
2771 } else if input.peek(LitInt) {
2772 input.parse().map(Member::Unnamed)
2773 } else {
2774 Err(input.error("expected identifier or integer"))
2775 }
2776 }
David Tolnay85b69a42017-12-27 20:43:10 -05002777 }
2778
Bastien Oriveld29ea392018-10-16 23:50:16 +02002779 #[cfg(feature = "full")]
2780 impl Parse for Arm {
2781 fn parse(input: ParseStream) -> Result<Arm> {
2782 let requires_comma;
2783 Ok(Arm {
2784 attrs: input.call(Attribute::parse_outer)?,
2785 leading_vert: input.parse()?,
2786 pats: {
2787 let mut pats = Punctuated::new();
2788 let value: Pat = input.parse()?;
2789 pats.push_value(value);
2790 loop {
2791 if !input.peek(Token![|]) {
2792 break;
2793 }
2794 let punct = input.parse()?;
2795 pats.push_punct(punct);
2796 let value: Pat = input.parse()?;
2797 pats.push_value(value);
2798 }
2799 pats
2800 },
2801 guard: {
2802 if input.peek(Token![if]) {
2803 let if_token: Token![if] = input.parse()?;
2804 let guard: Expr = input.parse()?;
2805 Some((if_token, Box::new(guard)))
2806 } else {
2807 None
2808 }
2809 },
2810 fat_arrow_token: input.parse()?,
2811 body: {
2812 let body = input.call(expr_early)?;
2813 requires_comma = requires_terminator(&body);
2814 Box::new(body)
2815 },
2816 comma: {
2817 if requires_comma && !input.is_empty() {
2818 Some(input.parse()?)
2819 } else {
2820 input.parse()?
2821 }
2822 },
2823 })
2824 }
2825 }
2826
David Tolnay1501f7e2018-08-27 14:21:03 -07002827 impl Parse for Index {
2828 fn parse(input: ParseStream) -> Result<Self> {
2829 let lit: LitInt = input.parse()?;
2830 if let IntSuffix::None = lit.suffix() {
2831 Ok(Index {
2832 index: lit.value() as u32,
2833 span: lit.span(),
2834 })
2835 } else {
David Tolnayff8c9342018-09-01 13:45:48 -07002836 Err(Error::new(lit.span(), "expected unsuffixed integer"))
David Tolnay1501f7e2018-08-27 14:21:03 -07002837 }
2838 }
David Tolnay85b69a42017-12-27 20:43:10 -05002839 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07002840
Michael Layzell734adb42017-06-07 16:58:31 -04002841 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002842 fn pat_range(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<PatRange> {
2843 Ok(PatRange {
2844 lo: Box::new(Expr::Path(ExprPath {
2845 attrs: Vec::new(),
2846 qself: qself,
2847 path: path,
2848 })),
2849 limits: input.parse()?,
2850 hi: input.call(pat_lit_expr)?,
David Tolnay310b3262018-08-30 15:33:00 -07002851 })
Alex Crichton954046c2017-05-30 21:49:42 -07002852 }
David Tolnay9636c052016-10-02 17:11:17 -07002853
Michael Layzell734adb42017-06-07 16:58:31 -04002854 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002855 fn pat_tuple(input: ParseStream) -> Result<PatTuple> {
2856 let content;
2857 let paren_token = parenthesized!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002858
David Tolnay310b3262018-08-30 15:33:00 -07002859 let mut front = Punctuated::new();
2860 let mut dot2_token = None::<Token![..]>;
2861 let mut comma_token = None::<Token![,]>;
2862 loop {
2863 if content.is_empty() {
2864 break;
David Tolnay60291082018-08-28 09:54:49 -07002865 }
David Tolnay310b3262018-08-30 15:33:00 -07002866 if content.peek(Token![..]) {
2867 dot2_token = Some(content.parse()?);
2868 comma_token = content.parse()?;
2869 break;
David Tolnay60291082018-08-28 09:54:49 -07002870 }
David Tolnay310b3262018-08-30 15:33:00 -07002871 let value: Pat = content.parse()?;
2872 front.push_value(value);
2873 if content.is_empty() {
2874 break;
2875 }
2876 let punct = content.parse()?;
2877 front.push_punct(punct);
2878 }
2879
David Tolnayf5ebc192018-08-30 18:23:46 -07002880 let mut back = Punctuated::new();
2881 while !content.is_empty() {
2882 let value: Pat = content.parse()?;
2883 back.push_value(value);
2884 if content.is_empty() {
2885 break;
2886 }
2887 let punct = content.parse()?;
2888 back.push_punct(punct);
2889 }
David Tolnay310b3262018-08-30 15:33:00 -07002890
2891 Ok(PatTuple {
2892 paren_token: paren_token,
2893 front: front,
2894 dot2_token: dot2_token,
2895 comma_token: comma_token,
2896 back: back,
2897 })
2898 }
2899
2900 #[cfg(feature = "full")]
2901 fn pat_ref(input: ParseStream) -> Result<PatRef> {
2902 Ok(PatRef {
2903 and_token: input.parse()?,
2904 mutability: input.parse()?,
2905 pat: input.parse()?,
2906 })
2907 }
2908
2909 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002910 fn pat_lit_or_range(input: ParseStream) -> Result<Pat> {
2911 let lo = input.call(pat_lit_expr)?;
2912 if input.peek(Token![..]) {
2913 Ok(Pat::Range(PatRange {
2914 lo: lo,
2915 limits: input.parse()?,
2916 hi: input.call(pat_lit_expr)?,
2917 }))
David Tolnay310b3262018-08-30 15:33:00 -07002918 } else {
David Tolnay8d534b02018-09-02 09:46:05 -07002919 Ok(Pat::Lit(PatLit { expr: lo }))
David Tolnay60291082018-08-28 09:54:49 -07002920 }
2921 }
2922
2923 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002924 fn pat_lit_expr(input: ParseStream) -> Result<Box<Expr>> {
2925 let neg: Option<Token![-]> = input.parse()?;
2926
2927 let lookahead = input.lookahead1();
2928 let expr = if lookahead.peek(Lit) {
Peter Hall04f42792019-04-02 16:58:45 +02002929 Expr::Lit(input.parse()?)
David Tolnay60291082018-08-28 09:54:49 -07002930 } else if lookahead.peek(Ident)
2931 || lookahead.peek(Token![::])
2932 || lookahead.peek(Token![<])
2933 || lookahead.peek(Token![self])
2934 || lookahead.peek(Token![Self])
2935 || lookahead.peek(Token![super])
2936 || lookahead.peek(Token![extern])
2937 || lookahead.peek(Token![crate])
2938 {
2939 Expr::Path(input.parse()?)
2940 } else {
2941 return Err(lookahead.error());
2942 };
2943
2944 Ok(Box::new(if let Some(neg) = neg {
David Tolnay8c91b882017-12-28 23:04:32 -05002945 Expr::Unary(ExprUnary {
2946 attrs: Vec::new(),
David Tolnayc29b9892017-12-27 22:58:14 -05002947 op: UnOp::Neg(neg),
David Tolnay60291082018-08-28 09:54:49 -07002948 expr: Box::new(expr),
David Tolnay3bc597f2017-12-31 02:31:11 -05002949 })
David Tolnay0ad9e9f2016-10-29 22:20:02 -07002950 } else {
David Tolnay60291082018-08-28 09:54:49 -07002951 expr
2952 }))
Alex Crichton954046c2017-05-30 21:49:42 -07002953 }
David Tolnay323279a2017-12-29 11:26:32 -05002954
2955 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002956 fn pat_slice(input: ParseStream) -> Result<PatSlice> {
2957 let content;
2958 let bracket_token = bracketed!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002959
David Tolnay310b3262018-08-30 15:33:00 -07002960 let mut front = Punctuated::new();
2961 let mut middle = None;
2962 loop {
2963 if content.is_empty() || content.peek(Token![..]) {
2964 break;
David Tolnay60291082018-08-28 09:54:49 -07002965 }
David Tolnay310b3262018-08-30 15:33:00 -07002966 let value: Pat = content.parse()?;
2967 if content.peek(Token![..]) {
2968 middle = Some(Box::new(value));
2969 break;
David Tolnay60291082018-08-28 09:54:49 -07002970 }
David Tolnay310b3262018-08-30 15:33:00 -07002971 front.push_value(value);
2972 if content.is_empty() {
2973 break;
2974 }
2975 let punct = content.parse()?;
2976 front.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002977 }
David Tolnay310b3262018-08-30 15:33:00 -07002978
2979 let dot2_token: Option<Token![..]> = content.parse()?;
2980 let mut comma_token = None::<Token![,]>;
2981 let mut back = Punctuated::new();
2982 if dot2_token.is_some() {
2983 comma_token = content.parse()?;
2984 if comma_token.is_some() {
2985 loop {
2986 if content.is_empty() {
2987 break;
2988 }
2989 let value: Pat = content.parse()?;
2990 back.push_value(value);
2991 if content.is_empty() {
2992 break;
2993 }
2994 let punct = content.parse()?;
2995 back.push_punct(punct);
2996 }
2997 }
2998 }
2999
3000 Ok(PatSlice {
3001 bracket_token: bracket_token,
3002 front: front,
3003 middle: middle,
3004 dot2_token: dot2_token,
3005 comma_token: comma_token,
3006 back: back,
3007 })
David Tolnay60291082018-08-28 09:54:49 -07003008 }
3009
3010 #[cfg(feature = "full")]
David Tolnay1501f7e2018-08-27 14:21:03 -07003011 impl Member {
3012 fn is_named(&self) -> bool {
3013 match *self {
3014 Member::Named(_) => true,
3015 Member::Unnamed(_) => false,
3016 }
3017 }
David Tolnay60291082018-08-28 09:54:49 -07003018
3019 fn is_unnamed(&self) -> bool {
3020 match *self {
3021 Member::Named(_) => false,
3022 Member::Unnamed(_) => true,
3023 }
3024 }
David Tolnay1501f7e2018-08-27 14:21:03 -07003025 }
David Tolnayb9c8e322016-09-23 20:48:37 -07003026}
3027
David Tolnayf4bbbd92016-09-23 14:41:55 -07003028#[cfg(feature = "printing")]
3029mod printing {
3030 use super::*;
David Tolnay64023912018-08-31 09:51:12 -07003031
Alex Crichtona74a1c82018-05-16 10:20:44 -07003032 use proc_macro2::{Literal, TokenStream};
3033 use quote::{ToTokens, TokenStreamExt};
David Tolnayf4bbbd92016-09-23 14:41:55 -07003034
David Tolnay64023912018-08-31 09:51:12 -07003035 #[cfg(feature = "full")]
3036 use attr::FilterAttrs;
3037 #[cfg(feature = "full")]
3038 use print::TokensOrDefault;
3039
David Tolnaybcf26022017-12-25 22:10:52 -05003040 // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
David Tolnayb6a0e7d2018-05-20 22:06:47 -07003041 // before appending it to `TokenStream`.
Michael Layzell3936ceb2017-07-08 00:28:36 -04003042 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003043 fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) {
David Tolnay8c91b882017-12-28 23:04:32 -05003044 if let Expr::Struct(_) = *e {
David Tolnay32954ef2017-12-26 22:43:16 -05003045 token::Paren::default().surround(tokens, |tokens| {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003046 e.to_tokens(tokens);
3047 });
3048 } else {
3049 e.to_tokens(tokens);
3050 }
3051 }
3052
David Tolnay8c91b882017-12-28 23:04:32 -05003053 #[cfg(feature = "full")]
David Tolnayd997aef2018-07-21 18:42:31 -07003054 fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
David Tolnay8c91b882017-12-28 23:04:32 -05003055 tokens.append_all(attrs.outer());
3056 }
Michael Layzell734adb42017-06-07 16:58:31 -04003057
David Tolnayd997aef2018-07-21 18:42:31 -07003058 #[cfg(feature = "full")]
3059 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3060 tokens.append_all(attrs.inner());
3061 }
3062
David Tolnay8c91b882017-12-28 23:04:32 -05003063 #[cfg(not(feature = "full"))]
David Tolnayd997aef2018-07-21 18:42:31 -07003064 fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3065
3066 #[cfg(not(feature = "full"))]
3067 fn inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
Alex Crichton62a0a592017-05-22 13:58:53 -07003068
Michael Layzell734adb42017-06-07 16:58:31 -04003069 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003070 impl ToTokens for ExprBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003071 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003072 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003073 self.box_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003074 self.expr.to_tokens(tokens);
3075 }
3076 }
3077
Michael Layzell734adb42017-06-07 16:58:31 -04003078 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003079 impl ToTokens for ExprInPlace {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003080 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003081 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8701a5c2017-12-28 23:31:10 -05003082 self.place.to_tokens(tokens);
3083 self.arrow_token.to_tokens(tokens);
3084 self.value.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003085 }
3086 }
3087
Michael Layzell734adb42017-06-07 16:58:31 -04003088 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003089 impl ToTokens for ExprArray {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003090 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003091 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003092 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003093 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003094 self.elems.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003095 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003096 }
3097 }
3098
3099 impl ToTokens for ExprCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003100 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003101 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003102 self.func.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003103 self.paren_token.surround(tokens, |tokens| {
3104 self.args.to_tokens(tokens);
3105 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003106 }
3107 }
3108
Michael Layzell734adb42017-06-07 16:58:31 -04003109 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003110 impl ToTokens for ExprMethodCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003111 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003112 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay76418512017-12-28 23:47:47 -05003113 self.receiver.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003114 self.dot_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003115 self.method.to_tokens(tokens);
David Tolnayd60cfec2017-12-29 00:21:38 -05003116 self.turbofish.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003117 self.paren_token.surround(tokens, |tokens| {
3118 self.args.to_tokens(tokens);
3119 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003120 }
3121 }
3122
Michael Layzell734adb42017-06-07 16:58:31 -04003123 #[cfg(feature = "full")]
David Tolnayd60cfec2017-12-29 00:21:38 -05003124 impl ToTokens for MethodTurbofish {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003125 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003126 self.colon2_token.to_tokens(tokens);
3127 self.lt_token.to_tokens(tokens);
3128 self.args.to_tokens(tokens);
3129 self.gt_token.to_tokens(tokens);
3130 }
3131 }
3132
3133 #[cfg(feature = "full")]
3134 impl ToTokens for GenericMethodArgument {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003135 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003136 match *self {
3137 GenericMethodArgument::Type(ref t) => t.to_tokens(tokens),
3138 GenericMethodArgument::Const(ref c) => c.to_tokens(tokens),
3139 }
3140 }
3141 }
3142
3143 #[cfg(feature = "full")]
David Tolnay05362582017-12-26 01:33:57 -05003144 impl ToTokens for ExprTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003145 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003146 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003147 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003148 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003149 self.elems.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003150 // If we only have one argument, we need a trailing comma to
David Tolnay05362582017-12-26 01:33:57 -05003151 // distinguish ExprTuple from ExprParen.
David Tolnaya0834b42018-01-01 21:30:02 -08003152 if self.elems.len() == 1 && !self.elems.trailing_punct() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003153 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003154 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003155 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003156 }
3157 }
3158
3159 impl ToTokens for ExprBinary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003160 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003161 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003162 self.left.to_tokens(tokens);
3163 self.op.to_tokens(tokens);
3164 self.right.to_tokens(tokens);
3165 }
3166 }
3167
3168 impl ToTokens for ExprUnary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003169 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003170 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003171 self.op.to_tokens(tokens);
3172 self.expr.to_tokens(tokens);
3173 }
3174 }
3175
David Tolnay8c91b882017-12-28 23:04:32 -05003176 impl ToTokens for ExprLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003177 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003178 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003179 self.lit.to_tokens(tokens);
3180 }
3181 }
3182
Alex Crichton62a0a592017-05-22 13:58:53 -07003183 impl ToTokens for ExprCast {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003184 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003185 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003186 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003187 self.as_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003188 self.ty.to_tokens(tokens);
3189 }
3190 }
3191
David Tolnay0cf94f22017-12-28 23:46:26 -05003192 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003193 impl ToTokens for ExprType {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003194 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003195 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003196 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003197 self.colon_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003198 self.ty.to_tokens(tokens);
3199 }
3200 }
3201
Michael Layzell734adb42017-06-07 16:58:31 -04003202 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003203 fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>) {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003204 if let Some((ref else_token, ref else_)) = *else_ {
3205 else_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003206
3207 // If we are not one of the valid expressions to exist in an else
3208 // clause, wrap ourselves in a block.
David Tolnay2ccf32a2017-12-29 00:34:26 -05003209 match **else_ {
David Tolnay9c119122018-09-01 18:47:02 -07003210 Expr::If(_) | Expr::Block(_) => {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003211 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003212 }
3213 _ => {
David Tolnay32954ef2017-12-26 22:43:16 -05003214 token::Brace::default().surround(tokens, |tokens| {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003215 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003216 });
3217 }
3218 }
3219 }
3220 }
3221
3222 #[cfg(feature = "full")]
David Tolnay9c119122018-09-01 18:47:02 -07003223 impl ToTokens for ExprLet {
3224 fn to_tokens(&self, tokens: &mut TokenStream) {
3225 outer_attrs_to_tokens(&self.attrs, tokens);
3226 self.let_token.to_tokens(tokens);
3227 self.pats.to_tokens(tokens);
3228 self.eq_token.to_tokens(tokens);
3229 wrap_bare_struct(tokens, &self.expr);
3230 }
3231 }
3232
3233 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003234 impl ToTokens for ExprIf {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003235 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003236 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003237 self.if_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003238 wrap_bare_struct(tokens, &self.cond);
David Tolnay2ccf32a2017-12-29 00:34:26 -05003239 self.then_branch.to_tokens(tokens);
3240 maybe_wrap_else(tokens, &self.else_branch);
Alex Crichton62a0a592017-05-22 13:58:53 -07003241 }
3242 }
3243
Michael Layzell734adb42017-06-07 16:58:31 -04003244 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003245 impl ToTokens for ExprWhile {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003246 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003247 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003248 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003249 self.while_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003250 wrap_bare_struct(tokens, &self.cond);
David Tolnay5d314dc2018-07-21 16:40:01 -07003251 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003252 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003253 tokens.append_all(&self.body.stmts);
3254 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003255 }
3256 }
3257
Michael Layzell734adb42017-06-07 16:58:31 -04003258 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003259 impl ToTokens for ExprForLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003260 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003261 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003262 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003263 self.for_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003264 self.pat.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003265 self.in_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003266 wrap_bare_struct(tokens, &self.expr);
David Tolnay5d314dc2018-07-21 16:40:01 -07003267 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003268 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003269 tokens.append_all(&self.body.stmts);
3270 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003271 }
3272 }
3273
Michael Layzell734adb42017-06-07 16:58:31 -04003274 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003275 impl ToTokens for ExprLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003276 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003277 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003278 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003279 self.loop_token.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003280 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003281 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003282 tokens.append_all(&self.body.stmts);
3283 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003284 }
3285 }
3286
Michael Layzell734adb42017-06-07 16:58:31 -04003287 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003288 impl ToTokens for ExprMatch {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003289 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003290 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003291 self.match_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003292 wrap_bare_struct(tokens, &self.expr);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003293 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003294 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay51382052017-12-27 13:46:21 -05003295 for (i, arm) in self.arms.iter().enumerate() {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003296 arm.to_tokens(tokens);
3297 // Ensure that we have a comma after a non-block arm, except
3298 // for the last one.
3299 let is_last = i == self.arms.len() - 1;
David Tolnaye532d6b2018-08-30 16:55:01 -07003300 if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003301 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003302 }
3303 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003304 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003305 }
3306 }
3307
Michael Layzell734adb42017-06-07 16:58:31 -04003308 #[cfg(feature = "full")]
David Tolnay02a9c6f2018-08-24 18:58:45 -04003309 impl ToTokens for ExprAsync {
3310 fn to_tokens(&self, tokens: &mut TokenStream) {
3311 outer_attrs_to_tokens(&self.attrs, tokens);
3312 self.async_token.to_tokens(tokens);
3313 self.capture.to_tokens(tokens);
3314 self.block.to_tokens(tokens);
3315 }
3316 }
3317
3318 #[cfg(feature = "full")]
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003319 impl ToTokens for ExprTryBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003320 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003321 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003322 self.try_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003323 self.block.to_tokens(tokens);
3324 }
3325 }
3326
Michael Layzell734adb42017-06-07 16:58:31 -04003327 #[cfg(feature = "full")]
Alex Crichtonfe110462017-06-01 12:49:27 -07003328 impl ToTokens for ExprYield {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003329 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003330 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonfe110462017-06-01 12:49:27 -07003331 self.yield_token.to_tokens(tokens);
3332 self.expr.to_tokens(tokens);
3333 }
3334 }
3335
3336 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003337 impl ToTokens for ExprClosure {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003338 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003339 outer_attrs_to_tokens(&self.attrs, tokens);
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09003340 self.asyncness.to_tokens(tokens);
David Tolnay13d4c0e2018-03-31 20:53:59 +02003341 self.movability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003342 self.capture.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003343 self.or1_token.to_tokens(tokens);
David Tolnay56080682018-01-06 14:01:52 -08003344 for input in self.inputs.pairs() {
3345 match **input.value() {
David Tolnay51382052017-12-27 13:46:21 -05003346 FnArg::Captured(ArgCaptured {
3347 ref pat,
3348 ty: Type::Infer(_),
3349 ..
3350 }) => {
Alex Crichton62a0a592017-05-22 13:58:53 -07003351 pat.to_tokens(tokens);
David Tolnay9636c052016-10-02 17:11:17 -07003352 }
David Tolnay56080682018-01-06 14:01:52 -08003353 _ => input.value().to_tokens(tokens),
David Tolnay3c2467c2016-10-02 17:55:08 -07003354 }
David Tolnayf2cfd722017-12-31 18:02:51 -05003355 input.punct().to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003356 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003357 self.or2_token.to_tokens(tokens);
David Tolnay7f675742017-12-27 22:43:21 -05003358 self.output.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003359 self.body.to_tokens(tokens);
3360 }
3361 }
3362
Michael Layzell734adb42017-06-07 16:58:31 -04003363 #[cfg(feature = "full")]
Nika Layzell640832a2017-12-04 13:37:09 -05003364 impl ToTokens for ExprUnsafe {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003365 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003366 outer_attrs_to_tokens(&self.attrs, tokens);
Nika Layzell640832a2017-12-04 13:37:09 -05003367 self.unsafe_token.to_tokens(tokens);
David Tolnayc4be3512018-08-27 06:25:44 -07003368 self.block.brace_token.surround(tokens, |tokens| {
3369 inner_attrs_to_tokens(&self.attrs, tokens);
3370 tokens.append_all(&self.block.stmts);
3371 });
Nika Layzell640832a2017-12-04 13:37:09 -05003372 }
3373 }
3374
3375 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003376 impl ToTokens for ExprBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003377 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003378 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay1d8e9962018-08-24 19:04:20 -04003379 self.label.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003380 self.block.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003381 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003382 tokens.append_all(&self.block.stmts);
3383 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003384 }
3385 }
3386
Michael Layzell734adb42017-06-07 16:58:31 -04003387 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003388 impl ToTokens for ExprAssign {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003389 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003390 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003391 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003392 self.eq_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003393 self.right.to_tokens(tokens);
3394 }
3395 }
3396
Michael Layzell734adb42017-06-07 16:58:31 -04003397 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003398 impl ToTokens for ExprAssignOp {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003399 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003400 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003401 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003402 self.op.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003403 self.right.to_tokens(tokens);
3404 }
3405 }
3406
3407 impl ToTokens for ExprField {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003408 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003409 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003410 self.base.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003411 self.dot_token.to_tokens(tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003412 self.member.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003413 }
3414 }
3415
David Tolnay85b69a42017-12-27 20:43:10 -05003416 impl ToTokens for Member {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003417 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay85b69a42017-12-27 20:43:10 -05003418 match *self {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003419 Member::Named(ref ident) => ident.to_tokens(tokens),
David Tolnay85b69a42017-12-27 20:43:10 -05003420 Member::Unnamed(ref index) => index.to_tokens(tokens),
3421 }
3422 }
3423 }
3424
David Tolnay85b69a42017-12-27 20:43:10 -05003425 impl ToTokens for Index {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003426 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichton9a4dca22018-03-28 06:32:19 -07003427 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
3428 lit.set_span(self.span);
3429 tokens.append(lit);
Alex Crichton62a0a592017-05-22 13:58:53 -07003430 }
3431 }
3432
3433 impl ToTokens for ExprIndex {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003434 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003435 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003436 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003437 self.bracket_token.surround(tokens, |tokens| {
3438 self.index.to_tokens(tokens);
3439 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003440 }
3441 }
3442
Michael Layzell734adb42017-06-07 16:58:31 -04003443 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003444 impl ToTokens for ExprRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003445 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003446 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003447 self.from.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003448 match self.limits {
3449 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
3450 RangeLimits::Closed(ref t) => t.to_tokens(tokens),
3451 }
Alex Crichton62a0a592017-05-22 13:58:53 -07003452 self.to.to_tokens(tokens);
3453 }
3454 }
3455
3456 impl ToTokens for ExprPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003457 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003458 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay12f3b6f2018-09-01 16:10:53 -07003459 private::print_path(tokens, &self.qself, &self.path);
Alex Crichton62a0a592017-05-22 13:58:53 -07003460 }
3461 }
3462
Michael Layzell734adb42017-06-07 16:58:31 -04003463 #[cfg(feature = "full")]
David Tolnay00674ba2018-03-31 18:14:11 +02003464 impl ToTokens for ExprReference {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003465 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003466 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003467 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003468 self.mutability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003469 self.expr.to_tokens(tokens);
3470 }
3471 }
3472
Michael Layzell734adb42017-06-07 16:58:31 -04003473 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003474 impl ToTokens for ExprBreak {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003475 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003476 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003477 self.break_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003478 self.label.to_tokens(tokens);
3479 self.expr.to_tokens(tokens);
3480 }
3481 }
3482
Michael Layzell734adb42017-06-07 16:58:31 -04003483 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003484 impl ToTokens for ExprContinue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003485 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003486 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003487 self.continue_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003488 self.label.to_tokens(tokens);
3489 }
3490 }
3491
Michael Layzell734adb42017-06-07 16:58:31 -04003492 #[cfg(feature = "full")]
David Tolnayc246cd32017-12-28 23:14:32 -05003493 impl ToTokens for ExprReturn {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003494 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003495 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003496 self.return_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003497 self.expr.to_tokens(tokens);
3498 }
3499 }
3500
Michael Layzell734adb42017-06-07 16:58:31 -04003501 #[cfg(feature = "full")]
David Tolnay8c91b882017-12-28 23:04:32 -05003502 impl ToTokens for ExprMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003503 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003504 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003505 self.mac.to_tokens(tokens);
3506 }
3507 }
3508
3509 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003510 impl ToTokens for ExprStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003511 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003512 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003513 self.path.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003514 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003515 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003516 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003517 if self.rest.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -07003518 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003519 self.rest.to_tokens(tokens);
3520 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003521 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003522 }
3523 }
3524
Michael Layzell734adb42017-06-07 16:58:31 -04003525 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003526 impl ToTokens for ExprRepeat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003527 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003528 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003529 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003530 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003531 self.expr.to_tokens(tokens);
3532 self.semi_token.to_tokens(tokens);
David Tolnay84d80442018-01-07 01:03:20 -08003533 self.len.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003534 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003535 }
3536 }
3537
David Tolnaye98775f2017-12-28 23:17:00 -05003538 #[cfg(feature = "full")]
Michael Layzell93c36282017-06-04 20:43:14 -04003539 impl ToTokens for ExprGroup {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003540 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003541 outer_attrs_to_tokens(&self.attrs, tokens);
Michael Layzell93c36282017-06-04 20:43:14 -04003542 self.group_token.surround(tokens, |tokens| {
3543 self.expr.to_tokens(tokens);
3544 });
3545 }
3546 }
3547
Alex Crichton62a0a592017-05-22 13:58:53 -07003548 impl ToTokens for ExprParen {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003549 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003550 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003551 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003552 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003553 self.expr.to_tokens(tokens);
3554 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003555 }
3556 }
3557
Michael Layzell734adb42017-06-07 16:58:31 -04003558 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003559 impl ToTokens for ExprTry {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003560 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003561 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003562 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003563 self.question_token.to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003564 }
3565 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07003566
David Tolnay2ae520a2017-12-29 11:19:50 -05003567 impl ToTokens for ExprVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003568 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003569 self.tts.to_tokens(tokens);
3570 }
3571 }
3572
Michael Layzell734adb42017-06-07 16:58:31 -04003573 #[cfg(feature = "full")]
David Tolnaybcd498f2017-12-29 12:02:33 -05003574 impl ToTokens for Label {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003575 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaybcd498f2017-12-29 12:02:33 -05003576 self.name.to_tokens(tokens);
3577 self.colon_token.to_tokens(tokens);
3578 }
3579 }
3580
3581 #[cfg(feature = "full")]
David Tolnay055a7042016-10-02 19:23:54 -07003582 impl ToTokens for FieldValue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003583 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003584 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003585 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003586 if let Some(ref colon_token) = self.colon_token {
3587 colon_token.to_tokens(tokens);
David Tolnay276690f2016-10-30 12:06:59 -07003588 self.expr.to_tokens(tokens);
3589 }
David Tolnay055a7042016-10-02 19:23:54 -07003590 }
3591 }
3592
Michael Layzell734adb42017-06-07 16:58:31 -04003593 #[cfg(feature = "full")]
David Tolnayb4ad3b52016-10-01 21:58:13 -07003594 impl ToTokens for Arm {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003595 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003596 tokens.append_all(&self.attrs);
David Tolnay18cc4d42018-03-31 18:47:20 +02003597 self.leading_vert.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003598 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003599 if let Some((ref if_token, ref guard)) = self.guard {
3600 if_token.to_tokens(tokens);
3601 guard.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003602 }
David Tolnaydfb91432018-03-31 19:19:44 +02003603 self.fat_arrow_token.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003604 self.body.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003605 self.comma.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003606 }
3607 }
3608
Michael Layzell734adb42017-06-07 16:58:31 -04003609 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003610 impl ToTokens for PatWild {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003611 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003612 self.underscore_token.to_tokens(tokens);
3613 }
3614 }
3615
Michael Layzell734adb42017-06-07 16:58:31 -04003616 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003617 impl ToTokens for PatIdent {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003618 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay24237fb2017-12-29 02:15:26 -05003619 self.by_ref.to_tokens(tokens);
David Tolnayefc96fb2017-12-29 02:03:15 -05003620 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003621 self.ident.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003622 if let Some((ref at_token, ref subpat)) = self.subpat {
3623 at_token.to_tokens(tokens);
3624 subpat.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003625 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003626 }
3627 }
3628
Michael Layzell734adb42017-06-07 16:58:31 -04003629 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003630 impl ToTokens for PatStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003631 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003632 self.path.to_tokens(tokens);
3633 self.brace_token.surround(tokens, |tokens| {
3634 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003635 // NOTE: We need a comma before the dot2 token if it is present.
3636 if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003637 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003638 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003639 self.dot2_token.to_tokens(tokens);
3640 });
3641 }
3642 }
3643
Michael Layzell734adb42017-06-07 16:58:31 -04003644 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003645 impl ToTokens for PatTupleStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003646 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003647 self.path.to_tokens(tokens);
3648 self.pat.to_tokens(tokens);
3649 }
3650 }
3651
Michael Layzell734adb42017-06-07 16:58:31 -04003652 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003653 impl ToTokens for PatPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003654 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay12f3b6f2018-09-01 16:10:53 -07003655 private::print_path(tokens, &self.qself, &self.path);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003656 }
3657 }
3658
Michael Layzell734adb42017-06-07 16:58:31 -04003659 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003660 impl ToTokens for PatTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003661 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003662 self.paren_token.surround(tokens, |tokens| {
David Tolnay41871922017-12-29 01:53:45 -05003663 self.front.to_tokens(tokens);
3664 if let Some(ref dot2_token) = self.dot2_token {
3665 if !self.front.empty_or_trailing() {
3666 // Ensure there is a comma before the .. token.
David Tolnayf8db7ba2017-11-11 22:52:16 -08003667 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003668 }
David Tolnay41871922017-12-29 01:53:45 -05003669 dot2_token.to_tokens(tokens);
3670 self.comma_token.to_tokens(tokens);
3671 if self.comma_token.is_none() && !self.back.is_empty() {
3672 // Ensure there is a comma after the .. token.
3673 <Token![,]>::default().to_tokens(tokens);
3674 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07003675 }
David Tolnay41871922017-12-29 01:53:45 -05003676 self.back.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003677 });
3678 }
3679 }
3680
Michael Layzell734adb42017-06-07 16:58:31 -04003681 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003682 impl ToTokens for PatBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003683 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003684 self.box_token.to_tokens(tokens);
3685 self.pat.to_tokens(tokens);
3686 }
3687 }
3688
Michael Layzell734adb42017-06-07 16:58:31 -04003689 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003690 impl ToTokens for PatRef {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003691 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003692 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003693 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003694 self.pat.to_tokens(tokens);
3695 }
3696 }
3697
Michael Layzell734adb42017-06-07 16:58:31 -04003698 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003699 impl ToTokens for PatLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003700 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003701 self.expr.to_tokens(tokens);
3702 }
3703 }
3704
Michael Layzell734adb42017-06-07 16:58:31 -04003705 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003706 impl ToTokens for PatRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003707 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003708 self.lo.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003709 match self.limits {
3710 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
David Tolnay7ac699c2018-08-24 14:00:58 -04003711 RangeLimits::Closed(ref t) => Token![...](t.spans).to_tokens(tokens),
David Tolnay475288a2017-12-19 22:59:44 -08003712 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003713 self.hi.to_tokens(tokens);
3714 }
3715 }
3716
Michael Layzell734adb42017-06-07 16:58:31 -04003717 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003718 impl ToTokens for PatSlice {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003719 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003720 self.bracket_token.surround(tokens, |tokens| {
3721 self.front.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003722
3723 // If we need a comma before the middle or standalone .. token,
3724 // then make sure it's present.
David Tolnay51382052017-12-27 13:46:21 -05003725 if !self.front.empty_or_trailing()
3726 && (self.middle.is_some() || self.dot2_token.is_some())
Michael Layzell3936ceb2017-07-08 00:28:36 -04003727 {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003728 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003729 }
3730
3731 // If we have an identifier, we always need a .. token.
3732 if self.middle.is_some() {
3733 self.middle.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -07003734 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003735 } else if self.dot2_token.is_some() {
3736 self.dot2_token.to_tokens(tokens);
3737 }
3738
3739 // Make sure we have a comma before the back half.
3740 if !self.back.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07003741 TokensOrDefault(&self.comma_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003742 self.back.to_tokens(tokens);
3743 } else {
3744 self.comma_token.to_tokens(tokens);
3745 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003746 })
David Tolnayb4ad3b52016-10-01 21:58:13 -07003747 }
3748 }
3749
Michael Layzell734adb42017-06-07 16:58:31 -04003750 #[cfg(feature = "full")]
David Tolnay323279a2017-12-29 11:26:32 -05003751 impl ToTokens for PatMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003752 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay323279a2017-12-29 11:26:32 -05003753 self.mac.to_tokens(tokens);
3754 }
3755 }
3756
3757 #[cfg(feature = "full")]
David Tolnay2ae520a2017-12-29 11:19:50 -05003758 impl ToTokens for PatVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003759 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003760 self.tts.to_tokens(tokens);
3761 }
3762 }
3763
3764 #[cfg(feature = "full")]
David Tolnay8d9e81a2016-10-03 22:36:32 -07003765 impl ToTokens for FieldPat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003766 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay5d7098a2017-12-29 01:35:24 -05003767 if let Some(ref colon_token) = self.colon_token {
David Tolnay85b69a42017-12-27 20:43:10 -05003768 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003769 colon_token.to_tokens(tokens);
David Tolnay8d9e81a2016-10-03 22:36:32 -07003770 }
3771 self.pat.to_tokens(tokens);
3772 }
3773 }
3774
Michael Layzell734adb42017-06-07 16:58:31 -04003775 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003776 impl ToTokens for Block {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003777 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003778 self.brace_token.surround(tokens, |tokens| {
3779 tokens.append_all(&self.stmts);
3780 });
David Tolnay42602292016-10-01 22:25:45 -07003781 }
3782 }
3783
Michael Layzell734adb42017-06-07 16:58:31 -04003784 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003785 impl ToTokens for Stmt {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003786 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay42602292016-10-01 22:25:45 -07003787 match *self {
David Tolnay191e0582016-10-02 18:31:09 -07003788 Stmt::Local(ref local) => local.to_tokens(tokens),
David Tolnay42602292016-10-01 22:25:45 -07003789 Stmt::Item(ref item) => item.to_tokens(tokens),
3790 Stmt::Expr(ref expr) => expr.to_tokens(tokens),
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003791 Stmt::Semi(ref expr, ref semi) => {
David Tolnay42602292016-10-01 22:25:45 -07003792 expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003793 semi.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -07003794 }
David Tolnay42602292016-10-01 22:25:45 -07003795 }
3796 }
3797 }
David Tolnay191e0582016-10-02 18:31:09 -07003798
Michael Layzell734adb42017-06-07 16:58:31 -04003799 #[cfg(feature = "full")]
David Tolnay191e0582016-10-02 18:31:09 -07003800 impl ToTokens for Local {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003801 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003802 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003803 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003804 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003805 if let Some((ref colon_token, ref ty)) = self.ty {
3806 colon_token.to_tokens(tokens);
3807 ty.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003808 }
David Tolnay8b4d3022017-12-29 12:11:10 -05003809 if let Some((ref eq_token, ref init)) = self.init {
3810 eq_token.to_tokens(tokens);
3811 init.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003812 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003813 self.semi_token.to_tokens(tokens);
David Tolnay191e0582016-10-02 18:31:09 -07003814 }
3815 }
David Tolnayf4bbbd92016-09-23 14:41:55 -07003816}