blob: b050e59debf4a7f12d5b8ea44f924d6802e9c7e9 [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 /// }
39 /// /* ... */
40 /// # _ => {}
41 /// }
42 /// # }
43 /// ```
44 ///
45 /// We begin with a variable `expr` of type `Expr` that has no fields
46 /// (because it is an enum), and by matching on it and rebinding a variable
47 /// with the same name `expr` we effectively imbue our variable with all of
48 /// the data fields provided by the variant that it turned out to be. So for
49 /// example above if we ended up in the `MethodCall` case then we get to use
David Tolnay9c119122018-09-01 18:47:02 -070050 /// `expr.receiver`, `expr.args` etc; if we ended up in the `If` case we get
51 /// to use `expr.cond`, `expr.then_branch`, `expr.else_branch`.
David Tolnay614a0142018-01-07 10:25:43 -080052 ///
53 /// The pattern is similar if the input expression is borrowed:
54 ///
David Tolnay95989db2019-01-01 15:05:57 -050055 /// ```edition2018
David Tolnay614a0142018-01-07 10:25:43 -080056 /// # use syn::Expr;
57 /// #
58 /// # fn example(expr: &Expr) {
59 /// match *expr {
60 /// Expr::MethodCall(ref expr) => {
61 /// # }
62 /// # _ => {}
63 /// # }
64 /// # }
65 /// ```
66 ///
67 /// This approach avoids repeating the variant names twice on every line.
68 ///
David Tolnay95989db2019-01-01 15:05:57 -050069 /// ```edition2018
David Tolnay614a0142018-01-07 10:25:43 -080070 /// # use syn::{Expr, ExprMethodCall};
71 /// #
72 /// # fn example(expr: Expr) {
73 /// # match expr {
74 /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => { // repetitive
75 /// # }
76 /// # _ => {}
77 /// # }
78 /// # }
79 /// ```
80 ///
81 /// In general, the name to which a syntax tree enum variant is bound should
82 /// be a suitable name for the complete syntax tree enum type.
83 ///
David Tolnay95989db2019-01-01 15:05:57 -050084 /// ```edition2018
David Tolnay614a0142018-01-07 10:25:43 -080085 /// # use syn::{Expr, ExprField};
86 /// #
87 /// # fn example(discriminant: &ExprField) {
88 /// // Binding is called `base` which is the name I would use if I were
89 /// // assigning `*discriminant.base` without an `if let`.
90 /// if let Expr::Tuple(ref base) = *discriminant.base {
91 /// # }
92 /// # }
93 /// ```
94 ///
95 /// A sign that you may not be choosing the right variable names is if you
96 /// see names getting repeated in your code, like accessing
97 /// `receiver.receiver` or `pat.pat` or `cond.cond`.
David Tolnay8c91b882017-12-28 23:04:32 -050098 pub enum Expr {
David Tolnaya454c8f2018-01-07 01:01:10 -080099 /// A box expression: `box f`.
David Tolnay461d98e2018-01-07 11:07:19 -0800100 ///
101 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400102 pub Box(ExprBox #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500103 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800104 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500105 pub expr: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700106 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500107
David Tolnaya454c8f2018-01-07 01:01:10 -0800108 /// A placement expression: `place <- value`.
David Tolnay461d98e2018-01-07 11:07:19 -0800109 ///
110 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400111 pub InPlace(ExprInPlace #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500112 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700113 pub place: Box<Expr>,
David Tolnay8701a5c2017-12-28 23:31:10 -0500114 pub arrow_token: Token![<-],
Alex Crichton62a0a592017-05-22 13:58:53 -0700115 pub value: Box<Expr>,
116 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500117
David Tolnaya454c8f2018-01-07 01:01:10 -0800118 /// A slice literal expression: `[a, b, c, d]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800119 ///
120 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400121 pub Array(ExprArray #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500122 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500123 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500124 pub elems: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700125 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500126
David Tolnaya454c8f2018-01-07 01:01:10 -0800127 /// A function call expression: `invoke(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800128 ///
129 /// *This type is available if Syn is built with the `"derive"` or
130 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700131 pub Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -0500132 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700133 pub func: Box<Expr>,
David Tolnay32954ef2017-12-26 22:43:16 -0500134 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500135 pub args: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700136 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500137
David Tolnaya454c8f2018-01-07 01:01:10 -0800138 /// A method call expression: `x.foo::<T>(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800139 ///
140 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400141 pub MethodCall(ExprMethodCall #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500142 pub attrs: Vec<Attribute>,
David Tolnay76418512017-12-28 23:47:47 -0500143 pub receiver: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800144 pub dot_token: Token![.],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500145 pub method: Ident,
David Tolnayd60cfec2017-12-29 00:21:38 -0500146 pub turbofish: Option<MethodTurbofish>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500147 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500148 pub args: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700149 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500150
David Tolnaya454c8f2018-01-07 01:01:10 -0800151 /// A tuple expression: `(a, b, c, d)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800152 ///
153 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay05362582017-12-26 01:33:57 -0500154 pub Tuple(ExprTuple #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500155 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500156 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500157 pub elems: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700158 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500159
David Tolnaya454c8f2018-01-07 01:01:10 -0800160 /// A binary operation: `a + b`, `a * b`.
David Tolnay461d98e2018-01-07 11:07:19 -0800161 ///
162 /// *This type is available if Syn is built with the `"derive"` or
163 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700164 pub Binary(ExprBinary {
David Tolnay8c91b882017-12-28 23:04:32 -0500165 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700166 pub left: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500167 pub op: BinOp,
Alex Crichton62a0a592017-05-22 13:58:53 -0700168 pub right: Box<Expr>,
169 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500170
David Tolnaya454c8f2018-01-07 01:01:10 -0800171 /// A unary operation: `!x`, `*x`.
David Tolnay461d98e2018-01-07 11:07:19 -0800172 ///
173 /// *This type is available if Syn is built with the `"derive"` or
174 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700175 pub Unary(ExprUnary {
David Tolnay8c91b882017-12-28 23:04:32 -0500176 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700177 pub op: UnOp,
178 pub expr: Box<Expr>,
179 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500180
David Tolnaya454c8f2018-01-07 01:01:10 -0800181 /// A literal in place of an expression: `1`, `"foo"`.
David Tolnay461d98e2018-01-07 11:07:19 -0800182 ///
183 /// *This type is available if Syn is built with the `"derive"` or
184 /// `"full"` feature.*
David Tolnay8c91b882017-12-28 23:04:32 -0500185 pub Lit(ExprLit {
186 pub attrs: Vec<Attribute>,
187 pub lit: Lit,
188 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500189
David Tolnaya454c8f2018-01-07 01:01:10 -0800190 /// A cast expression: `foo as f64`.
David Tolnay461d98e2018-01-07 11:07:19 -0800191 ///
192 /// *This type is available if Syn is built with the `"derive"` or
193 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700194 pub Cast(ExprCast {
David Tolnay8c91b882017-12-28 23:04:32 -0500195 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700196 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800197 pub as_token: Token![as],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800198 pub ty: Box<Type>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700199 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500200
David Tolnaya454c8f2018-01-07 01:01:10 -0800201 /// A type ascription expression: `foo: f64`.
David Tolnay461d98e2018-01-07 11:07:19 -0800202 ///
203 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay0cf94f22017-12-28 23:46:26 -0500204 pub Type(ExprType #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500205 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700206 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800207 pub colon_token: Token![:],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800208 pub ty: Box<Type>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700209 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500210
David Tolnay9c119122018-09-01 18:47:02 -0700211 /// A `let` guard: `let Some(x) = opt`.
212 ///
213 /// *This type is available if Syn is built with the `"full"` feature.*
214 pub Let(ExprLet #full {
215 pub attrs: Vec<Attribute>,
216 pub let_token: Token![let],
217 pub pats: Punctuated<Pat, Token![|]>,
218 pub eq_token: Token![=],
219 pub expr: Box<Expr>,
220 }),
221
David Tolnaya454c8f2018-01-07 01:01:10 -0800222 /// An `if` expression with an optional `else` block: `if expr { ... }
223 /// else { ... }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700224 ///
David Tolnay9c119122018-09-01 18:47:02 -0700225 /// The `else` branch expression may only be an `If` or `Block`
226 /// expression, not any of the other types of expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800227 ///
228 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400229 pub If(ExprIf #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500230 pub attrs: Vec<Attribute>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500231 pub if_token: Token![if],
Alex Crichton62a0a592017-05-22 13:58:53 -0700232 pub cond: Box<Expr>,
David Tolnay2ccf32a2017-12-29 00:34:26 -0500233 pub then_branch: Block,
234 pub else_branch: Option<(Token![else], Box<Expr>)>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700235 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500236
David Tolnaya454c8f2018-01-07 01:01:10 -0800237 /// A while loop: `while expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800238 ///
239 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400240 pub While(ExprWhile #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500241 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500242 pub label: Option<Label>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800243 pub while_token: Token![while],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500244 pub cond: Box<Expr>,
245 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700246 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500247
David Tolnaya454c8f2018-01-07 01:01:10 -0800248 /// A for loop: `for pat in expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800249 ///
250 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400251 pub ForLoop(ExprForLoop #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500252 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500253 pub label: Option<Label>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500254 pub for_token: Token![for],
Alex Crichton62a0a592017-05-22 13:58:53 -0700255 pub pat: Box<Pat>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500256 pub in_token: Token![in],
Alex Crichton62a0a592017-05-22 13:58:53 -0700257 pub expr: Box<Expr>,
258 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700259 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500260
David Tolnaya454c8f2018-01-07 01:01:10 -0800261 /// Conditionless loop: `loop { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800262 ///
263 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400264 pub Loop(ExprLoop #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500265 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500266 pub label: Option<Label>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500267 pub loop_token: Token![loop],
268 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700269 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500270
David Tolnaya454c8f2018-01-07 01:01:10 -0800271 /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800272 ///
273 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400274 pub Match(ExprMatch #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500275 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800276 pub match_token: Token![match],
Alex Crichton62a0a592017-05-22 13:58:53 -0700277 pub expr: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500278 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700279 pub arms: Vec<Arm>,
280 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500281
David Tolnaya454c8f2018-01-07 01:01:10 -0800282 /// A closure expression: `|a, b| a + b`.
David Tolnay461d98e2018-01-07 11:07:19 -0800283 ///
284 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400285 pub Closure(ExprClosure #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500286 pub attrs: Vec<Attribute>,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +0900287 pub asyncness: Option<Token![async]>,
David Tolnay13d4c0e2018-03-31 20:53:59 +0200288 pub movability: Option<Token![static]>,
David Tolnayefc96fb2017-12-29 02:03:15 -0500289 pub capture: Option<Token![move]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800290 pub or1_token: Token![|],
David Tolnayf2cfd722017-12-31 18:02:51 -0500291 pub inputs: Punctuated<FnArg, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800292 pub or2_token: Token![|],
David Tolnay7f675742017-12-27 22:43:21 -0500293 pub output: ReturnType,
294 pub body: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700295 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500296
David Tolnaya454c8f2018-01-07 01:01:10 -0800297 /// An unsafe block: `unsafe { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800298 ///
299 /// *This type is available if Syn is built with the `"full"` feature.*
Nika Layzell640832a2017-12-04 13:37:09 -0500300 pub Unsafe(ExprUnsafe #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500301 pub attrs: Vec<Attribute>,
Nika Layzell640832a2017-12-04 13:37:09 -0500302 pub unsafe_token: Token![unsafe],
303 pub block: Block,
304 }),
305
David Tolnaya454c8f2018-01-07 01:01:10 -0800306 /// A blocked scope: `{ ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800307 ///
308 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400309 pub Block(ExprBlock #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500310 pub attrs: Vec<Attribute>,
David Tolnay1d8e9962018-08-24 19:04:20 -0400311 pub label: Option<Label>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700312 pub block: Block,
313 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700314
David Tolnaya454c8f2018-01-07 01:01:10 -0800315 /// An assignment expression: `a = compute()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800316 ///
317 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400318 pub Assign(ExprAssign #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500319 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700320 pub left: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800321 pub eq_token: Token![=],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500322 pub right: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700323 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500324
David Tolnaya454c8f2018-01-07 01:01:10 -0800325 /// A compound assignment expression: `counter += 1`.
David Tolnay461d98e2018-01-07 11:07:19 -0800326 ///
327 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400328 pub AssignOp(ExprAssignOp #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500329 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700330 pub left: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500331 pub op: BinOp,
Alex Crichton62a0a592017-05-22 13:58:53 -0700332 pub right: Box<Expr>,
333 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500334
David Tolnaya454c8f2018-01-07 01:01:10 -0800335 /// Access of a named struct field (`obj.k`) or unnamed tuple struct
David Tolnay85b69a42017-12-27 20:43:10 -0500336 /// field (`obj.0`).
David Tolnay461d98e2018-01-07 11:07:19 -0800337 ///
338 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd5147742018-06-30 10:09:52 -0700339 pub Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -0500340 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -0500341 pub base: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800342 pub dot_token: Token![.],
David Tolnay85b69a42017-12-27 20:43:10 -0500343 pub member: Member,
Alex Crichton62a0a592017-05-22 13:58:53 -0700344 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500345
David Tolnay05658502018-01-07 09:56:37 -0800346 /// A square bracketed indexing expression: `vector[2]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800347 ///
348 /// *This type is available if Syn is built with the `"derive"` or
349 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700350 pub Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -0500351 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700352 pub expr: Box<Expr>,
David Tolnay32954ef2017-12-26 22:43:16 -0500353 pub bracket_token: token::Bracket,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500354 pub index: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700355 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500356
David Tolnaya454c8f2018-01-07 01:01:10 -0800357 /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800358 ///
359 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400360 pub Range(ExprRange #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500361 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700362 pub from: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700363 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500364 pub to: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700365 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700366
David Tolnaya454c8f2018-01-07 01:01:10 -0800367 /// A path like `std::mem::replace` possibly containing generic
368 /// parameters and a qualified self-type.
Alex Crichton62a0a592017-05-22 13:58:53 -0700369 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800370 /// A plain identifier like `x` is a path of length 1.
David Tolnay461d98e2018-01-07 11:07:19 -0800371 ///
372 /// *This type is available if Syn is built with the `"derive"` or
373 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700374 pub Path(ExprPath {
David Tolnay8c91b882017-12-28 23:04:32 -0500375 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700376 pub qself: Option<QSelf>,
377 pub path: Path,
378 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700379
David Tolnaya454c8f2018-01-07 01:01:10 -0800380 /// A referencing operation: `&a` or `&mut a`.
David Tolnay461d98e2018-01-07 11:07:19 -0800381 ///
382 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay00674ba2018-03-31 18:14:11 +0200383 pub Reference(ExprReference #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500384 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800385 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500386 pub mutability: Option<Token![mut]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700387 pub expr: Box<Expr>,
388 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500389
David Tolnaya454c8f2018-01-07 01:01:10 -0800390 /// A `break`, with an optional label to break and an optional
391 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800392 ///
393 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400394 pub Break(ExprBreak #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500395 pub attrs: Vec<Attribute>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500396 pub break_token: Token![break],
David Tolnay63e3dee2017-06-03 20:13:17 -0700397 pub label: Option<Lifetime>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700398 pub expr: Option<Box<Expr>>,
399 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500400
David Tolnaya454c8f2018-01-07 01:01:10 -0800401 /// A `continue`, with an optional label.
David Tolnay461d98e2018-01-07 11:07:19 -0800402 ///
403 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400404 pub Continue(ExprContinue #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500405 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800406 pub continue_token: Token![continue],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500407 pub label: Option<Lifetime>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700408 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500409
David Tolnaya454c8f2018-01-07 01:01:10 -0800410 /// A `return`, with an optional value to be returned.
David Tolnay461d98e2018-01-07 11:07:19 -0800411 ///
412 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayc246cd32017-12-28 23:14:32 -0500413 pub Return(ExprReturn #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500414 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800415 pub return_token: Token![return],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500416 pub expr: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700417 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700418
David Tolnaya454c8f2018-01-07 01:01:10 -0800419 /// A macro invocation expression: `format!("{}", q)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800420 ///
421 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay8c91b882017-12-28 23:04:32 -0500422 pub Macro(ExprMacro #full {
423 pub attrs: Vec<Attribute>,
424 pub mac: Macro,
425 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700426
David Tolnaya454c8f2018-01-07 01:01:10 -0800427 /// A struct literal expression: `Point { x: 1, y: 1 }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700428 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800429 /// The `rest` provides the value of the remaining fields as in `S { a:
430 /// 1, b: 1, ..rest }`.
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 Struct(ExprStruct #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500434 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700435 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500436 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500437 pub fields: Punctuated<FieldValue, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500438 pub dot2_token: Option<Token![..]>,
439 pub rest: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700440 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700441
David Tolnaya454c8f2018-01-07 01:01:10 -0800442 /// An array literal constructed from one repeated element: `[0u8; N]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800443 ///
444 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400445 pub Repeat(ExprRepeat #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500446 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500447 pub bracket_token: token::Bracket,
Alex Crichton62a0a592017-05-22 13:58:53 -0700448 pub expr: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500449 pub semi_token: Token![;],
David Tolnay84d80442018-01-07 01:03:20 -0800450 pub len: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700451 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700452
David Tolnaya454c8f2018-01-07 01:01:10 -0800453 /// A parenthesized expression: `(a + b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800454 ///
455 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay9374bc02018-01-27 18:49:36 -0800456 pub Paren(ExprParen {
David Tolnay8c91b882017-12-28 23:04:32 -0500457 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500458 pub paren_token: token::Paren,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500459 pub expr: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700460 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700461
David Tolnaya454c8f2018-01-07 01:01:10 -0800462 /// An expression contained within invisible delimiters.
Michael Layzell93c36282017-06-04 20:43:14 -0400463 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800464 /// This variant is important for faithfully representing the precedence
465 /// of expressions and is related to `None`-delimited spans in a
466 /// `TokenStream`.
David Tolnay461d98e2018-01-07 11:07:19 -0800467 ///
468 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaye98775f2017-12-28 23:17:00 -0500469 pub Group(ExprGroup #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500470 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500471 pub group_token: token::Group,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500472 pub expr: Box<Expr>,
Michael Layzell93c36282017-06-04 20:43:14 -0400473 }),
474
David Tolnaya454c8f2018-01-07 01:01:10 -0800475 /// A try-expression: `expr?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800476 ///
477 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400478 pub Try(ExprTry #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500479 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700480 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800481 pub question_token: Token![?],
Alex Crichton62a0a592017-05-22 13:58:53 -0700482 }),
Arnavion02ef13f2017-04-25 00:54:31 -0700483
David Tolnay02a9c6f2018-08-24 18:58:45 -0400484 /// An async block: `async { ... }`.
485 ///
486 /// *This type is available if Syn is built with the `"full"` feature.*
487 pub Async(ExprAsync #full {
488 pub attrs: Vec<Attribute>,
489 pub async_token: Token![async],
490 pub capture: Option<Token![move]>,
491 pub block: Block,
492 }),
493
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400494 /// A try block: `try { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800495 ///
496 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400497 pub TryBlock(ExprTryBlock #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500498 pub attrs: Vec<Attribute>,
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400499 pub try_token: Token![try],
Alex Crichton62a0a592017-05-22 13:58:53 -0700500 pub block: Block,
501 }),
Alex Crichtonfe110462017-06-01 12:49:27 -0700502
David Tolnaya454c8f2018-01-07 01:01:10 -0800503 /// A yield expression: `yield expr`.
David Tolnay461d98e2018-01-07 11:07:19 -0800504 ///
505 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonfe110462017-06-01 12:49:27 -0700506 pub Yield(ExprYield #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500507 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800508 pub yield_token: Token![yield],
Alex Crichtonfe110462017-06-01 12:49:27 -0700509 pub expr: Option<Box<Expr>>,
510 }),
David Tolnay2ae520a2017-12-29 11:19:50 -0500511
David Tolnaya454c8f2018-01-07 01:01:10 -0800512 /// Tokens in expression position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800513 ///
514 /// *This type is available if Syn is built with the `"derive"` or
515 /// `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500516 pub Verbatim(ExprVerbatim #manual_extra_traits {
517 pub tts: TokenStream,
518 }),
519 }
520}
521
522#[cfg(feature = "extra-traits")]
523impl Eq for ExprVerbatim {}
524
525#[cfg(feature = "extra-traits")]
526impl PartialEq for ExprVerbatim {
527 fn eq(&self, other: &Self) -> bool {
528 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
529 }
530}
531
532#[cfg(feature = "extra-traits")]
533impl Hash for ExprVerbatim {
534 fn hash<H>(&self, state: &mut H)
535 where
536 H: Hasher,
537 {
538 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700539 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700540}
541
David Tolnay8c91b882017-12-28 23:04:32 -0500542impl Expr {
David Tolnay631dca62018-09-01 02:46:25 -0700543 #[cfg(all(feature = "parsing", feature = "full"))]
David Tolnay94f06632018-08-31 10:17:17 -0700544 fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
David Tolnay8c91b882017-12-28 23:04:32 -0500545 match *self {
David Tolnay61037c62018-01-05 16:21:03 -0800546 Expr::Box(ExprBox { ref mut attrs, .. })
547 | Expr::InPlace(ExprInPlace { ref mut attrs, .. })
548 | Expr::Array(ExprArray { ref mut attrs, .. })
549 | Expr::Call(ExprCall { ref mut attrs, .. })
550 | Expr::MethodCall(ExprMethodCall { ref mut attrs, .. })
551 | Expr::Tuple(ExprTuple { ref mut attrs, .. })
552 | Expr::Binary(ExprBinary { ref mut attrs, .. })
553 | Expr::Unary(ExprUnary { ref mut attrs, .. })
554 | Expr::Lit(ExprLit { ref mut attrs, .. })
555 | Expr::Cast(ExprCast { ref mut attrs, .. })
556 | Expr::Type(ExprType { ref mut attrs, .. })
David Tolnay9c119122018-09-01 18:47:02 -0700557 | Expr::Let(ExprLet { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800558 | Expr::If(ExprIf { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800559 | Expr::While(ExprWhile { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800560 | Expr::ForLoop(ExprForLoop { ref mut attrs, .. })
561 | Expr::Loop(ExprLoop { ref mut attrs, .. })
562 | Expr::Match(ExprMatch { ref mut attrs, .. })
563 | Expr::Closure(ExprClosure { ref mut attrs, .. })
564 | Expr::Unsafe(ExprUnsafe { ref mut attrs, .. })
565 | Expr::Block(ExprBlock { ref mut attrs, .. })
566 | Expr::Assign(ExprAssign { ref mut attrs, .. })
567 | Expr::AssignOp(ExprAssignOp { ref mut attrs, .. })
568 | Expr::Field(ExprField { ref mut attrs, .. })
569 | Expr::Index(ExprIndex { ref mut attrs, .. })
570 | Expr::Range(ExprRange { ref mut attrs, .. })
571 | Expr::Path(ExprPath { ref mut attrs, .. })
David Tolnay00674ba2018-03-31 18:14:11 +0200572 | Expr::Reference(ExprReference { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800573 | Expr::Break(ExprBreak { ref mut attrs, .. })
574 | Expr::Continue(ExprContinue { ref mut attrs, .. })
575 | Expr::Return(ExprReturn { ref mut attrs, .. })
576 | Expr::Macro(ExprMacro { ref mut attrs, .. })
577 | Expr::Struct(ExprStruct { ref mut attrs, .. })
578 | Expr::Repeat(ExprRepeat { ref mut attrs, .. })
579 | Expr::Paren(ExprParen { ref mut attrs, .. })
580 | Expr::Group(ExprGroup { ref mut attrs, .. })
581 | Expr::Try(ExprTry { ref mut attrs, .. })
David Tolnay02a9c6f2018-08-24 18:58:45 -0400582 | Expr::Async(ExprAsync { ref mut attrs, .. })
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400583 | Expr::TryBlock(ExprTryBlock { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800584 | Expr::Yield(ExprYield { ref mut attrs, .. }) => mem::replace(attrs, new),
David Tolnay10f464a2018-08-30 18:48:55 -0700585 Expr::Verbatim(_) => Vec::new(),
David Tolnay8c91b882017-12-28 23:04:32 -0500586 }
587 }
588}
589
David Tolnay85b69a42017-12-27 20:43:10 -0500590ast_enum! {
591 /// A struct or tuple struct field accessed in a struct literal or field
592 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800593 ///
594 /// *This type is available if Syn is built with the `"derive"` or `"full"`
595 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500596 pub enum Member {
597 /// A named field like `self.x`.
598 Named(Ident),
599 /// An unnamed field like `self.0`.
600 Unnamed(Index),
601 }
602}
603
David Tolnay85b69a42017-12-27 20:43:10 -0500604ast_struct! {
605 /// The index of an unnamed tuple struct field.
David Tolnay461d98e2018-01-07 11:07:19 -0800606 ///
607 /// *This type is available if Syn is built with the `"derive"` or `"full"`
608 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500609 pub struct Index #manual_extra_traits {
610 pub index: u32,
611 pub span: Span,
612 }
613}
614
David Tolnay14982012017-12-29 00:49:51 -0500615impl From<usize> for Index {
616 fn from(index: usize) -> Index {
David Tolnay34071ba2018-05-20 20:00:41 -0700617 assert!(index < u32::max_value() as usize);
David Tolnay14982012017-12-29 00:49:51 -0500618 Index {
619 index: index as u32,
Alex Crichton9a4dca22018-03-28 06:32:19 -0700620 span: Span::call_site(),
David Tolnay14982012017-12-29 00:49:51 -0500621 }
622 }
623}
624
625#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500626impl Eq for Index {}
627
David Tolnay14982012017-12-29 00:49:51 -0500628#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500629impl PartialEq for Index {
630 fn eq(&self, other: &Self) -> bool {
631 self.index == other.index
632 }
633}
634
David Tolnay14982012017-12-29 00:49:51 -0500635#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500636impl Hash for Index {
637 fn hash<H: Hasher>(&self, state: &mut H) {
638 self.index.hash(state);
639 }
640}
641
642#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700643ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800644 /// The `::<>` explicit type parameters passed to a method call:
645 /// `parse::<u64>()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800646 ///
647 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500648 pub struct MethodTurbofish {
649 pub colon2_token: Token![::],
650 pub lt_token: Token![<],
David Tolnayf2cfd722017-12-31 18:02:51 -0500651 pub args: Punctuated<GenericMethodArgument, Token![,]>,
David Tolnayd60cfec2017-12-29 00:21:38 -0500652 pub gt_token: Token![>],
653 }
654}
655
656#[cfg(feature = "full")]
657ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800658 /// An individual generic argument to a method, like `T`.
David Tolnay461d98e2018-01-07 11:07:19 -0800659 ///
660 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500661 pub enum GenericMethodArgument {
David Tolnaya454c8f2018-01-07 01:01:10 -0800662 /// A type argument.
David Tolnayd60cfec2017-12-29 00:21:38 -0500663 Type(Type),
David Tolnaya454c8f2018-01-07 01:01:10 -0800664 /// A const expression. Must be inside of a block.
David Tolnayd60cfec2017-12-29 00:21:38 -0500665 ///
666 /// NOTE: Identity expressions are represented as Type arguments, as
667 /// they are indistinguishable syntactically.
668 Const(Expr),
669 }
670}
671
672#[cfg(feature = "full")]
673ast_struct! {
Alex Crichton62a0a592017-05-22 13:58:53 -0700674 /// A field-value pair in a struct literal.
David Tolnay461d98e2018-01-07 11:07:19 -0800675 ///
676 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700677 pub struct FieldValue {
David Tolnay85b69a42017-12-27 20:43:10 -0500678 /// Attributes tagged on the field.
679 pub attrs: Vec<Attribute>,
680
681 /// Name or index of the field.
682 pub member: Member,
683
David Tolnay5d7098a2017-12-29 01:35:24 -0500684 /// The colon in `Struct { x: x }`. If written in shorthand like
685 /// `Struct { x }`, there is no colon.
David Tolnay85b69a42017-12-27 20:43:10 -0500686 pub colon_token: Option<Token![:]>,
Clar Charrd22b5702017-03-10 15:24:56 -0500687
Alex Crichton62a0a592017-05-22 13:58:53 -0700688 /// Value of the field.
689 pub expr: Expr,
Alex Crichton62a0a592017-05-22 13:58:53 -0700690 }
David Tolnay055a7042016-10-02 19:23:54 -0700691}
692
Michael Layzell734adb42017-06-07 16:58:31 -0400693#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700694ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800695 /// A lifetime labeling a `for`, `while`, or `loop`.
David Tolnay461d98e2018-01-07 11:07:19 -0800696 ///
697 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaybcd498f2017-12-29 12:02:33 -0500698 pub struct Label {
699 pub name: Lifetime,
700 pub colon_token: Token![:],
701 }
702}
703
704#[cfg(feature = "full")]
705ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800706 /// A braced block containing Rust statements.
David Tolnay461d98e2018-01-07 11:07:19 -0800707 ///
708 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700709 pub struct Block {
David Tolnay32954ef2017-12-26 22:43:16 -0500710 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700711 /// Statements in a block
712 pub stmts: Vec<Stmt>,
713 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700714}
715
Michael Layzell734adb42017-06-07 16:58:31 -0400716#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700717ast_enum! {
718 /// A statement, usually ending in a semicolon.
David Tolnay461d98e2018-01-07 11:07:19 -0800719 ///
720 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700721 pub enum Stmt {
722 /// A local (let) binding.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800723 Local(Local),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700724
Alex Crichton62a0a592017-05-22 13:58:53 -0700725 /// An item definition.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800726 Item(Item),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700727
Alex Crichton62a0a592017-05-22 13:58:53 -0700728 /// Expr without trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800729 Expr(Expr),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700730
David Tolnaya454c8f2018-01-07 01:01:10 -0800731 /// Expression with trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800732 Semi(Expr, Token![;]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700733 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700734}
735
Michael Layzell734adb42017-06-07 16:58:31 -0400736#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700737ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800738 /// A local `let` binding: `let x: u64 = s.parse()?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800739 ///
740 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700741 pub struct Local {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500742 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800743 pub let_token: Token![let],
David Tolnay5b5b7d22018-03-31 21:05:00 +0200744 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500745 pub ty: Option<(Token![:], Box<Type>)>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500746 pub init: Option<(Token![=], Box<Expr>)>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500747 pub semi_token: Token![;],
Alex Crichton62a0a592017-05-22 13:58:53 -0700748 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700749}
750
Michael Layzell734adb42017-06-07 16:58:31 -0400751#[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700752ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800753 /// A pattern in a local binding, function signature, match expression, or
754 /// various other places.
David Tolnay614a0142018-01-07 10:25:43 -0800755 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800756 /// *This type is available if Syn is built with the `"full"` feature.*
757 ///
David Tolnay614a0142018-01-07 10:25:43 -0800758 /// # Syntax tree enum
759 ///
760 /// This type is a [syntax tree enum].
761 ///
762 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
Alex Crichton62a0a592017-05-22 13:58:53 -0700763 pub enum Pat {
David Tolnaya454c8f2018-01-07 01:01:10 -0800764 /// A pattern that matches any value: `_`.
David Tolnay461d98e2018-01-07 11:07:19 -0800765 ///
766 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700767 pub Wild(PatWild {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800768 pub underscore_token: Token![_],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700769 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700770
David Tolnaya454c8f2018-01-07 01:01:10 -0800771 /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
David Tolnay461d98e2018-01-07 11:07:19 -0800772 ///
773 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700774 pub Ident(PatIdent {
David Tolnay24237fb2017-12-29 02:15:26 -0500775 pub by_ref: Option<Token![ref]>,
776 pub mutability: Option<Token![mut]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700777 pub ident: Ident,
David Tolnay8b4d3022017-12-29 12:11:10 -0500778 pub subpat: Option<(Token![@], Box<Pat>)>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700779 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700780
David Tolnaya454c8f2018-01-07 01:01:10 -0800781 /// A struct or struct variant pattern: `Variant { x, y, .. }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800782 ///
783 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700784 pub Struct(PatStruct {
785 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500786 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500787 pub fields: Punctuated<FieldPat, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800788 pub dot2_token: Option<Token![..]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700789 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700790
David Tolnaya454c8f2018-01-07 01:01:10 -0800791 /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800792 ///
793 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700794 pub TupleStruct(PatTupleStruct {
795 pub path: Path,
796 pub pat: PatTuple,
797 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700798
David Tolnaya454c8f2018-01-07 01:01:10 -0800799 /// A path pattern like `Color::Red`, optionally qualified with a
800 /// self-type.
801 ///
Daniel Muellerd3d71a12019-01-28 06:10:46 -0800802 /// Unqualified path patterns can legally refer to variants, structs,
803 /// constants or associated constants. Qualified path patterns like
David Tolnaya454c8f2018-01-07 01:01:10 -0800804 /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
805 /// associated constants.
David Tolnay461d98e2018-01-07 11:07:19 -0800806 ///
807 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700808 pub Path(PatPath {
809 pub qself: Option<QSelf>,
810 pub path: Path,
811 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700812
David Tolnaya454c8f2018-01-07 01:01:10 -0800813 /// A tuple pattern: `(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800814 ///
815 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700816 pub Tuple(PatTuple {
David Tolnay32954ef2017-12-26 22:43:16 -0500817 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500818 pub front: Punctuated<Pat, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500819 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500820 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500821 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700822 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800823
824 /// A box pattern: `box v`.
David Tolnay461d98e2018-01-07 11:07:19 -0800825 ///
826 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700827 pub Box(PatBox {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800828 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500829 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700830 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800831
832 /// A reference pattern: `&mut (first, second)`.
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 Ref(PatRef {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800836 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500837 pub mutability: Option<Token![mut]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500838 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700839 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800840
841 /// A literal pattern: `0`.
842 ///
843 /// This holds an `Expr` rather than a `Lit` because negative numbers
844 /// are represented as an `Expr::Unary`.
David Tolnay461d98e2018-01-07 11:07:19 -0800845 ///
846 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700847 pub Lit(PatLit {
848 pub expr: Box<Expr>,
849 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800850
851 /// A range pattern: `1..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800852 ///
853 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700854 pub Range(PatRange {
855 pub lo: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700856 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500857 pub hi: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700858 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800859
860 /// A dynamically sized slice pattern: `[a, b, i.., y, z]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800861 ///
862 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700863 pub Slice(PatSlice {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500864 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500865 pub front: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700866 pub middle: Option<Box<Pat>>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500867 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500868 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500869 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700870 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800871
872 /// A macro in expression position.
David Tolnay461d98e2018-01-07 11:07:19 -0800873 ///
874 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay323279a2017-12-29 11:26:32 -0500875 pub Macro(PatMacro {
876 pub mac: Macro,
877 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800878
879 /// Tokens in pattern position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800880 ///
881 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500882 pub Verbatim(PatVerbatim #manual_extra_traits {
883 pub tts: TokenStream,
884 }),
885 }
886}
887
David Tolnayc43b44e2017-12-30 23:55:54 -0500888#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500889impl Eq for PatVerbatim {}
890
David Tolnayc43b44e2017-12-30 23:55:54 -0500891#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500892impl PartialEq for PatVerbatim {
893 fn eq(&self, other: &Self) -> bool {
894 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
895 }
896}
897
David Tolnayc43b44e2017-12-30 23:55:54 -0500898#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500899impl Hash for PatVerbatim {
900 fn hash<H>(&self, state: &mut H)
901 where
902 H: Hasher,
903 {
904 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700905 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700906}
907
Michael Layzell734adb42017-06-07 16:58:31 -0400908#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700909ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800910 /// One arm of a `match` expression: `0...10 => { return true; }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700911 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800912 /// As in:
Alex Crichton62a0a592017-05-22 13:58:53 -0700913 ///
David Tolnay95989db2019-01-01 15:05:57 -0500914 /// ```edition2018
David Tolnaya454c8f2018-01-07 01:01:10 -0800915 /// # fn f() -> bool {
David Tolnaybcf26022017-12-25 22:10:52 -0500916 /// # let n = 0;
Alex Crichton62a0a592017-05-22 13:58:53 -0700917 /// match n {
David Tolnaya454c8f2018-01-07 01:01:10 -0800918 /// 0...10 => {
919 /// return true;
920 /// }
921 /// // ...
David Tolnaybcf26022017-12-25 22:10:52 -0500922 /// # _ => {}
Alex Crichton62a0a592017-05-22 13:58:53 -0700923 /// }
David Tolnaya454c8f2018-01-07 01:01:10 -0800924 /// # false
David Tolnaybcf26022017-12-25 22:10:52 -0500925 /// # }
Alex Crichton62a0a592017-05-22 13:58:53 -0700926 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800927 ///
928 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700929 pub struct Arm {
930 pub attrs: Vec<Attribute>,
David Tolnay18cc4d42018-03-31 18:47:20 +0200931 pub leading_vert: Option<Token![|]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500932 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500933 pub guard: Option<(Token![if], Box<Expr>)>,
David Tolnaydfb91432018-03-31 19:19:44 +0200934 pub fat_arrow_token: Token![=>],
Alex Crichton62a0a592017-05-22 13:58:53 -0700935 pub body: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800936 pub comma: Option<Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700937 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700938}
939
Michael Layzell734adb42017-06-07 16:58:31 -0400940#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700941ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800942 /// Limit types of a range, inclusive or exclusive.
David Tolnay461d98e2018-01-07 11:07:19 -0800943 ///
944 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton2e0229c2017-05-23 09:34:50 -0700945 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700946 pub enum RangeLimits {
David Tolnaya454c8f2018-01-07 01:01:10 -0800947 /// Inclusive at the beginning, exclusive at the end.
David Tolnayf8db7ba2017-11-11 22:52:16 -0800948 HalfOpen(Token![..]),
David Tolnaya454c8f2018-01-07 01:01:10 -0800949 /// Inclusive at the beginning and end.
David Tolnaybe55d7b2017-12-17 23:41:20 -0800950 Closed(Token![..=]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700951 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700952}
953
Michael Layzell734adb42017-06-07 16:58:31 -0400954#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700955ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800956 /// A single field in a struct pattern.
Alex Crichton62a0a592017-05-22 13:58:53 -0700957 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800958 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
959 /// 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 -0800960 ///
961 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700962 pub struct FieldPat {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500963 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -0500964 pub member: Member,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500965 pub colon_token: Option<Token![:]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700966 pub pat: Box<Pat>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700967 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700968}
969
Michael Layzell3936ceb2017-07-08 00:28:36 -0400970#[cfg(any(feature = "parsing", feature = "printing"))]
971#[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -0700972fn requires_terminator(expr: &Expr) -> bool {
David Tolnay01218d12018-08-29 18:13:07 -0700973 // see https://github.com/rust-lang/rust/blob/eb8f2586e/src/libsyntax/parse/classify.rs#L17-L37
David Tolnay8c91b882017-12-28 23:04:32 -0500974 match *expr {
975 Expr::Unsafe(..)
976 | Expr::Block(..)
977 | Expr::If(..)
David Tolnay8c91b882017-12-28 23:04:32 -0500978 | Expr::Match(..)
979 | Expr::While(..)
David Tolnay8c91b882017-12-28 23:04:32 -0500980 | Expr::Loop(..)
981 | Expr::ForLoop(..)
David Tolnay02a9c6f2018-08-24 18:58:45 -0400982 | Expr::Async(..)
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400983 | Expr::TryBlock(..) => false,
Alex Crichton03b30272017-08-28 09:35:24 -0700984 _ => true,
Michael Layzell3936ceb2017-07-08 00:28:36 -0400985 }
986}
987
David Tolnayb9c8e322016-09-23 20:48:37 -0700988#[cfg(feature = "parsing")]
989pub mod parsing {
990 use super::*;
David Tolnayb9c8e322016-09-23 20:48:37 -0700991
Michael Layzell734adb42017-06-07 16:58:31 -0400992 #[cfg(feature = "full")]
David Tolnay94d304f2018-08-30 23:43:53 -0700993 use ext::IdentExt;
David Tolnay10951d52018-08-31 10:27:39 -0700994 use parse::{Parse, ParseStream, Result};
David Tolnay94d304f2018-08-30 23:43:53 -0700995 use path;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700996
David Tolnaybcf26022017-12-25 22:10:52 -0500997 // When we're parsing expressions which occur before blocks, like in an if
998 // statement's condition, we cannot parse a struct literal.
999 //
1000 // Struct literals are ambiguous in certain positions
1001 // https://github.com/rust-lang/rfcs/pull/92
David Tolnay9389c382018-08-27 09:13:37 -07001002 #[derive(Copy, Clone)]
1003 pub struct AllowStruct(bool);
1004
David Tolnay01218d12018-08-29 18:13:07 -07001005 #[derive(Copy, Clone, PartialEq, PartialOrd)]
1006 enum Precedence {
1007 Any,
1008 Assign,
1009 Placement,
1010 Range,
1011 Or,
1012 And,
1013 Compare,
1014 BitOr,
1015 BitXor,
1016 BitAnd,
1017 Shift,
1018 Arithmetic,
1019 Term,
1020 Cast,
1021 }
1022
1023 impl Precedence {
1024 fn of(op: &BinOp) -> Self {
1025 match *op {
1026 BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic,
1027 BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term,
1028 BinOp::And(_) => Precedence::And,
1029 BinOp::Or(_) => Precedence::Or,
1030 BinOp::BitXor(_) => Precedence::BitXor,
1031 BinOp::BitAnd(_) => Precedence::BitAnd,
1032 BinOp::BitOr(_) => Precedence::BitOr,
1033 BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
David Tolnay73b7ca12018-08-30 21:05:13 -07001034 BinOp::Eq(_)
1035 | BinOp::Lt(_)
1036 | BinOp::Le(_)
1037 | BinOp::Ne(_)
1038 | BinOp::Ge(_)
1039 | BinOp::Gt(_) => Precedence::Compare,
1040 BinOp::AddEq(_)
1041 | BinOp::SubEq(_)
1042 | BinOp::MulEq(_)
1043 | BinOp::DivEq(_)
1044 | BinOp::RemEq(_)
1045 | BinOp::BitXorEq(_)
1046 | BinOp::BitAndEq(_)
1047 | BinOp::BitOrEq(_)
1048 | BinOp::ShlEq(_)
1049 | BinOp::ShrEq(_) => Precedence::Assign,
David Tolnay01218d12018-08-29 18:13:07 -07001050 }
1051 }
1052 }
1053
David Tolnay9389c382018-08-27 09:13:37 -07001054 impl Parse for Expr {
1055 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001056 ambiguous_expr(input, AllowStruct(true))
Alex Crichton954046c2017-05-30 21:49:42 -07001057 }
1058 }
1059
Michael Layzell734adb42017-06-07 16:58:31 -04001060 #[cfg(feature = "full")]
David Tolnay9fb0aed2018-08-27 10:23:12 -07001061 fn expr_no_struct(input: ParseStream) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001062 ambiguous_expr(input, AllowStruct(false))
David Tolnay9fb0aed2018-08-27 10:23:12 -07001063 }
David Tolnayaf2557e2016-10-24 11:52:21 -07001064
David Tolnay01218d12018-08-29 18:13:07 -07001065 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001066 fn parse_expr(
1067 input: ParseStream,
1068 mut lhs: Expr,
1069 allow_struct: AllowStruct,
1070 base: Precedence,
1071 ) -> Result<Expr> {
David Tolnay01218d12018-08-29 18:13:07 -07001072 loop {
David Tolnay73b7ca12018-08-30 21:05:13 -07001073 if input
1074 .fork()
1075 .parse::<BinOp>()
1076 .ok()
1077 .map_or(false, |op| Precedence::of(&op) >= base)
1078 {
David Tolnay01218d12018-08-29 18:13:07 -07001079 let op: BinOp = input.parse()?;
1080 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001081 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001082 loop {
1083 let next = peek_precedence(input);
1084 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001085 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001086 } else {
1087 break;
1088 }
1089 }
David Tolnay90276252018-08-31 10:50:08 -07001090 lhs = if precedence == Precedence::Assign {
1091 Expr::AssignOp(ExprAssignOp {
1092 attrs: Vec::new(),
1093 left: Box::new(lhs),
1094 op: op,
1095 right: Box::new(rhs),
1096 })
1097 } else {
1098 Expr::Binary(ExprBinary {
1099 attrs: Vec::new(),
1100 left: Box::new(lhs),
1101 op: op,
1102 right: Box::new(rhs),
1103 })
1104 };
David Tolnay73b7ca12018-08-30 21:05:13 -07001105 } else if Precedence::Assign >= base
1106 && input.peek(Token![=])
1107 && !input.peek(Token![==])
1108 && !input.peek(Token![=>])
1109 {
David Tolnay01218d12018-08-29 18:13:07 -07001110 let eq_token: Token![=] = input.parse()?;
David Tolnay7d2e1db2018-08-30 11:49:04 -07001111 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001112 loop {
1113 let next = peek_precedence(input);
1114 if next >= Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001115 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001116 } else {
1117 break;
1118 }
1119 }
1120 lhs = Expr::Assign(ExprAssign {
1121 attrs: Vec::new(),
1122 left: Box::new(lhs),
1123 eq_token: eq_token,
1124 right: Box::new(rhs),
1125 });
1126 } else if Precedence::Placement >= base && input.peek(Token![<-]) {
1127 let arrow_token: Token![<-] = input.parse()?;
David Tolnay7d2e1db2018-08-30 11:49:04 -07001128 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001129 loop {
1130 let next = peek_precedence(input);
1131 if next > Precedence::Placement {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001132 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001133 } else {
1134 break;
1135 }
1136 }
1137 lhs = Expr::InPlace(ExprInPlace {
1138 attrs: Vec::new(),
1139 place: Box::new(lhs),
1140 arrow_token: arrow_token,
1141 value: Box::new(rhs),
1142 });
1143 } else if Precedence::Range >= base && input.peek(Token![..]) {
1144 let limits: RangeLimits = input.parse()?;
1145 let rhs = if input.is_empty()
1146 || input.peek(Token![,])
1147 || input.peek(Token![;])
1148 || !allow_struct.0 && input.peek(token::Brace)
1149 {
1150 None
1151 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001152 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001153 loop {
1154 let next = peek_precedence(input);
1155 if next > Precedence::Range {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001156 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001157 } else {
1158 break;
1159 }
1160 }
1161 Some(rhs)
1162 };
1163 lhs = Expr::Range(ExprRange {
1164 attrs: Vec::new(),
1165 from: Some(Box::new(lhs)),
1166 limits: limits,
1167 to: rhs.map(Box::new),
1168 });
1169 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1170 let as_token: Token![as] = input.parse()?;
1171 let ty = input.call(Type::without_plus)?;
1172 lhs = Expr::Cast(ExprCast {
1173 attrs: Vec::new(),
1174 expr: Box::new(lhs),
1175 as_token: as_token,
1176 ty: Box::new(ty),
1177 });
1178 } else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) {
1179 let colon_token: Token![:] = input.parse()?;
1180 let ty = input.call(Type::without_plus)?;
1181 lhs = Expr::Type(ExprType {
1182 attrs: Vec::new(),
1183 expr: Box::new(lhs),
1184 colon_token: colon_token,
1185 ty: Box::new(ty),
1186 });
1187 } else {
1188 break;
1189 }
1190 }
1191 Ok(lhs)
1192 }
1193
David Tolnay3e541292018-08-30 11:42:15 -07001194 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001195 fn parse_expr(
1196 input: ParseStream,
1197 mut lhs: Expr,
1198 allow_struct: AllowStruct,
1199 base: Precedence,
1200 ) -> Result<Expr> {
David Tolnay3e541292018-08-30 11:42:15 -07001201 loop {
David Tolnay73b7ca12018-08-30 21:05:13 -07001202 if input
1203 .fork()
1204 .parse::<BinOp>()
1205 .ok()
1206 .map_or(false, |op| Precedence::of(&op) >= base)
1207 {
David Tolnay3e541292018-08-30 11:42:15 -07001208 let op: BinOp = input.parse()?;
1209 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001210 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay3e541292018-08-30 11:42:15 -07001211 loop {
1212 let next = peek_precedence(input);
1213 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001214 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay3e541292018-08-30 11:42:15 -07001215 } else {
1216 break;
1217 }
1218 }
1219 lhs = Expr::Binary(ExprBinary {
1220 attrs: Vec::new(),
1221 left: Box::new(lhs),
1222 op: op,
1223 right: Box::new(rhs),
1224 });
1225 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1226 let as_token: Token![as] = input.parse()?;
1227 let ty = input.call(Type::without_plus)?;
1228 lhs = Expr::Cast(ExprCast {
1229 attrs: Vec::new(),
1230 expr: Box::new(lhs),
1231 as_token: as_token,
1232 ty: Box::new(ty),
1233 });
1234 } else {
1235 break;
1236 }
1237 }
1238 Ok(lhs)
1239 }
1240
David Tolnay01218d12018-08-29 18:13:07 -07001241 fn peek_precedence(input: ParseStream) -> Precedence {
1242 if let Ok(op) = input.fork().parse() {
1243 Precedence::of(&op)
David Tolnay3e541292018-08-30 11:42:15 -07001244 } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
David Tolnay01218d12018-08-29 18:13:07 -07001245 Precedence::Assign
1246 } else if input.peek(Token![<-]) {
1247 Precedence::Placement
1248 } else if input.peek(Token![..]) {
1249 Precedence::Range
1250 } else if input.peek(Token![as]) || input.peek(Token![:]) && !input.peek(Token![::]) {
1251 Precedence::Cast
1252 } else {
1253 Precedence::Any
1254 }
1255 }
1256
David Tolnaybcf26022017-12-25 22:10:52 -05001257 // Parse an arbitrary expression.
David Tolnay73b7ca12018-08-30 21:05:13 -07001258 fn ambiguous_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001259 let lhs = unary_expr(input, allow_struct)?;
1260 parse_expr(input, lhs, allow_struct, Precedence::Any)
Michael Layzellb78f3b52017-06-04 19:03:03 -04001261 }
1262
David Tolnaybcf26022017-12-25 22:10:52 -05001263 // <UnOp> <trailer>
1264 // & <trailer>
1265 // &mut <trailer>
1266 // box <trailer>
Michael Layzell734adb42017-06-07 16:58:31 -04001267 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001268 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001269 let ahead = input.fork();
1270 ahead.call(Attribute::parse_outer)?;
1271 if ahead.peek(Token![&])
1272 || ahead.peek(Token![box])
1273 || ahead.peek(Token![*])
1274 || ahead.peek(Token![!])
1275 || ahead.peek(Token![-])
1276 {
1277 let attrs = input.call(Attribute::parse_outer)?;
1278 if input.peek(Token![&]) {
1279 Ok(Expr::Reference(ExprReference {
1280 attrs: attrs,
1281 and_token: input.parse()?,
1282 mutability: 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 } else if input.peek(Token![box]) {
1286 Ok(Expr::Box(ExprBox {
1287 attrs: attrs,
1288 box_token: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001289 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001290 }))
1291 } else {
1292 Ok(Expr::Unary(ExprUnary {
1293 attrs: attrs,
1294 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001295 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001296 }))
1297 }
1298 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001299 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001300 }
1301 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001302
Michael Layzell734adb42017-06-07 16:58:31 -04001303 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001304 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001305 let ahead = input.fork();
1306 ahead.call(Attribute::parse_outer)?;
1307 if ahead.peek(Token![*]) || ahead.peek(Token![!]) || ahead.peek(Token![-]) {
1308 Ok(Expr::Unary(ExprUnary {
1309 attrs: input.call(Attribute::parse_outer)?,
1310 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001311 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001312 }))
1313 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001314 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001315 }
1316 }
Michael Layzell734adb42017-06-07 16:58:31 -04001317
David Tolnaybcf26022017-12-25 22:10:52 -05001318 // <atom> (..<args>) ...
1319 // <atom> . <ident> (..<args>) ...
1320 // <atom> . <ident> ...
1321 // <atom> . <lit> ...
1322 // <atom> [ <expr> ] ...
1323 // <atom> ? ...
Michael Layzell734adb42017-06-07 16:58:31 -04001324 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001325 fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay577fd312018-09-01 02:26:40 -07001326 if input.peek(token::Group) {
1327 return input.call(expr_group).map(Expr::Group);
1328 }
David Tolnay1501f7e2018-08-27 14:21:03 -07001329
David Tolnay577fd312018-09-01 02:26:40 -07001330 let outer_attrs = input.call(Attribute::parse_outer)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001331
David Tolnay577fd312018-09-01 02:26:40 -07001332 let atom = atom_expr(input, allow_struct)?;
1333 let mut e = trailer_helper(input, atom)?;
David Tolnay01218d12018-08-29 18:13:07 -07001334
David Tolnay577fd312018-09-01 02:26:40 -07001335 let inner_attrs = e.replace_attrs(Vec::new());
1336 let attrs = private::attrs(outer_attrs, inner_attrs);
David Tolnay01218d12018-08-29 18:13:07 -07001337 e.replace_attrs(attrs);
1338 Ok(e)
1339 }
1340
1341 #[cfg(feature = "full")]
1342 fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
David Tolnay1501f7e2018-08-27 14:21:03 -07001343 loop {
1344 if input.peek(token::Paren) {
1345 let content;
1346 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001347 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001348 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001349 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001350 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001351 });
1352 } else if input.peek(Token![.]) && !input.peek(Token![..]) {
1353 let dot_token: Token![.] = input.parse()?;
1354 let member: Member = input.parse()?;
1355 let turbofish = if member.is_named() && input.peek(Token![::]) {
1356 Some(MethodTurbofish {
1357 colon2_token: input.parse()?,
1358 lt_token: input.parse()?,
1359 args: {
1360 let mut args = Punctuated::new();
1361 loop {
1362 if input.peek(Token![>]) {
1363 break;
1364 }
David Tolnay310b3262018-08-30 15:33:00 -07001365 let value = input.call(generic_method_argument)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001366 args.push_value(value);
1367 if input.peek(Token![>]) {
1368 break;
1369 }
1370 let punct = input.parse()?;
1371 args.push_punct(punct);
1372 }
1373 args
1374 },
1375 gt_token: input.parse()?,
1376 })
1377 } else {
1378 None
1379 };
1380
1381 if turbofish.is_some() || input.peek(token::Paren) {
1382 if let Member::Named(method) = member {
1383 let content;
1384 e = Expr::MethodCall(ExprMethodCall {
1385 attrs: Vec::new(),
1386 receiver: Box::new(e),
1387 dot_token: dot_token,
1388 method: method,
1389 turbofish: turbofish,
1390 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001391 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001392 });
1393 continue;
1394 }
1395 }
1396
1397 e = Expr::Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -05001398 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001399 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001400 dot_token: dot_token,
David Tolnay85b69a42017-12-27 20:43:10 -05001401 member: member,
David Tolnay1501f7e2018-08-27 14:21:03 -07001402 });
1403 } else if input.peek(token::Bracket) {
1404 let content;
1405 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001406 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001407 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001408 bracket_token: bracketed!(content in input),
1409 index: content.parse()?,
1410 });
1411 } else if input.peek(Token![?]) {
1412 e = Expr::Try(ExprTry {
David Tolnay8c91b882017-12-28 23:04:32 -05001413 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001414 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001415 question_token: input.parse()?,
1416 });
1417 } else {
1418 break;
1419 }
1420 }
David Tolnay1501f7e2018-08-27 14:21:03 -07001421 Ok(e)
1422 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001423
Michael Layzell734adb42017-06-07 16:58:31 -04001424 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001425 fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001426 let mut e = atom_expr(input, allow_struct)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001427
1428 loop {
1429 if input.peek(token::Paren) {
1430 let content;
1431 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001432 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001433 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001434 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001435 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001436 });
1437 } else if input.peek(Token![.]) {
1438 e = Expr::Field(ExprField {
David Tolnayd5147742018-06-30 10:09:52 -07001439 attrs: Vec::new(),
1440 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001441 dot_token: input.parse()?,
1442 member: input.parse()?,
1443 });
1444 } else if input.peek(token::Bracket) {
1445 let content;
1446 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001447 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001448 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001449 bracket_token: bracketed!(content in input),
1450 index: content.parse()?,
1451 });
1452 } else {
1453 break;
1454 }
1455 }
1456
1457 Ok(e)
1458 }
Michael Layzell734adb42017-06-07 16:58:31 -04001459
David Tolnaya454c8f2018-01-07 01:01:10 -08001460 // Parse all atomic expressions which don't have to worry about precedence
David Tolnaybcf26022017-12-25 22:10:52 -05001461 // interactions, as they are fully contained.
Michael Layzell734adb42017-06-07 16:58:31 -04001462 #[cfg(feature = "full")]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001463 fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001464 if input.peek(token::Group) {
David Tolnay577fd312018-09-01 02:26:40 -07001465 input.call(expr_group).map(Expr::Group)
David Tolnay6e1e5052018-08-30 10:21:48 -07001466 } else if input.peek(Lit) {
Peter Hall04f42792019-04-02 16:58:45 +02001467 input.parse().map(Expr::Lit)
David Tolnay6e1e5052018-08-30 10:21:48 -07001468 } else if input.peek(Token![async])
1469 && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
1470 {
David Tolnay577fd312018-09-01 02:26:40 -07001471 input.call(expr_async).map(Expr::Async)
David Tolnay6e1e5052018-08-30 10:21:48 -07001472 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay577fd312018-09-01 02:26:40 -07001473 input.call(expr_try_block).map(Expr::TryBlock)
David Tolnay6e1e5052018-08-30 10:21:48 -07001474 } else if input.peek(Token![|])
1475 || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1476 || input.peek(Token![static])
1477 || input.peek(Token![move])
1478 {
David Tolnay577fd312018-09-01 02:26:40 -07001479 expr_closure(input, allow_struct).map(Expr::Closure)
David Tolnay6e1e5052018-08-30 10:21:48 -07001480 } else if input.peek(Ident)
1481 || input.peek(Token![::])
1482 || input.peek(Token![<])
1483 || input.peek(Token![self])
1484 || input.peek(Token![Self])
1485 || input.peek(Token![super])
1486 || input.peek(Token![extern])
1487 || input.peek(Token![crate])
1488 {
David Tolnay577fd312018-09-01 02:26:40 -07001489 path_or_macro_or_struct(input, allow_struct)
David Tolnay6e1e5052018-08-30 10:21:48 -07001490 } else if input.peek(token::Paren) {
David Tolnay577fd312018-09-01 02:26:40 -07001491 paren_or_tuple(input)
David Tolnay6e1e5052018-08-30 10:21:48 -07001492 } else if input.peek(Token![break]) {
David Tolnay577fd312018-09-01 02:26:40 -07001493 expr_break(input, allow_struct).map(Expr::Break)
David Tolnay6e1e5052018-08-30 10:21:48 -07001494 } else if input.peek(Token![continue]) {
David Tolnay577fd312018-09-01 02:26:40 -07001495 input.call(expr_continue).map(Expr::Continue)
David Tolnay6e1e5052018-08-30 10:21:48 -07001496 } else if input.peek(Token![return]) {
David Tolnay577fd312018-09-01 02:26:40 -07001497 expr_ret(input, allow_struct).map(Expr::Return)
David Tolnay6e1e5052018-08-30 10:21:48 -07001498 } else if input.peek(token::Bracket) {
David Tolnay577fd312018-09-01 02:26:40 -07001499 array_or_repeat(input)
David Tolnay9c119122018-09-01 18:47:02 -07001500 } else if input.peek(Token![let]) {
1501 input.call(expr_let).map(Expr::Let)
David Tolnay6e1e5052018-08-30 10:21:48 -07001502 } else if input.peek(Token![if]) {
Peter Hall04f42792019-04-02 16:58:45 +02001503 input.parse().map(Expr::If)
David Tolnay6e1e5052018-08-30 10:21:48 -07001504 } else if input.peek(Token![while]) {
Peter Hall04f42792019-04-02 16:58:45 +02001505 input.parse().map(Expr::While)
David Tolnay6e1e5052018-08-30 10:21:48 -07001506 } else if input.peek(Token![for]) {
Peter Hall04f42792019-04-02 16:58:45 +02001507 input.parse().map(Expr::ForLoop)
David Tolnay6e1e5052018-08-30 10:21:48 -07001508 } else if input.peek(Token![loop]) {
Peter Hall04f42792019-04-02 16:58:45 +02001509 input.parse().map(Expr::Loop)
David Tolnay6e1e5052018-08-30 10:21:48 -07001510 } else if input.peek(Token![match]) {
Peter Hall55f00f72019-04-02 16:50:57 +02001511 input.parse().map(Expr::Match)
David Tolnay6e1e5052018-08-30 10:21:48 -07001512 } else if input.peek(Token![yield]) {
David Tolnay577fd312018-09-01 02:26:40 -07001513 input.call(expr_yield).map(Expr::Yield)
David Tolnay6e1e5052018-08-30 10:21:48 -07001514 } else if input.peek(Token![unsafe]) {
David Tolnay577fd312018-09-01 02:26:40 -07001515 input.call(expr_unsafe).map(Expr::Unsafe)
David Tolnay7d2e1db2018-08-30 11:49:04 -07001516 } else if input.peek(token::Brace) {
David Tolnay577fd312018-09-01 02:26:40 -07001517 input.call(expr_block).map(Expr::Block)
David Tolnay6e1e5052018-08-30 10:21:48 -07001518 } else if input.peek(Token![..]) {
David Tolnay577fd312018-09-01 02:26:40 -07001519 expr_range(input, allow_struct).map(Expr::Range)
David Tolnay6e1e5052018-08-30 10:21:48 -07001520 } else if input.peek(Lifetime) {
1521 let the_label: Label = input.parse()?;
1522 let mut expr = if input.peek(Token![while]) {
Peter Hall04f42792019-04-02 16:58:45 +02001523 Expr::While(input.parse()?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001524 } else if input.peek(Token![for]) {
Peter Hall04f42792019-04-02 16:58:45 +02001525 Expr::ForLoop(input.parse()?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001526 } else if input.peek(Token![loop]) {
Peter Hall04f42792019-04-02 16:58:45 +02001527 Expr::Loop(input.parse()?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001528 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001529 Expr::Block(input.call(expr_block)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001530 } else {
1531 return Err(input.error("expected loop or block expression"));
1532 };
1533 match expr {
David Tolnay9c119122018-09-01 18:47:02 -07001534 Expr::While(ExprWhile { ref mut label, .. })
David Tolnay73b7ca12018-08-30 21:05:13 -07001535 | Expr::ForLoop(ExprForLoop { ref mut label, .. })
1536 | Expr::Loop(ExprLoop { ref mut label, .. })
1537 | Expr::Block(ExprBlock { ref mut label, .. }) => *label = Some(the_label),
David Tolnay6e1e5052018-08-30 10:21:48 -07001538 _ => unreachable!(),
1539 }
David Tolnay577fd312018-09-01 02:26:40 -07001540 Ok(expr)
David Tolnay6e1e5052018-08-30 10:21:48 -07001541 } else {
David Tolnay577fd312018-09-01 02:26:40 -07001542 Err(input.error("expected expression"))
1543 }
David Tolnay6e1e5052018-08-30 10:21:48 -07001544 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001545
Michael Layzell734adb42017-06-07 16:58:31 -04001546 #[cfg(not(feature = "full"))]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001547 fn atom_expr(input: ParseStream, _allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001548 if input.peek(Lit) {
Peter Hall04f42792019-04-02 16:58:45 +02001549 input.parse().map(Expr::Lit)
David Tolnay6e1e5052018-08-30 10:21:48 -07001550 } else if input.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07001551 input.call(expr_paren).map(Expr::Paren)
David Tolnay6e1e5052018-08-30 10:21:48 -07001552 } else if input.peek(Ident)
1553 || input.peek(Token![::])
1554 || input.peek(Token![<])
1555 || input.peek(Token![self])
1556 || input.peek(Token![Self])
1557 || input.peek(Token![super])
1558 || input.peek(Token![extern])
1559 || input.peek(Token![crate])
1560 {
1561 input.parse().map(Expr::Path)
1562 } else {
1563 Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
1564 }
1565 }
1566
1567 #[cfg(feature = "full")]
1568 fn path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1569 let expr: ExprPath = input.parse()?;
1570 if expr.qself.is_some() {
1571 return Ok(Expr::Path(expr));
1572 }
1573
1574 if input.peek(Token![!]) && !input.peek(Token![!=]) {
1575 let mut contains_arguments = false;
1576 for segment in &expr.path.segments {
1577 match segment.arguments {
1578 PathArguments::None => {}
1579 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
1580 contains_arguments = true;
1581 }
1582 }
1583 }
1584
1585 if !contains_arguments {
1586 let bang_token: Token![!] = input.parse()?;
1587 let (delimiter, tts) = mac::parse_delimiter(input)?;
1588 return Ok(Expr::Macro(ExprMacro {
1589 attrs: Vec::new(),
1590 mac: Macro {
1591 path: expr.path,
1592 bang_token: bang_token,
1593 delimiter: delimiter,
1594 tts: tts,
1595 },
1596 }));
1597 }
1598 }
1599
1600 if allow_struct.0 && input.peek(token::Brace) {
1601 let outer_attrs = Vec::new();
1602 expr_struct_helper(input, outer_attrs, expr.path).map(Expr::Struct)
1603 } else {
1604 Ok(Expr::Path(expr))
1605 }
1606 }
1607
1608 #[cfg(feature = "full")]
1609 fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
1610 let content;
1611 let paren_token = parenthesized!(content in input);
1612 let inner_attrs = content.call(Attribute::parse_inner)?;
1613 if content.is_empty() {
1614 return Ok(Expr::Tuple(ExprTuple {
1615 attrs: inner_attrs,
1616 paren_token: paren_token,
1617 elems: Punctuated::new(),
1618 }));
1619 }
1620
1621 let first: Expr = content.parse()?;
1622 if content.is_empty() {
1623 return Ok(Expr::Paren(ExprParen {
1624 attrs: inner_attrs,
1625 paren_token: paren_token,
1626 expr: Box::new(first),
1627 }));
1628 }
1629
1630 let mut elems = Punctuated::new();
1631 elems.push_value(first);
1632 while !content.is_empty() {
1633 let punct = content.parse()?;
1634 elems.push_punct(punct);
1635 if content.is_empty() {
1636 break;
1637 }
1638 let value = content.parse()?;
1639 elems.push_value(value);
1640 }
1641 Ok(Expr::Tuple(ExprTuple {
1642 attrs: inner_attrs,
1643 paren_token: paren_token,
1644 elems: elems,
1645 }))
1646 }
1647
1648 #[cfg(feature = "full")]
1649 fn array_or_repeat(input: ParseStream) -> Result<Expr> {
1650 let content;
1651 let bracket_token = bracketed!(content in input);
1652 let inner_attrs = content.call(Attribute::parse_inner)?;
1653 if content.is_empty() {
1654 return Ok(Expr::Array(ExprArray {
1655 attrs: inner_attrs,
1656 bracket_token: bracket_token,
1657 elems: Punctuated::new(),
1658 }));
1659 }
1660
1661 let first: Expr = content.parse()?;
1662 if content.is_empty() || content.peek(Token![,]) {
1663 let mut elems = Punctuated::new();
1664 elems.push_value(first);
1665 while !content.is_empty() {
1666 let punct = content.parse()?;
1667 elems.push_punct(punct);
1668 if content.is_empty() {
1669 break;
1670 }
1671 let value = content.parse()?;
1672 elems.push_value(value);
1673 }
1674 Ok(Expr::Array(ExprArray {
1675 attrs: inner_attrs,
1676 bracket_token: bracket_token,
1677 elems: elems,
1678 }))
1679 } else if content.peek(Token![;]) {
1680 let semi_token: Token![;] = content.parse()?;
1681 let len: Expr = content.parse()?;
1682 Ok(Expr::Repeat(ExprRepeat {
1683 attrs: inner_attrs,
1684 bracket_token: bracket_token,
1685 expr: Box::new(first),
1686 semi_token: semi_token,
1687 len: Box::new(len),
1688 }))
1689 } else {
1690 Err(content.error("expected `,` or `;`"))
1691 }
1692 }
Michael Layzell734adb42017-06-07 16:58:31 -04001693
Michael Layzell734adb42017-06-07 16:58:31 -04001694 #[cfg(feature = "full")]
David Tolnay01218d12018-08-29 18:13:07 -07001695 fn expr_early(input: ParseStream) -> Result<Expr> {
1696 let mut attrs = input.call(Attribute::parse_outer)?;
1697 let mut expr = if input.peek(Token![if]) {
Peter Hall04f42792019-04-02 16:58:45 +02001698 Expr::If(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001699 } else if input.peek(Token![while]) {
Peter Hall04f42792019-04-02 16:58:45 +02001700 Expr::While(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001701 } else if input.peek(Token![for]) {
Peter Hall04f42792019-04-02 16:58:45 +02001702 Expr::ForLoop(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001703 } else if input.peek(Token![loop]) {
Peter Hall04f42792019-04-02 16:58:45 +02001704 Expr::Loop(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001705 } else if input.peek(Token![match]) {
Peter Hall55f00f72019-04-02 16:50:57 +02001706 Expr::Match(input.parse()?)
David Tolnay01218d12018-08-29 18:13:07 -07001707 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001708 Expr::TryBlock(input.call(expr_try_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001709 } else if input.peek(Token![unsafe]) {
David Tolnay310b3262018-08-30 15:33:00 -07001710 Expr::Unsafe(input.call(expr_unsafe)?)
David Tolnay01218d12018-08-29 18:13:07 -07001711 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001712 Expr::Block(input.call(expr_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001713 } else {
1714 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001715 let mut expr = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001716
1717 attrs.extend(expr.replace_attrs(Vec::new()));
1718 expr.replace_attrs(attrs);
1719
David Tolnay7d2e1db2018-08-30 11:49:04 -07001720 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001721 };
1722
1723 if input.peek(Token![.]) || input.peek(Token![?]) {
1724 expr = trailer_helper(input, expr)?;
1725
1726 attrs.extend(expr.replace_attrs(Vec::new()));
1727 expr.replace_attrs(attrs);
1728
1729 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001730 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001731 }
1732
1733 attrs.extend(expr.replace_attrs(Vec::new()));
1734 expr.replace_attrs(attrs);
1735 Ok(expr)
1736 }
Michael Layzell35418782017-06-07 09:20:25 -04001737
Peter Hall04f42792019-04-02 16:58:45 +02001738 impl Parse for ExprLit {
1739 fn parse(input: ParseStream) -> Result<Self> {
1740 Ok(ExprLit {
1741 attrs: Vec::new(),
1742 lit: input.parse()?,
1743 })
1744 }
David Tolnay8c91b882017-12-28 23:04:32 -05001745 }
1746
1747 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001748 fn expr_group(input: ParseStream) -> Result<ExprGroup> {
David Tolnay10951d52018-08-31 10:27:39 -07001749 let group = private::parse_group(input)?;
David Tolnay310b3262018-08-30 15:33:00 -07001750 Ok(ExprGroup {
1751 attrs: Vec::new(),
David Tolnayf57f76f2018-08-31 10:23:17 -07001752 group_token: group.token,
1753 expr: group.content.parse()?,
David Tolnay310b3262018-08-30 15:33:00 -07001754 })
1755 }
1756
1757 #[cfg(not(feature = "full"))]
1758 fn expr_paren(input: ParseStream) -> Result<ExprParen> {
1759 let content;
1760 Ok(ExprParen {
1761 attrs: Vec::new(),
1762 paren_token: parenthesized!(content in input),
1763 expr: content.parse()?,
1764 })
David Tolnay8c91b882017-12-28 23:04:32 -05001765 }
1766
David Tolnaye98775f2017-12-28 23:17:00 -05001767 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001768 fn generic_method_argument(input: ParseStream) -> Result<GenericMethodArgument> {
David Tolnayd60cfec2017-12-29 00:21:38 -05001769 // TODO parse const generics as well
David Tolnay8db2d662018-08-30 17:40:59 -07001770 input.parse().map(GenericMethodArgument::Type)
David Tolnayd60cfec2017-12-29 00:21:38 -05001771 }
1772
1773 #[cfg(feature = "full")]
David Tolnay9c119122018-09-01 18:47:02 -07001774 fn expr_let(input: ParseStream) -> Result<ExprLet> {
1775 Ok(ExprLet {
David Tolnay310b3262018-08-30 15:33:00 -07001776 attrs: Vec::new(),
David Tolnay310b3262018-08-30 15:33:00 -07001777 let_token: input.parse()?,
1778 pats: {
1779 let mut pats = Punctuated::new();
David Tolnaye2a6ffa2019-01-15 20:57:02 -08001780 input.parse::<Option<Token![|]>>()?;
David Tolnay310b3262018-08-30 15:33:00 -07001781 let value: Pat = input.parse()?;
1782 pats.push_value(value);
David Tolnay73b7ca12018-08-30 21:05:13 -07001783 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
David Tolnay310b3262018-08-30 15:33:00 -07001784 let punct = input.parse()?;
1785 pats.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07001786 let value: Pat = input.parse()?;
1787 pats.push_value(value);
David Tolnay310b3262018-08-30 15:33:00 -07001788 }
1789 pats
1790 },
1791 eq_token: input.parse()?,
1792 expr: Box::new(input.call(expr_no_struct)?),
David Tolnay310b3262018-08-30 15:33:00 -07001793 })
David Tolnay29f9ce12016-10-02 20:58:40 -07001794 }
1795
Michael Layzell734adb42017-06-07 16:58:31 -04001796 #[cfg(feature = "full")]
Peter Hall04f42792019-04-02 16:58:45 +02001797 impl Parse for ExprIf {
1798 fn parse(input: ParseStream) -> Result<Self> {
1799 Ok(ExprIf {
1800 attrs: Vec::new(),
1801 if_token: input.parse()?,
1802 cond: Box::new(input.call(expr_no_struct)?),
1803 then_branch: input.parse()?,
1804 else_branch: {
1805 if input.peek(Token![else]) {
1806 Some(input.call(else_block)?)
1807 } else {
1808 None
1809 }
1810 },
1811 })
1812 }
Alex Crichton954046c2017-05-30 21:49:42 -07001813 }
David Tolnaybb6feae2016-10-02 21:25:20 -07001814
Michael Layzell734adb42017-06-07 16:58:31 -04001815 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001816 fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
1817 let else_token: Token![else] = input.parse()?;
1818
1819 let lookahead = input.lookahead1();
1820 let else_branch = if input.peek(Token![if]) {
Peter Hall04f42792019-04-02 16:58:45 +02001821 input.parse().map(Expr::If)?
David Tolnay60291082018-08-28 09:54:49 -07001822 } else if input.peek(token::Brace) {
1823 Expr::Block(ExprBlock {
1824 attrs: Vec::new(),
1825 label: None,
1826 block: input.parse()?,
1827 })
1828 } else {
1829 return Err(lookahead.error());
1830 };
1831
1832 Ok((else_token, Box::new(else_branch)))
1833 }
David Tolnay939766a2016-09-23 23:48:12 -07001834
Michael Layzell734adb42017-06-07 16:58:31 -04001835 #[cfg(feature = "full")]
Peter Hall04f42792019-04-02 16:58:45 +02001836 impl Parse for ExprForLoop {
1837 fn parse(input: ParseStream) -> Result<Self> {
1838 let label: Option<Label> = input.parse()?;
1839 let for_token: Token![for] = input.parse()?;
1840 let pat: Pat = input.parse()?;
1841 let in_token: Token![in] = input.parse()?;
1842 let expr: Expr = input.call(expr_no_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07001843
Peter Hall04f42792019-04-02 16:58:45 +02001844 let content;
1845 let brace_token = braced!(content in input);
1846 let inner_attrs = content.call(Attribute::parse_inner)?;
1847 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07001848
Peter Hall04f42792019-04-02 16:58:45 +02001849 Ok(ExprForLoop {
1850 attrs: inner_attrs,
1851 label: label,
1852 for_token: for_token,
1853 pat: Box::new(pat),
1854 in_token: in_token,
1855 expr: Box::new(expr),
1856 body: Block {
1857 brace_token: brace_token,
1858 stmts: stmts,
1859 },
1860 })
1861 }
Alex Crichton954046c2017-05-30 21:49:42 -07001862 }
David Tolnay1978c672016-10-27 22:05:52 -07001863
Michael Layzell734adb42017-06-07 16:58:31 -04001864 #[cfg(feature = "full")]
Peter Hall04f42792019-04-02 16:58:45 +02001865 impl Parse for ExprLoop {
1866 fn parse(input: ParseStream) -> Result<Self> {
1867 let label: Option<Label> = input.parse()?;
1868 let loop_token: Token![loop] = input.parse()?;
David Tolnay310b3262018-08-30 15:33:00 -07001869
Peter Hall04f42792019-04-02 16:58:45 +02001870 let content;
1871 let brace_token = braced!(content in input);
1872 let inner_attrs = content.call(Attribute::parse_inner)?;
1873 let stmts = content.call(Block::parse_within)?;
David Tolnay310b3262018-08-30 15:33:00 -07001874
Peter Hall04f42792019-04-02 16:58:45 +02001875 Ok(ExprLoop {
1876 attrs: inner_attrs,
1877 label: label,
1878 loop_token: loop_token,
1879 body: Block {
1880 brace_token: brace_token,
1881 stmts: stmts,
1882 },
1883 })
1884 }
Alex Crichton954046c2017-05-30 21:49:42 -07001885 }
Arnavion02ef13f2017-04-25 00:54:31 -07001886
Michael Layzell734adb42017-06-07 16:58:31 -04001887 #[cfg(feature = "full")]
Peter Hall55f00f72019-04-02 16:50:57 +02001888 impl Parse for ExprMatch {
1889 fn parse(input: ParseStream) -> Result<Self> {
1890 let match_token: Token![match] = input.parse()?;
1891 let expr = expr_no_struct(input)?;
David Tolnay310b3262018-08-30 15:33:00 -07001892
Peter Hall55f00f72019-04-02 16:50:57 +02001893 let content;
1894 let brace_token = braced!(content in input);
1895 let inner_attrs = content.call(Attribute::parse_inner)?;
David Tolnay310b3262018-08-30 15:33:00 -07001896
Peter Hall55f00f72019-04-02 16:50:57 +02001897 let mut arms = Vec::new();
1898 while !content.is_empty() {
1899 arms.push(content.call(Arm::parse)?);
1900 }
1901
1902 Ok(ExprMatch {
1903 attrs: inner_attrs,
1904 match_token: match_token,
1905 expr: Box::new(expr),
1906 brace_token: brace_token,
1907 arms: arms,
1908 })
David Tolnay310b3262018-08-30 15:33:00 -07001909 }
David Tolnay310b3262018-08-30 15:33:00 -07001910 }
1911
bstriecde20e62019-05-05 13:29:15 -04001912 macro_rules! impl_by_parsing_expr {
bstrieb7f8aaf2019-04-30 20:20:25 -04001913 ($expr_type:ty, $variant:ident, $msg:expr) => (
bstrie6c50fdb2019-05-01 16:29:13 -04001914 #[cfg(all(feature = "full", feature = "printing"))]
bstrieb7f8aaf2019-04-30 20:20:25 -04001915 impl Parse for $expr_type {
1916 fn parse(input: ParseStream) -> Result<Self> {
bstrie1626c372019-05-05 13:44:57 -04001917 let mut expr: Expr = input.parse()?;
1918 loop {
1919 match expr {
1920 Expr::$variant(inner) => return Ok(inner),
1921 Expr::Group(ExprGroup { expr: next, .. }) => expr = *next,
1922 _ => return Err(Error::new_spanned(expr, $msg))
1923 }
bstrieb7f8aaf2019-04-30 20:20:25 -04001924 }
1925 }
bstrie7b4f52d2019-04-30 18:44:21 -04001926 }
bstrieb7f8aaf2019-04-30 20:20:25 -04001927 )
bstrie7b4f52d2019-04-30 18:44:21 -04001928 }
1929
bstriecde20e62019-05-05 13:29:15 -04001930 impl_by_parsing_expr!(ExprBox, Box, "expected box expression");
1931 impl_by_parsing_expr!(ExprInPlace, InPlace, "expected placement expression");
1932 impl_by_parsing_expr!(ExprArray, Array, "expected slice literal expression");
1933 impl_by_parsing_expr!(ExprCall, Call, "expected function call expression");
1934 impl_by_parsing_expr!(ExprMethodCall, MethodCall, "expected method call expression");
1935 impl_by_parsing_expr!(ExprTuple, Tuple, "expected tuple expression");
1936 impl_by_parsing_expr!(ExprBinary, Binary, "expected binary operation");
1937 impl_by_parsing_expr!(ExprUnary, Unary, "expected unary operation");
1938 impl_by_parsing_expr!(ExprCast, Cast, "expected cast expression");
1939 impl_by_parsing_expr!(ExprType, Type, "expected type ascription expression");
1940 impl_by_parsing_expr!(ExprLet, Let, "expected let guard");
1941 impl_by_parsing_expr!(ExprClosure, Closure, "expected closure expression");
1942 impl_by_parsing_expr!(ExprUnsafe, Unsafe, "expected unsafe block");
1943 impl_by_parsing_expr!(ExprBlock, Block, "expected blocked scope");
1944 impl_by_parsing_expr!(ExprAssign, Assign, "expected assignment expression");
1945 impl_by_parsing_expr!(ExprAssignOp, AssignOp, "expected compound assignment expression");
1946 impl_by_parsing_expr!(ExprField, Field, "expected struct field access");
1947 impl_by_parsing_expr!(ExprIndex, Index, "expected indexing expression");
1948 impl_by_parsing_expr!(ExprRange, Range, "expected range expression");
1949 impl_by_parsing_expr!(ExprReference, Reference, "expected referencing operation");
1950 impl_by_parsing_expr!(ExprBreak, Break, "expected break expression");
1951 impl_by_parsing_expr!(ExprContinue, Continue, "expected continue expression");
1952 impl_by_parsing_expr!(ExprReturn, Return, "expected return expression");
1953 impl_by_parsing_expr!(ExprMacro, Macro, "expected macro invocation expression");
1954 impl_by_parsing_expr!(ExprStruct, Struct, "expected struct literal expression");
1955 impl_by_parsing_expr!(ExprRepeat, Repeat, "expected array literal constructed from one repeated element");
1956 impl_by_parsing_expr!(ExprParen, Paren, "expected parenthesized expression");
1957 impl_by_parsing_expr!(ExprTry, Try, "expected try expression");
1958 impl_by_parsing_expr!(ExprAsync, Async, "expected async block");
1959 impl_by_parsing_expr!(ExprTryBlock, TryBlock, "expected try block");
1960 impl_by_parsing_expr!(ExprYield, Yield, "expected yield expression");
bstrieb7f8aaf2019-04-30 20:20:25 -04001961
bstrie7b4f52d2019-04-30 18:44:21 -04001962 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001963 fn expr_try_block(input: ParseStream) -> Result<ExprTryBlock> {
1964 Ok(ExprTryBlock {
1965 attrs: Vec::new(),
1966 try_token: input.parse()?,
1967 block: input.parse()?,
1968 })
1969 }
1970
1971 #[cfg(feature = "full")]
1972 fn expr_yield(input: ParseStream) -> Result<ExprYield> {
1973 Ok(ExprYield {
1974 attrs: Vec::new(),
1975 yield_token: input.parse()?,
1976 expr: {
1977 if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
1978 Some(input.parse()?)
1979 } else {
1980 None
1981 }
1982 },
1983 })
1984 }
1985
1986 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001987 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
David Tolnay60291082018-08-28 09:54:49 -07001988 let asyncness: Option<Token![async]> = input.parse()?;
1989 let movability: Option<Token![static]> = if asyncness.is_none() {
1990 input.parse()?
1991 } else {
1992 None
1993 };
1994 let capture: Option<Token![move]> = input.parse()?;
1995 let or1_token: Token![|] = input.parse()?;
1996
1997 let mut inputs = Punctuated::new();
1998 loop {
1999 if input.peek(Token![|]) {
2000 break;
2001 }
2002 let value = fn_arg(input)?;
2003 inputs.push_value(value);
2004 if input.peek(Token![|]) {
2005 break;
2006 }
2007 let punct: Token![,] = input.parse()?;
2008 inputs.push_punct(punct);
2009 }
2010
2011 let or2_token: Token![|] = input.parse()?;
2012
2013 let (output, body) = if input.peek(Token![->]) {
2014 let arrow_token: Token![->] = input.parse()?;
2015 let ty: Type = input.parse()?;
2016 let body: Block = input.parse()?;
2017 let output = ReturnType::Type(arrow_token, Box::new(ty));
2018 let block = Expr::Block(ExprBlock {
2019 attrs: Vec::new(),
2020 label: None,
2021 block: body,
2022 });
2023 (output, block)
2024 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002025 let body = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002026 (ReturnType::Default, body)
2027 };
2028
2029 Ok(ExprClosure {
David Tolnay310b3262018-08-30 15:33:00 -07002030 attrs: Vec::new(),
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002031 asyncness: asyncness,
2032 movability: movability,
2033 capture: capture,
David Tolnay60291082018-08-28 09:54:49 -07002034 or1_token: or1_token,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002035 inputs: inputs,
David Tolnay60291082018-08-28 09:54:49 -07002036 or2_token: or2_token,
2037 output: output,
2038 body: Box::new(body),
2039 })
David Tolnay02a9c6f2018-08-24 18:58:45 -04002040 }
Yusuke Sasaki851062f2018-08-01 06:28:28 +09002041
2042 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002043 fn expr_async(input: ParseStream) -> Result<ExprAsync> {
2044 Ok(ExprAsync {
2045 attrs: Vec::new(),
2046 async_token: input.parse()?,
2047 capture: input.parse()?,
2048 block: input.parse()?,
2049 })
David Tolnay60291082018-08-28 09:54:49 -07002050 }
Gregory Katz3e562cc2016-09-28 18:33:02 -04002051
Michael Layzell734adb42017-06-07 16:58:31 -04002052 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002053 fn fn_arg(input: ParseStream) -> Result<FnArg> {
2054 let pat: Pat = input.parse()?;
2055
2056 if input.peek(Token![:]) {
2057 Ok(FnArg::Captured(ArgCaptured {
2058 pat: pat,
2059 colon_token: input.parse()?,
2060 ty: input.parse()?,
2061 }))
2062 } else {
2063 Ok(FnArg::Inferred(pat))
2064 }
2065 }
2066
2067 #[cfg(feature = "full")]
Peter Hall04f42792019-04-02 16:58:45 +02002068 impl Parse for ExprWhile {
2069 fn parse(input: ParseStream) -> Result<Self> {
2070 let label: Option<Label> = input.parse()?;
2071 let while_token: Token![while] = input.parse()?;
2072 let cond = expr_no_struct(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002073
Peter Hall04f42792019-04-02 16:58:45 +02002074 let content;
2075 let brace_token = braced!(content in input);
2076 let inner_attrs = content.call(Attribute::parse_inner)?;
2077 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002078
Peter Hall04f42792019-04-02 16:58:45 +02002079 Ok(ExprWhile {
2080 attrs: inner_attrs,
2081 label: label,
2082 while_token: while_token,
2083 cond: Box::new(cond),
2084 body: Block {
2085 brace_token: brace_token,
2086 stmts: stmts,
2087 },
2088 })
2089 }
Alex Crichton954046c2017-05-30 21:49:42 -07002090 }
2091
Michael Layzell734adb42017-06-07 16:58:31 -04002092 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002093 impl Parse for Label {
2094 fn parse(input: ParseStream) -> Result<Self> {
2095 Ok(Label {
2096 name: input.parse()?,
2097 colon_token: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04002098 })
David Tolnay60291082018-08-28 09:54:49 -07002099 }
Alex Crichton954046c2017-05-30 21:49:42 -07002100 }
2101
Michael Layzell734adb42017-06-07 16:58:31 -04002102 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002103 impl Parse for Option<Label> {
2104 fn parse(input: ParseStream) -> Result<Self> {
2105 if input.peek(Lifetime) {
2106 input.parse().map(Some)
2107 } else {
2108 Ok(None)
2109 }
2110 }
2111 }
2112
2113 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002114 fn expr_continue(input: ParseStream) -> Result<ExprContinue> {
2115 Ok(ExprContinue {
2116 attrs: Vec::new(),
2117 continue_token: input.parse()?,
2118 label: input.parse()?,
2119 })
Alex Crichton954046c2017-05-30 21:49:42 -07002120 }
Gregory Katzfd6935d2016-09-30 22:51:25 -04002121
Michael Layzell734adb42017-06-07 16:58:31 -04002122 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002123 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2124 Ok(ExprBreak {
David Tolnay310b3262018-08-30 15:33:00 -07002125 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002126 break_token: input.parse()?,
2127 label: input.parse()?,
2128 expr: {
2129 if input.is_empty()
2130 || input.peek(Token![,])
2131 || input.peek(Token![;])
2132 || !allow_struct.0 && input.peek(token::Brace)
2133 {
2134 None
2135 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002136 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002137 Some(Box::new(expr))
Michael Layzell92639a52017-06-01 00:07:44 -04002138 }
David Tolnay60291082018-08-28 09:54:49 -07002139 },
2140 })
Alex Crichton954046c2017-05-30 21:49:42 -07002141 }
2142
Michael Layzell734adb42017-06-07 16:58:31 -04002143 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002144 fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
2145 Ok(ExprReturn {
David Tolnay310b3262018-08-30 15:33:00 -07002146 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002147 return_token: input.parse()?,
2148 expr: {
2149 if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
2150 None
2151 } else {
2152 // NOTE: return is greedy and eats blocks after it even when in a
2153 // position where structs are not allowed, such as in if statement
2154 // conditions. For example:
2155 //
2156 // if return { println!("A") } {} // Prints "A"
David Tolnay7d2e1db2018-08-30 11:49:04 -07002157 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002158 Some(Box::new(expr))
2159 }
2160 },
2161 })
2162 }
2163
2164 #[cfg(feature = "full")]
David Tolnaya7aa4ee2018-09-02 12:15:00 -07002165 impl Parse for FieldValue {
2166 fn parse(input: ParseStream) -> Result<Self> {
2167 let member: Member = input.parse()?;
2168 let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
2169 let colon_token: Token![:] = input.parse()?;
2170 let value: Expr = input.parse()?;
2171 (Some(colon_token), value)
2172 } else if let Member::Named(ref ident) = member {
2173 let value = Expr::Path(ExprPath {
2174 attrs: Vec::new(),
2175 qself: None,
2176 path: Path::from(ident.clone()),
2177 });
2178 (None, value)
2179 } else {
2180 unreachable!()
2181 };
2182
2183 Ok(FieldValue {
2184 attrs: Vec::new(),
2185 member: member,
2186 colon_token: colon_token,
2187 expr: value,
2188 })
2189 }
2190 }
2191
2192 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07002193 fn expr_struct_helper(
2194 input: ParseStream,
2195 outer_attrs: Vec<Attribute>,
2196 path: Path,
2197 ) -> Result<ExprStruct> {
David Tolnay6e1e5052018-08-30 10:21:48 -07002198 let content;
2199 let brace_token = braced!(content in input);
2200 let inner_attrs = content.call(Attribute::parse_inner)?;
David Tolnay60291082018-08-28 09:54:49 -07002201
David Tolnay6e1e5052018-08-30 10:21:48 -07002202 let mut fields = Punctuated::new();
2203 loop {
2204 let attrs = content.call(Attribute::parse_outer)?;
2205 if content.fork().parse::<Member>().is_err() {
2206 if attrs.is_empty() {
David Tolnay60291082018-08-28 09:54:49 -07002207 break;
David Tolnay6e1e5052018-08-30 10:21:48 -07002208 } else {
2209 return Err(content.error("expected struct field"));
David Tolnay60291082018-08-28 09:54:49 -07002210 }
David Tolnay60291082018-08-28 09:54:49 -07002211 }
2212
David Tolnay6e1e5052018-08-30 10:21:48 -07002213 fields.push(FieldValue {
2214 attrs: attrs,
David Tolnaya7aa4ee2018-09-02 12:15:00 -07002215 ..content.parse()?
David Tolnay6e1e5052018-08-30 10:21:48 -07002216 });
2217
2218 if !content.peek(Token![,]) {
2219 break;
2220 }
2221 let punct: Token![,] = content.parse()?;
2222 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002223 }
David Tolnay6e1e5052018-08-30 10:21:48 -07002224
2225 let (dot2_token, rest) = if fields.empty_or_trailing() && content.peek(Token![..]) {
2226 let dot2_token: Token![..] = content.parse()?;
2227 let rest: Expr = content.parse()?;
2228 (Some(dot2_token), Some(Box::new(rest)))
2229 } else {
2230 (None, None)
2231 };
2232
2233 Ok(ExprStruct {
David Tolnayb5f6fc02018-09-01 02:18:50 -07002234 attrs: private::attrs(outer_attrs, inner_attrs),
David Tolnay6e1e5052018-08-30 10:21:48 -07002235 brace_token: brace_token,
2236 path: path,
2237 fields: fields,
2238 dot2_token: dot2_token,
2239 rest: rest,
2240 })
Alex Crichton954046c2017-05-30 21:49:42 -07002241 }
David Tolnay055a7042016-10-02 19:23:54 -07002242
Michael Layzell734adb42017-06-07 16:58:31 -04002243 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002244 fn expr_unsafe(input: ParseStream) -> Result<ExprUnsafe> {
2245 let unsafe_token: Token![unsafe] = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002246
David Tolnay310b3262018-08-30 15:33:00 -07002247 let content;
2248 let brace_token = braced!(content in input);
2249 let inner_attrs = content.call(Attribute::parse_inner)?;
2250 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002251
David Tolnay310b3262018-08-30 15:33:00 -07002252 Ok(ExprUnsafe {
2253 attrs: inner_attrs,
2254 unsafe_token: unsafe_token,
2255 block: Block {
2256 brace_token: brace_token,
2257 stmts: stmts,
2258 },
2259 })
Alex Crichton954046c2017-05-30 21:49:42 -07002260 }
David Tolnay055a7042016-10-02 19:23:54 -07002261
Michael Layzell734adb42017-06-07 16:58:31 -04002262 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002263 pub fn expr_block(input: ParseStream) -> Result<ExprBlock> {
2264 let label: Option<Label> = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002265
David Tolnay310b3262018-08-30 15:33:00 -07002266 let content;
2267 let brace_token = braced!(content in input);
2268 let inner_attrs = content.call(Attribute::parse_inner)?;
2269 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002270
David Tolnay310b3262018-08-30 15:33:00 -07002271 Ok(ExprBlock {
2272 attrs: inner_attrs,
2273 label: label,
2274 block: Block {
2275 brace_token: brace_token,
2276 stmts: stmts,
2277 },
2278 })
Alex Crichton954046c2017-05-30 21:49:42 -07002279 }
David Tolnay89e05672016-10-02 14:39:42 -07002280
Michael Layzell734adb42017-06-07 16:58:31 -04002281 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002282 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2283 Ok(ExprRange {
David Tolnay8c91b882017-12-28 23:04:32 -05002284 attrs: Vec::new(),
2285 from: None,
David Tolnay60291082018-08-28 09:54:49 -07002286 limits: input.parse()?,
2287 to: {
2288 if input.is_empty()
2289 || input.peek(Token![,])
2290 || input.peek(Token![;])
2291 || !allow_struct.0 && input.peek(token::Brace)
2292 {
2293 None
2294 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002295 let to = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002296 Some(Box::new(to))
2297 }
2298 },
2299 })
2300 }
David Tolnay438c9052016-10-07 23:24:48 -07002301
Michael Layzell734adb42017-06-07 16:58:31 -04002302 #[cfg(feature = "full")]
David Tolnayc4c631e2018-08-27 10:44:37 -07002303 impl Parse for RangeLimits {
2304 fn parse(input: ParseStream) -> Result<Self> {
2305 let lookahead = input.lookahead1();
2306 if lookahead.peek(Token![..=]) {
2307 input.parse().map(RangeLimits::Closed)
2308 } else if lookahead.peek(Token![...]) {
2309 let dot3: Token![...] = input.parse()?;
2310 Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2311 } else if lookahead.peek(Token![..]) {
2312 input.parse().map(RangeLimits::HalfOpen)
2313 } else {
2314 Err(lookahead.error())
2315 }
2316 }
Alex Crichton954046c2017-05-30 21:49:42 -07002317 }
David Tolnay438c9052016-10-07 23:24:48 -07002318
David Tolnay60291082018-08-28 09:54:49 -07002319 impl Parse for ExprPath {
2320 fn parse(input: ParseStream) -> Result<Self> {
2321 #[cfg(not(feature = "full"))]
2322 let attrs = Vec::new();
2323 #[cfg(feature = "full")]
2324 let attrs = input.call(Attribute::parse_outer)?;
David Tolnayeb981bb2018-07-21 19:31:38 -07002325
David Tolnay60291082018-08-28 09:54:49 -07002326 let (qself, path) = path::parsing::qpath(input, true)?;
2327
2328 Ok(ExprPath {
David Tolnay73c9b522018-07-21 15:58:40 -07002329 attrs: attrs,
David Tolnay60291082018-08-28 09:54:49 -07002330 qself: qself,
2331 path: path,
Michael Layzell92639a52017-06-01 00:07:44 -04002332 })
David Tolnay60291082018-08-28 09:54:49 -07002333 }
Alex Crichton954046c2017-05-30 21:49:42 -07002334 }
David Tolnay42602292016-10-01 22:25:45 -07002335
Michael Layzell734adb42017-06-07 16:58:31 -04002336 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002337 impl Parse for Block {
2338 fn parse(input: ParseStream) -> Result<Self> {
2339 let content;
2340 Ok(Block {
2341 brace_token: braced!(content in input),
2342 stmts: content.call(Block::parse_within)?,
Michael Layzell92639a52017-06-01 00:07:44 -04002343 })
David Tolnay60291082018-08-28 09:54:49 -07002344 }
Alex Crichton954046c2017-05-30 21:49:42 -07002345 }
David Tolnay939766a2016-09-23 23:48:12 -07002346
Michael Layzell734adb42017-06-07 16:58:31 -04002347 #[cfg(feature = "full")]
Alex Crichton954046c2017-05-30 21:49:42 -07002348 impl Block {
David Tolnay6b457252018-09-01 15:55:47 -07002349 /// Parse the body of a block as zero or more statements, possibly
2350 /// including one trailing expression.
2351 ///
David Tolnay206edfb2018-09-01 16:02:20 -07002352 /// *This function is available if Syn is built with the `"parsing"`
2353 /// feature.*
2354 ///
David Tolnay6b457252018-09-01 15:55:47 -07002355 /// # Example
2356 ///
David Tolnay95989db2019-01-01 15:05:57 -05002357 /// ```edition2018
David Tolnayfd5b1172018-12-31 17:54:36 -05002358 /// use syn::{braced, token, Attribute, Block, Ident, Result, Stmt, Token};
David Tolnay67fea042018-11-24 14:50:20 -08002359 /// use syn::parse::{Parse, ParseStream};
David Tolnay6b457252018-09-01 15:55:47 -07002360 ///
2361 /// // Parse a function with no generics or parameter list.
David Tolnaye7ea1652018-09-02 09:11:54 -07002362 /// //
2363 /// // fn playground {
2364 /// // let mut x = 1;
2365 /// // x += 1;
2366 /// // println!("{}", x);
2367 /// // }
David Tolnay6b457252018-09-01 15:55:47 -07002368 /// struct MiniFunction {
2369 /// attrs: Vec<Attribute>,
2370 /// fn_token: Token![fn],
2371 /// name: Ident,
2372 /// brace_token: token::Brace,
2373 /// stmts: Vec<Stmt>,
2374 /// }
2375 ///
2376 /// impl Parse for MiniFunction {
2377 /// fn parse(input: ParseStream) -> Result<Self> {
2378 /// let outer_attrs = input.call(Attribute::parse_outer)?;
2379 /// let fn_token: Token![fn] = input.parse()?;
2380 /// let name: Ident = input.parse()?;
2381 ///
2382 /// let content;
2383 /// let brace_token = braced!(content in input);
2384 /// let inner_attrs = content.call(Attribute::parse_inner)?;
2385 /// let stmts = content.call(Block::parse_within)?;
2386 ///
2387 /// Ok(MiniFunction {
2388 /// attrs: {
2389 /// let mut attrs = outer_attrs;
2390 /// attrs.extend(inner_attrs);
2391 /// attrs
2392 /// },
2393 /// fn_token: fn_token,
2394 /// name: name,
2395 /// brace_token: brace_token,
2396 /// stmts: stmts,
2397 /// })
2398 /// }
2399 /// }
David Tolnay6b457252018-09-01 15:55:47 -07002400 /// ```
David Tolnay9389c382018-08-27 09:13:37 -07002401 pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002402 let mut stmts = Vec::new();
David Tolnay7158c5f2018-08-30 17:28:34 -07002403 loop {
2404 while input.peek(Token![;]) {
2405 input.parse::<Token![;]>()?;
Michael Layzell92639a52017-06-01 00:07:44 -04002406 }
David Tolnay7158c5f2018-08-30 17:28:34 -07002407 if input.is_empty() {
2408 break;
2409 }
2410 let s = parse_stmt(input, true)?;
2411 let requires_semicolon = if let Stmt::Expr(ref s) = s {
2412 requires_terminator(s)
2413 } else {
2414 false
2415 };
David Tolnaye532d6b2018-08-30 16:55:01 -07002416 stmts.push(s);
David Tolnay7158c5f2018-08-30 17:28:34 -07002417 if input.is_empty() {
2418 break;
2419 } else if requires_semicolon {
2420 return Err(input.error("unexpected token"));
2421 }
David Tolnaye532d6b2018-08-30 16:55:01 -07002422 }
2423 Ok(stmts)
2424 }
Alex Crichton954046c2017-05-30 21:49:42 -07002425 }
2426
Michael Layzell734adb42017-06-07 16:58:31 -04002427 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002428 impl Parse for Stmt {
2429 fn parse(input: ParseStream) -> Result<Self> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002430 parse_stmt(input, false)
2431 }
2432 }
David Tolnay939766a2016-09-23 23:48:12 -07002433
David Tolnaye532d6b2018-08-30 16:55:01 -07002434 #[cfg(feature = "full")]
2435 fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
2436 let ahead = input.fork();
2437 ahead.call(Attribute::parse_outer)?;
2438
David Tolnaye532d6b2018-08-30 16:55:01 -07002439 if {
2440 let ahead = ahead.fork();
2441 // Only parse braces here; paren and bracket will get parsed as
2442 // expression statements
2443 ahead.call(Path::parse_mod_style).is_ok()
2444 && ahead.parse::<Token![!]>().is_ok()
2445 && (ahead.peek(token::Brace) || ahead.peek(Ident))
2446 } {
2447 stmt_mac(input)
2448 } else if ahead.peek(Token![let]) {
2449 stmt_local(input).map(Stmt::Local)
2450 } else if ahead.peek(Token![pub])
2451 || ahead.peek(Token![crate]) && !ahead.peek2(Token![::])
2452 || ahead.peek(Token![extern]) && !ahead.peek2(Token![::])
2453 || ahead.peek(Token![use])
2454 || ahead.peek(Token![static]) && (ahead.peek2(Token![mut]) || ahead.peek2(Ident))
2455 || ahead.peek(Token![const])
2456 || ahead.peek(Token![unsafe]) && !ahead.peek2(token::Brace)
2457 || ahead.peek(Token![async]) && (ahead.peek2(Token![extern]) || ahead.peek2(Token![fn]))
2458 || ahead.peek(Token![fn])
2459 || ahead.peek(Token![mod])
2460 || ahead.peek(Token![type])
2461 || ahead.peek(Token![existential]) && ahead.peek2(Token![type])
2462 || ahead.peek(Token![struct])
2463 || ahead.peek(Token![enum])
2464 || ahead.peek(Token![union]) && ahead.peek2(Ident)
2465 || ahead.peek(Token![auto]) && ahead.peek2(Token![trait])
2466 || ahead.peek(Token![trait])
David Tolnay73b7ca12018-08-30 21:05:13 -07002467 || ahead.peek(Token![default])
David Tolnay2beee042019-04-03 08:36:59 -07002468 && (ahead.peek2(Token![unsafe]) || ahead.peek2(Token![impl]))
2469 || ahead.peek(Token![impl])
David Tolnaye532d6b2018-08-30 16:55:01 -07002470 || ahead.peek(Token![macro])
2471 {
2472 input.parse().map(Stmt::Item)
2473 } else {
2474 stmt_expr(input, allow_nosemi)
David Tolnay60291082018-08-28 09:54:49 -07002475 }
Alex Crichton954046c2017-05-30 21:49:42 -07002476 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07002477
Michael Layzell734adb42017-06-07 16:58:31 -04002478 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002479 fn stmt_mac(input: ParseStream) -> Result<Stmt> {
2480 let attrs = input.call(Attribute::parse_outer)?;
2481 let path = input.call(Path::parse_mod_style)?;
2482 let bang_token: Token![!] = input.parse()?;
2483 let ident: Option<Ident> = input.parse()?;
2484 let (delimiter, tts) = mac::parse_delimiter(input)?;
2485 let semi_token: Option<Token![;]> = input.parse()?;
2486
2487 Ok(Stmt::Item(Item::Macro(ItemMacro {
2488 attrs: attrs,
2489 ident: ident,
2490 mac: Macro {
2491 path: path,
2492 bang_token: bang_token,
2493 delimiter: delimiter,
2494 tts: tts,
2495 },
2496 semi_token: semi_token,
2497 })))
Alex Crichton954046c2017-05-30 21:49:42 -07002498 }
David Tolnay84aa0752016-10-02 23:01:13 -07002499
Michael Layzell734adb42017-06-07 16:58:31 -04002500 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002501 fn stmt_local(input: ParseStream) -> Result<Local> {
2502 Ok(Local {
2503 attrs: input.call(Attribute::parse_outer)?,
2504 let_token: input.parse()?,
2505 pats: {
2506 let mut pats = Punctuated::new();
2507 let value: Pat = input.parse()?;
2508 pats.push_value(value);
2509 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2510 let punct = input.parse()?;
2511 pats.push_punct(punct);
2512 let value: Pat = input.parse()?;
2513 pats.push_value(value);
2514 }
2515 pats
2516 },
2517 ty: {
2518 if input.peek(Token![:]) {
2519 let colon_token: Token![:] = input.parse()?;
2520 let ty: Type = input.parse()?;
2521 Some((colon_token, Box::new(ty)))
2522 } else {
2523 None
2524 }
2525 },
2526 init: {
2527 if input.peek(Token![=]) {
2528 let eq_token: Token![=] = input.parse()?;
2529 let init: Expr = input.parse()?;
2530 Some((eq_token, Box::new(init)))
2531 } else {
2532 None
2533 }
2534 },
2535 semi_token: input.parse()?,
2536 })
2537 }
2538
2539 #[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -07002540 fn stmt_expr(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
David Tolnay60291082018-08-28 09:54:49 -07002541 let mut attrs = input.call(Attribute::parse_outer)?;
David Tolnay01218d12018-08-29 18:13:07 -07002542 let mut e = expr_early(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002543
2544 attrs.extend(e.replace_attrs(Vec::new()));
2545 e.replace_attrs(attrs);
2546
2547 if input.peek(Token![;]) {
David Tolnay01218d12018-08-29 18:13:07 -07002548 return Ok(Stmt::Semi(e, input.parse()?));
David Tolnay60291082018-08-28 09:54:49 -07002549 }
David Tolnay60291082018-08-28 09:54:49 -07002550
David Tolnayf00a2762018-08-30 17:22:22 -07002551 if allow_nosemi || !requires_terminator(&e) {
David Tolnaye532d6b2018-08-30 16:55:01 -07002552 Ok(Stmt::Expr(e))
2553 } else {
2554 Err(input.error("expected semicolon"))
David Tolnay01218d12018-08-29 18:13:07 -07002555 }
David Tolnay60291082018-08-28 09:54:49 -07002556 }
2557
2558 #[cfg(feature = "full")]
2559 impl Parse for Pat {
2560 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay60291082018-08-28 09:54:49 -07002561 let lookahead = input.lookahead1();
2562 if lookahead.peek(Token![_]) {
David Tolnay310b3262018-08-30 15:33:00 -07002563 input.call(pat_wild).map(Pat::Wild)
David Tolnay60291082018-08-28 09:54:49 -07002564 } else if lookahead.peek(Token![box]) {
David Tolnay310b3262018-08-30 15:33:00 -07002565 input.call(pat_box).map(Pat::Box)
David Tolnay8d534b02018-09-02 09:46:05 -07002566 } else if lookahead.peek(Token![-]) || lookahead.peek(Lit) {
2567 pat_lit_or_range(input)
2568 } else if input.peek(Ident)
2569 && ({
2570 input.peek2(Token![::])
2571 || input.peek2(Token![!])
2572 || input.peek2(token::Brace)
2573 || input.peek2(token::Paren)
David Tolnaye614f282018-10-27 22:50:12 -07002574 || input.peek2(Token![..])
2575 && !{
2576 let ahead = input.fork();
2577 ahead.parse::<Ident>()?;
2578 ahead.parse::<RangeLimits>()?;
2579 ahead.is_empty() || ahead.peek(Token![,])
2580 }
David Tolnay8d534b02018-09-02 09:46:05 -07002581 })
Michael Bradshaw7531e152018-10-19 22:26:56 -07002582 || input.peek(Token![self]) && input.peek2(Token![::])
David Tolnay8d534b02018-09-02 09:46:05 -07002583 || input.peek(Token![::])
2584 || input.peek(Token![<])
David Tolnay8d534b02018-09-02 09:46:05 -07002585 || input.peek(Token![Self])
2586 || input.peek(Token![super])
2587 || input.peek(Token![extern])
2588 || input.peek(Token![crate])
2589 {
2590 pat_path_or_macro_or_struct_or_range(input)
Michael Bradshaw7531e152018-10-19 22:26:56 -07002591 } else if input.peek(Token![ref])
2592 || input.peek(Token![mut])
2593 || input.peek(Token![self])
2594 || input.peek(Ident)
2595 {
David Tolnay310b3262018-08-30 15:33:00 -07002596 input.call(pat_ident).map(Pat::Ident)
David Tolnay60291082018-08-28 09:54:49 -07002597 } else if lookahead.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07002598 input.call(pat_tuple).map(Pat::Tuple)
David Tolnay60291082018-08-28 09:54:49 -07002599 } else if lookahead.peek(Token![&]) {
David Tolnay310b3262018-08-30 15:33:00 -07002600 input.call(pat_ref).map(Pat::Ref)
David Tolnay60291082018-08-28 09:54:49 -07002601 } else if lookahead.peek(token::Bracket) {
David Tolnay310b3262018-08-30 15:33:00 -07002602 input.call(pat_slice).map(Pat::Slice)
David Tolnay60291082018-08-28 09:54:49 -07002603 } else {
2604 Err(lookahead.error())
2605 }
2606 }
2607 }
2608
2609 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002610 fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> {
2611 let (qself, path) = path::parsing::qpath(input, true)?;
2612
2613 if input.peek(Token![..]) {
2614 return pat_range(input, qself, path).map(Pat::Range);
2615 }
2616
2617 if qself.is_some() {
2618 return Ok(Pat::Path(PatPath {
2619 qself: qself,
2620 path: path,
2621 }));
2622 }
2623
2624 if input.peek(Token![!]) && !input.peek(Token![!=]) {
2625 let mut contains_arguments = false;
2626 for segment in &path.segments {
2627 match segment.arguments {
2628 PathArguments::None => {}
2629 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
2630 contains_arguments = true;
2631 }
2632 }
2633 }
2634
2635 if !contains_arguments {
2636 let bang_token: Token![!] = input.parse()?;
2637 let (delimiter, tts) = mac::parse_delimiter(input)?;
2638 return Ok(Pat::Macro(PatMacro {
2639 mac: Macro {
2640 path: path,
2641 bang_token: bang_token,
2642 delimiter: delimiter,
2643 tts: tts,
2644 },
2645 }));
2646 }
2647 }
2648
2649 if input.peek(token::Brace) {
2650 pat_struct(input, path).map(Pat::Struct)
2651 } else if input.peek(token::Paren) {
2652 pat_tuple_struct(input, path).map(Pat::TupleStruct)
2653 } else if input.peek(Token![..]) {
2654 pat_range(input, qself, path).map(Pat::Range)
2655 } else {
2656 Ok(Pat::Path(PatPath {
2657 qself: qself,
2658 path: path,
2659 }))
2660 }
2661 }
2662
2663 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002664 fn pat_wild(input: ParseStream) -> Result<PatWild> {
2665 Ok(PatWild {
2666 underscore_token: input.parse()?,
2667 })
Alex Crichton954046c2017-05-30 21:49:42 -07002668 }
2669
Michael Layzell734adb42017-06-07 16:58:31 -04002670 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002671 fn pat_box(input: ParseStream) -> Result<PatBox> {
2672 Ok(PatBox {
2673 box_token: input.parse()?,
2674 pat: input.parse()?,
2675 })
David Tolnay60291082018-08-28 09:54:49 -07002676 }
2677
2678 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002679 fn pat_ident(input: ParseStream) -> Result<PatIdent> {
2680 Ok(PatIdent {
2681 by_ref: input.parse()?,
2682 mutability: input.parse()?,
David Tolnay8d534b02018-09-02 09:46:05 -07002683 ident: input.call(Ident::parse_any)?,
David Tolnay310b3262018-08-30 15:33:00 -07002684 subpat: {
2685 if input.peek(Token![@]) {
2686 let at_token: Token![@] = input.parse()?;
2687 let subpat: Pat = input.parse()?;
2688 Some((at_token, Box::new(subpat)))
2689 } else {
2690 None
2691 }
2692 },
2693 })
David Tolnay60291082018-08-28 09:54:49 -07002694 }
2695
2696 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002697 fn pat_tuple_struct(input: ParseStream, path: Path) -> Result<PatTupleStruct> {
David Tolnay310b3262018-08-30 15:33:00 -07002698 Ok(PatTupleStruct {
David Tolnay8d534b02018-09-02 09:46:05 -07002699 path: path,
David Tolnay310b3262018-08-30 15:33:00 -07002700 pat: input.call(pat_tuple)?,
2701 })
2702 }
David Tolnay60291082018-08-28 09:54:49 -07002703
David Tolnay310b3262018-08-30 15:33:00 -07002704 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002705 fn pat_struct(input: ParseStream, path: Path) -> Result<PatStruct> {
David Tolnay310b3262018-08-30 15:33:00 -07002706 let content;
2707 let brace_token = braced!(content in input);
2708
2709 let mut fields = Punctuated::new();
2710 while !content.is_empty() && !content.peek(Token![..]) {
2711 let value = content.call(field_pat)?;
2712 fields.push_value(value);
2713 if !content.peek(Token![,]) {
2714 break;
David Tolnay60291082018-08-28 09:54:49 -07002715 }
David Tolnay310b3262018-08-30 15:33:00 -07002716 let punct: Token![,] = content.parse()?;
2717 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002718 }
David Tolnay310b3262018-08-30 15:33:00 -07002719
2720 let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) {
2721 Some(content.parse()?)
2722 } else {
2723 None
2724 };
2725
2726 Ok(PatStruct {
2727 path: path,
2728 brace_token: brace_token,
2729 fields: fields,
2730 dot2_token: dot2_token,
2731 })
2732 }
2733
2734 #[cfg(feature = "full")]
2735 fn field_pat(input: ParseStream) -> Result<FieldPat> {
2736 let boxed: Option<Token![box]> = input.parse()?;
2737 let by_ref: Option<Token![ref]> = input.parse()?;
2738 let mutability: Option<Token![mut]> = input.parse()?;
2739 let member: Member = input.parse()?;
2740
2741 if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
2742 || member.is_unnamed()
2743 {
2744 return Ok(FieldPat {
2745 attrs: Vec::new(),
2746 member: member,
2747 colon_token: input.parse()?,
2748 pat: input.parse()?,
2749 });
2750 }
2751
2752 let ident = match member {
2753 Member::Named(ident) => ident,
2754 Member::Unnamed(_) => unreachable!(),
2755 };
2756
2757 let mut pat = Pat::Ident(PatIdent {
2758 by_ref: by_ref,
2759 mutability: mutability,
2760 ident: ident.clone(),
2761 subpat: None,
2762 });
2763
2764 if let Some(boxed) = boxed {
2765 pat = Pat::Box(PatBox {
2766 pat: Box::new(pat),
2767 box_token: boxed,
2768 });
2769 }
2770
2771 Ok(FieldPat {
2772 member: Member::Named(ident),
2773 pat: Box::new(pat),
2774 attrs: Vec::new(),
2775 colon_token: None,
2776 })
Alex Crichton954046c2017-05-30 21:49:42 -07002777 }
2778
David Tolnay1501f7e2018-08-27 14:21:03 -07002779 impl Parse for Member {
2780 fn parse(input: ParseStream) -> Result<Self> {
2781 if input.peek(Ident) {
2782 input.parse().map(Member::Named)
2783 } else if input.peek(LitInt) {
2784 input.parse().map(Member::Unnamed)
2785 } else {
2786 Err(input.error("expected identifier or integer"))
2787 }
2788 }
David Tolnay85b69a42017-12-27 20:43:10 -05002789 }
2790
Bastien Oriveld29ea392018-10-16 23:50:16 +02002791 #[cfg(feature = "full")]
2792 impl Parse for Arm {
2793 fn parse(input: ParseStream) -> Result<Arm> {
2794 let requires_comma;
2795 Ok(Arm {
2796 attrs: input.call(Attribute::parse_outer)?,
2797 leading_vert: input.parse()?,
2798 pats: {
2799 let mut pats = Punctuated::new();
2800 let value: Pat = input.parse()?;
2801 pats.push_value(value);
2802 loop {
2803 if !input.peek(Token![|]) {
2804 break;
2805 }
2806 let punct = input.parse()?;
2807 pats.push_punct(punct);
2808 let value: Pat = input.parse()?;
2809 pats.push_value(value);
2810 }
2811 pats
2812 },
2813 guard: {
2814 if input.peek(Token![if]) {
2815 let if_token: Token![if] = input.parse()?;
2816 let guard: Expr = input.parse()?;
2817 Some((if_token, Box::new(guard)))
2818 } else {
2819 None
2820 }
2821 },
2822 fat_arrow_token: input.parse()?,
2823 body: {
2824 let body = input.call(expr_early)?;
2825 requires_comma = requires_terminator(&body);
2826 Box::new(body)
2827 },
2828 comma: {
2829 if requires_comma && !input.is_empty() {
2830 Some(input.parse()?)
2831 } else {
2832 input.parse()?
2833 }
2834 },
2835 })
2836 }
2837 }
2838
David Tolnay1501f7e2018-08-27 14:21:03 -07002839 impl Parse for Index {
2840 fn parse(input: ParseStream) -> Result<Self> {
2841 let lit: LitInt = input.parse()?;
2842 if let IntSuffix::None = lit.suffix() {
2843 Ok(Index {
2844 index: lit.value() as u32,
2845 span: lit.span(),
2846 })
2847 } else {
David Tolnayff8c9342018-09-01 13:45:48 -07002848 Err(Error::new(lit.span(), "expected unsuffixed integer"))
David Tolnay1501f7e2018-08-27 14:21:03 -07002849 }
2850 }
David Tolnay85b69a42017-12-27 20:43:10 -05002851 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07002852
Michael Layzell734adb42017-06-07 16:58:31 -04002853 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002854 fn pat_range(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<PatRange> {
2855 Ok(PatRange {
2856 lo: Box::new(Expr::Path(ExprPath {
2857 attrs: Vec::new(),
2858 qself: qself,
2859 path: path,
2860 })),
2861 limits: input.parse()?,
2862 hi: input.call(pat_lit_expr)?,
David Tolnay310b3262018-08-30 15:33:00 -07002863 })
Alex Crichton954046c2017-05-30 21:49:42 -07002864 }
David Tolnay9636c052016-10-02 17:11:17 -07002865
Michael Layzell734adb42017-06-07 16:58:31 -04002866 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002867 fn pat_tuple(input: ParseStream) -> Result<PatTuple> {
2868 let content;
2869 let paren_token = parenthesized!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002870
David Tolnay310b3262018-08-30 15:33:00 -07002871 let mut front = Punctuated::new();
2872 let mut dot2_token = None::<Token![..]>;
2873 let mut comma_token = None::<Token![,]>;
2874 loop {
2875 if content.is_empty() {
2876 break;
David Tolnay60291082018-08-28 09:54:49 -07002877 }
David Tolnay310b3262018-08-30 15:33:00 -07002878 if content.peek(Token![..]) {
2879 dot2_token = Some(content.parse()?);
2880 comma_token = content.parse()?;
2881 break;
David Tolnay60291082018-08-28 09:54:49 -07002882 }
David Tolnay310b3262018-08-30 15:33:00 -07002883 let value: Pat = content.parse()?;
2884 front.push_value(value);
2885 if content.is_empty() {
2886 break;
2887 }
2888 let punct = content.parse()?;
2889 front.push_punct(punct);
2890 }
2891
David Tolnayf5ebc192018-08-30 18:23:46 -07002892 let mut back = Punctuated::new();
2893 while !content.is_empty() {
2894 let value: Pat = content.parse()?;
2895 back.push_value(value);
2896 if content.is_empty() {
2897 break;
2898 }
2899 let punct = content.parse()?;
2900 back.push_punct(punct);
2901 }
David Tolnay310b3262018-08-30 15:33:00 -07002902
2903 Ok(PatTuple {
2904 paren_token: paren_token,
2905 front: front,
2906 dot2_token: dot2_token,
2907 comma_token: comma_token,
2908 back: back,
2909 })
2910 }
2911
2912 #[cfg(feature = "full")]
2913 fn pat_ref(input: ParseStream) -> Result<PatRef> {
2914 Ok(PatRef {
2915 and_token: input.parse()?,
2916 mutability: input.parse()?,
2917 pat: input.parse()?,
2918 })
2919 }
2920
2921 #[cfg(feature = "full")]
David Tolnay8d534b02018-09-02 09:46:05 -07002922 fn pat_lit_or_range(input: ParseStream) -> Result<Pat> {
2923 let lo = input.call(pat_lit_expr)?;
2924 if input.peek(Token![..]) {
2925 Ok(Pat::Range(PatRange {
2926 lo: lo,
2927 limits: input.parse()?,
2928 hi: input.call(pat_lit_expr)?,
2929 }))
David Tolnay310b3262018-08-30 15:33:00 -07002930 } else {
David Tolnay8d534b02018-09-02 09:46:05 -07002931 Ok(Pat::Lit(PatLit { expr: lo }))
David Tolnay60291082018-08-28 09:54:49 -07002932 }
2933 }
2934
2935 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002936 fn pat_lit_expr(input: ParseStream) -> Result<Box<Expr>> {
2937 let neg: Option<Token![-]> = input.parse()?;
2938
2939 let lookahead = input.lookahead1();
2940 let expr = if lookahead.peek(Lit) {
Peter Hall04f42792019-04-02 16:58:45 +02002941 Expr::Lit(input.parse()?)
David Tolnay60291082018-08-28 09:54:49 -07002942 } else if lookahead.peek(Ident)
2943 || lookahead.peek(Token![::])
2944 || lookahead.peek(Token![<])
2945 || lookahead.peek(Token![self])
2946 || lookahead.peek(Token![Self])
2947 || lookahead.peek(Token![super])
2948 || lookahead.peek(Token![extern])
2949 || lookahead.peek(Token![crate])
2950 {
2951 Expr::Path(input.parse()?)
2952 } else {
2953 return Err(lookahead.error());
2954 };
2955
2956 Ok(Box::new(if let Some(neg) = neg {
David Tolnay8c91b882017-12-28 23:04:32 -05002957 Expr::Unary(ExprUnary {
2958 attrs: Vec::new(),
David Tolnayc29b9892017-12-27 22:58:14 -05002959 op: UnOp::Neg(neg),
David Tolnay60291082018-08-28 09:54:49 -07002960 expr: Box::new(expr),
David Tolnay3bc597f2017-12-31 02:31:11 -05002961 })
David Tolnay0ad9e9f2016-10-29 22:20:02 -07002962 } else {
David Tolnay60291082018-08-28 09:54:49 -07002963 expr
2964 }))
Alex Crichton954046c2017-05-30 21:49:42 -07002965 }
David Tolnay323279a2017-12-29 11:26:32 -05002966
2967 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002968 fn pat_slice(input: ParseStream) -> Result<PatSlice> {
2969 let content;
2970 let bracket_token = bracketed!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002971
David Tolnay310b3262018-08-30 15:33:00 -07002972 let mut front = Punctuated::new();
2973 let mut middle = None;
2974 loop {
2975 if content.is_empty() || content.peek(Token![..]) {
2976 break;
David Tolnay60291082018-08-28 09:54:49 -07002977 }
David Tolnay310b3262018-08-30 15:33:00 -07002978 let value: Pat = content.parse()?;
2979 if content.peek(Token![..]) {
2980 middle = Some(Box::new(value));
2981 break;
David Tolnay60291082018-08-28 09:54:49 -07002982 }
David Tolnay310b3262018-08-30 15:33:00 -07002983 front.push_value(value);
2984 if content.is_empty() {
2985 break;
2986 }
2987 let punct = content.parse()?;
2988 front.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002989 }
David Tolnay310b3262018-08-30 15:33:00 -07002990
2991 let dot2_token: Option<Token![..]> = content.parse()?;
2992 let mut comma_token = None::<Token![,]>;
2993 let mut back = Punctuated::new();
2994 if dot2_token.is_some() {
2995 comma_token = content.parse()?;
2996 if comma_token.is_some() {
2997 loop {
2998 if content.is_empty() {
2999 break;
3000 }
3001 let value: Pat = content.parse()?;
3002 back.push_value(value);
3003 if content.is_empty() {
3004 break;
3005 }
3006 let punct = content.parse()?;
3007 back.push_punct(punct);
3008 }
3009 }
3010 }
3011
3012 Ok(PatSlice {
3013 bracket_token: bracket_token,
3014 front: front,
3015 middle: middle,
3016 dot2_token: dot2_token,
3017 comma_token: comma_token,
3018 back: back,
3019 })
David Tolnay60291082018-08-28 09:54:49 -07003020 }
3021
3022 #[cfg(feature = "full")]
David Tolnay1501f7e2018-08-27 14:21:03 -07003023 impl Member {
3024 fn is_named(&self) -> bool {
3025 match *self {
3026 Member::Named(_) => true,
3027 Member::Unnamed(_) => false,
3028 }
3029 }
David Tolnay60291082018-08-28 09:54:49 -07003030
3031 fn is_unnamed(&self) -> bool {
3032 match *self {
3033 Member::Named(_) => false,
3034 Member::Unnamed(_) => true,
3035 }
3036 }
David Tolnay1501f7e2018-08-27 14:21:03 -07003037 }
David Tolnayb9c8e322016-09-23 20:48:37 -07003038}
3039
David Tolnayf4bbbd92016-09-23 14:41:55 -07003040#[cfg(feature = "printing")]
3041mod printing {
3042 use super::*;
David Tolnay64023912018-08-31 09:51:12 -07003043
Alex Crichtona74a1c82018-05-16 10:20:44 -07003044 use proc_macro2::{Literal, TokenStream};
3045 use quote::{ToTokens, TokenStreamExt};
David Tolnayf4bbbd92016-09-23 14:41:55 -07003046
David Tolnay64023912018-08-31 09:51:12 -07003047 #[cfg(feature = "full")]
3048 use attr::FilterAttrs;
3049 #[cfg(feature = "full")]
3050 use print::TokensOrDefault;
3051
David Tolnaybcf26022017-12-25 22:10:52 -05003052 // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
David Tolnayb6a0e7d2018-05-20 22:06:47 -07003053 // before appending it to `TokenStream`.
Michael Layzell3936ceb2017-07-08 00:28:36 -04003054 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003055 fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) {
David Tolnay8c91b882017-12-28 23:04:32 -05003056 if let Expr::Struct(_) = *e {
David Tolnay32954ef2017-12-26 22:43:16 -05003057 token::Paren::default().surround(tokens, |tokens| {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003058 e.to_tokens(tokens);
3059 });
3060 } else {
3061 e.to_tokens(tokens);
3062 }
3063 }
3064
David Tolnay8c91b882017-12-28 23:04:32 -05003065 #[cfg(feature = "full")]
David Tolnayd997aef2018-07-21 18:42:31 -07003066 fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
David Tolnay8c91b882017-12-28 23:04:32 -05003067 tokens.append_all(attrs.outer());
3068 }
Michael Layzell734adb42017-06-07 16:58:31 -04003069
David Tolnayd997aef2018-07-21 18:42:31 -07003070 #[cfg(feature = "full")]
3071 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3072 tokens.append_all(attrs.inner());
3073 }
3074
David Tolnay8c91b882017-12-28 23:04:32 -05003075 #[cfg(not(feature = "full"))]
David Tolnayd997aef2018-07-21 18:42:31 -07003076 fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3077
3078 #[cfg(not(feature = "full"))]
3079 fn inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
Alex Crichton62a0a592017-05-22 13:58:53 -07003080
Michael Layzell734adb42017-06-07 16:58:31 -04003081 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003082 impl ToTokens for ExprBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003083 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003084 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003085 self.box_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003086 self.expr.to_tokens(tokens);
3087 }
3088 }
3089
Michael Layzell734adb42017-06-07 16:58:31 -04003090 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003091 impl ToTokens for ExprInPlace {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003092 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003093 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8701a5c2017-12-28 23:31:10 -05003094 self.place.to_tokens(tokens);
3095 self.arrow_token.to_tokens(tokens);
3096 self.value.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003097 }
3098 }
3099
Michael Layzell734adb42017-06-07 16:58:31 -04003100 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003101 impl ToTokens for ExprArray {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003102 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003103 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003104 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003105 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003106 self.elems.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003107 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003108 }
3109 }
3110
3111 impl ToTokens for ExprCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003112 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003113 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003114 self.func.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003115 self.paren_token.surround(tokens, |tokens| {
3116 self.args.to_tokens(tokens);
3117 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003118 }
3119 }
3120
Michael Layzell734adb42017-06-07 16:58:31 -04003121 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003122 impl ToTokens for ExprMethodCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003123 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003124 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay76418512017-12-28 23:47:47 -05003125 self.receiver.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003126 self.dot_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003127 self.method.to_tokens(tokens);
David Tolnayd60cfec2017-12-29 00:21:38 -05003128 self.turbofish.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003129 self.paren_token.surround(tokens, |tokens| {
3130 self.args.to_tokens(tokens);
3131 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003132 }
3133 }
3134
Michael Layzell734adb42017-06-07 16:58:31 -04003135 #[cfg(feature = "full")]
David Tolnayd60cfec2017-12-29 00:21:38 -05003136 impl ToTokens for MethodTurbofish {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003137 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003138 self.colon2_token.to_tokens(tokens);
3139 self.lt_token.to_tokens(tokens);
3140 self.args.to_tokens(tokens);
3141 self.gt_token.to_tokens(tokens);
3142 }
3143 }
3144
3145 #[cfg(feature = "full")]
3146 impl ToTokens for GenericMethodArgument {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003147 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003148 match *self {
3149 GenericMethodArgument::Type(ref t) => t.to_tokens(tokens),
3150 GenericMethodArgument::Const(ref c) => c.to_tokens(tokens),
3151 }
3152 }
3153 }
3154
3155 #[cfg(feature = "full")]
David Tolnay05362582017-12-26 01:33:57 -05003156 impl ToTokens for ExprTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003157 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003158 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003159 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003160 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003161 self.elems.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003162 // If we only have one argument, we need a trailing comma to
David Tolnay05362582017-12-26 01:33:57 -05003163 // distinguish ExprTuple from ExprParen.
David Tolnaya0834b42018-01-01 21:30:02 -08003164 if self.elems.len() == 1 && !self.elems.trailing_punct() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003165 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003166 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003167 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003168 }
3169 }
3170
3171 impl ToTokens for ExprBinary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003172 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003173 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003174 self.left.to_tokens(tokens);
3175 self.op.to_tokens(tokens);
3176 self.right.to_tokens(tokens);
3177 }
3178 }
3179
3180 impl ToTokens for ExprUnary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003181 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003182 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003183 self.op.to_tokens(tokens);
3184 self.expr.to_tokens(tokens);
3185 }
3186 }
3187
David Tolnay8c91b882017-12-28 23:04:32 -05003188 impl ToTokens for ExprLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003189 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003190 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003191 self.lit.to_tokens(tokens);
3192 }
3193 }
3194
Alex Crichton62a0a592017-05-22 13:58:53 -07003195 impl ToTokens for ExprCast {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003196 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003197 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003198 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003199 self.as_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003200 self.ty.to_tokens(tokens);
3201 }
3202 }
3203
David Tolnay0cf94f22017-12-28 23:46:26 -05003204 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003205 impl ToTokens for ExprType {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003206 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003207 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003208 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003209 self.colon_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003210 self.ty.to_tokens(tokens);
3211 }
3212 }
3213
Michael Layzell734adb42017-06-07 16:58:31 -04003214 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003215 fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>) {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003216 if let Some((ref else_token, ref else_)) = *else_ {
3217 else_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003218
3219 // If we are not one of the valid expressions to exist in an else
3220 // clause, wrap ourselves in a block.
David Tolnay2ccf32a2017-12-29 00:34:26 -05003221 match **else_ {
David Tolnay9c119122018-09-01 18:47:02 -07003222 Expr::If(_) | Expr::Block(_) => {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003223 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003224 }
3225 _ => {
David Tolnay32954ef2017-12-26 22:43:16 -05003226 token::Brace::default().surround(tokens, |tokens| {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003227 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003228 });
3229 }
3230 }
3231 }
3232 }
3233
3234 #[cfg(feature = "full")]
David Tolnay9c119122018-09-01 18:47:02 -07003235 impl ToTokens for ExprLet {
3236 fn to_tokens(&self, tokens: &mut TokenStream) {
3237 outer_attrs_to_tokens(&self.attrs, tokens);
3238 self.let_token.to_tokens(tokens);
3239 self.pats.to_tokens(tokens);
3240 self.eq_token.to_tokens(tokens);
3241 wrap_bare_struct(tokens, &self.expr);
3242 }
3243 }
3244
3245 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003246 impl ToTokens for ExprIf {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003247 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003248 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003249 self.if_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003250 wrap_bare_struct(tokens, &self.cond);
David Tolnay2ccf32a2017-12-29 00:34:26 -05003251 self.then_branch.to_tokens(tokens);
3252 maybe_wrap_else(tokens, &self.else_branch);
Alex Crichton62a0a592017-05-22 13:58:53 -07003253 }
3254 }
3255
Michael Layzell734adb42017-06-07 16:58:31 -04003256 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003257 impl ToTokens for ExprWhile {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003258 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003259 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003260 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003261 self.while_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003262 wrap_bare_struct(tokens, &self.cond);
David Tolnay5d314dc2018-07-21 16:40:01 -07003263 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003264 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003265 tokens.append_all(&self.body.stmts);
3266 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003267 }
3268 }
3269
Michael Layzell734adb42017-06-07 16:58:31 -04003270 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003271 impl ToTokens for ExprForLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003272 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003273 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003274 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003275 self.for_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003276 self.pat.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003277 self.in_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003278 wrap_bare_struct(tokens, &self.expr);
David Tolnay5d314dc2018-07-21 16:40:01 -07003279 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003280 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003281 tokens.append_all(&self.body.stmts);
3282 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003283 }
3284 }
3285
Michael Layzell734adb42017-06-07 16:58:31 -04003286 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003287 impl ToTokens for ExprLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003288 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003289 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003290 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003291 self.loop_token.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003292 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003293 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003294 tokens.append_all(&self.body.stmts);
3295 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003296 }
3297 }
3298
Michael Layzell734adb42017-06-07 16:58:31 -04003299 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003300 impl ToTokens for ExprMatch {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003301 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003302 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003303 self.match_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003304 wrap_bare_struct(tokens, &self.expr);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003305 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003306 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay51382052017-12-27 13:46:21 -05003307 for (i, arm) in self.arms.iter().enumerate() {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003308 arm.to_tokens(tokens);
3309 // Ensure that we have a comma after a non-block arm, except
3310 // for the last one.
3311 let is_last = i == self.arms.len() - 1;
David Tolnaye532d6b2018-08-30 16:55:01 -07003312 if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003313 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003314 }
3315 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003316 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003317 }
3318 }
3319
Michael Layzell734adb42017-06-07 16:58:31 -04003320 #[cfg(feature = "full")]
David Tolnay02a9c6f2018-08-24 18:58:45 -04003321 impl ToTokens for ExprAsync {
3322 fn to_tokens(&self, tokens: &mut TokenStream) {
3323 outer_attrs_to_tokens(&self.attrs, tokens);
3324 self.async_token.to_tokens(tokens);
3325 self.capture.to_tokens(tokens);
3326 self.block.to_tokens(tokens);
3327 }
3328 }
3329
3330 #[cfg(feature = "full")]
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003331 impl ToTokens for ExprTryBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003332 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003333 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003334 self.try_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003335 self.block.to_tokens(tokens);
3336 }
3337 }
3338
Michael Layzell734adb42017-06-07 16:58:31 -04003339 #[cfg(feature = "full")]
Alex Crichtonfe110462017-06-01 12:49:27 -07003340 impl ToTokens for ExprYield {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003341 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003342 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonfe110462017-06-01 12:49:27 -07003343 self.yield_token.to_tokens(tokens);
3344 self.expr.to_tokens(tokens);
3345 }
3346 }
3347
3348 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003349 impl ToTokens for ExprClosure {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003350 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003351 outer_attrs_to_tokens(&self.attrs, tokens);
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09003352 self.asyncness.to_tokens(tokens);
David Tolnay13d4c0e2018-03-31 20:53:59 +02003353 self.movability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003354 self.capture.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003355 self.or1_token.to_tokens(tokens);
David Tolnay56080682018-01-06 14:01:52 -08003356 for input in self.inputs.pairs() {
3357 match **input.value() {
David Tolnay51382052017-12-27 13:46:21 -05003358 FnArg::Captured(ArgCaptured {
3359 ref pat,
3360 ty: Type::Infer(_),
3361 ..
3362 }) => {
Alex Crichton62a0a592017-05-22 13:58:53 -07003363 pat.to_tokens(tokens);
David Tolnay9636c052016-10-02 17:11:17 -07003364 }
David Tolnay56080682018-01-06 14:01:52 -08003365 _ => input.value().to_tokens(tokens),
David Tolnay3c2467c2016-10-02 17:55:08 -07003366 }
David Tolnayf2cfd722017-12-31 18:02:51 -05003367 input.punct().to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003368 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003369 self.or2_token.to_tokens(tokens);
David Tolnay7f675742017-12-27 22:43:21 -05003370 self.output.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003371 self.body.to_tokens(tokens);
3372 }
3373 }
3374
Michael Layzell734adb42017-06-07 16:58:31 -04003375 #[cfg(feature = "full")]
Nika Layzell640832a2017-12-04 13:37:09 -05003376 impl ToTokens for ExprUnsafe {
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);
Nika Layzell640832a2017-12-04 13:37:09 -05003379 self.unsafe_token.to_tokens(tokens);
David Tolnayc4be3512018-08-27 06:25:44 -07003380 self.block.brace_token.surround(tokens, |tokens| {
3381 inner_attrs_to_tokens(&self.attrs, tokens);
3382 tokens.append_all(&self.block.stmts);
3383 });
Nika Layzell640832a2017-12-04 13:37:09 -05003384 }
3385 }
3386
3387 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003388 impl ToTokens for ExprBlock {
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);
David Tolnay1d8e9962018-08-24 19:04:20 -04003391 self.label.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003392 self.block.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003393 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003394 tokens.append_all(&self.block.stmts);
3395 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003396 }
3397 }
3398
Michael Layzell734adb42017-06-07 16:58:31 -04003399 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003400 impl ToTokens for ExprAssign {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003401 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003402 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003403 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003404 self.eq_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003405 self.right.to_tokens(tokens);
3406 }
3407 }
3408
Michael Layzell734adb42017-06-07 16:58:31 -04003409 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003410 impl ToTokens for ExprAssignOp {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003411 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003412 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003413 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003414 self.op.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003415 self.right.to_tokens(tokens);
3416 }
3417 }
3418
3419 impl ToTokens for ExprField {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003420 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003421 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003422 self.base.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003423 self.dot_token.to_tokens(tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003424 self.member.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003425 }
3426 }
3427
David Tolnay85b69a42017-12-27 20:43:10 -05003428 impl ToTokens for Member {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003429 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay85b69a42017-12-27 20:43:10 -05003430 match *self {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003431 Member::Named(ref ident) => ident.to_tokens(tokens),
David Tolnay85b69a42017-12-27 20:43:10 -05003432 Member::Unnamed(ref index) => index.to_tokens(tokens),
3433 }
3434 }
3435 }
3436
David Tolnay85b69a42017-12-27 20:43:10 -05003437 impl ToTokens for Index {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003438 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichton9a4dca22018-03-28 06:32:19 -07003439 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
3440 lit.set_span(self.span);
3441 tokens.append(lit);
Alex Crichton62a0a592017-05-22 13:58:53 -07003442 }
3443 }
3444
3445 impl ToTokens for ExprIndex {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003446 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003447 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003448 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003449 self.bracket_token.surround(tokens, |tokens| {
3450 self.index.to_tokens(tokens);
3451 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003452 }
3453 }
3454
Michael Layzell734adb42017-06-07 16:58:31 -04003455 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003456 impl ToTokens for ExprRange {
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);
Alex Crichton62a0a592017-05-22 13:58:53 -07003459 self.from.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003460 match self.limits {
3461 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
3462 RangeLimits::Closed(ref t) => t.to_tokens(tokens),
3463 }
Alex Crichton62a0a592017-05-22 13:58:53 -07003464 self.to.to_tokens(tokens);
3465 }
3466 }
3467
3468 impl ToTokens for ExprPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003469 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003470 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay12f3b6f2018-09-01 16:10:53 -07003471 private::print_path(tokens, &self.qself, &self.path);
Alex Crichton62a0a592017-05-22 13:58:53 -07003472 }
3473 }
3474
Michael Layzell734adb42017-06-07 16:58:31 -04003475 #[cfg(feature = "full")]
David Tolnay00674ba2018-03-31 18:14:11 +02003476 impl ToTokens for ExprReference {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003477 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003478 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003479 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003480 self.mutability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003481 self.expr.to_tokens(tokens);
3482 }
3483 }
3484
Michael Layzell734adb42017-06-07 16:58:31 -04003485 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003486 impl ToTokens for ExprBreak {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003487 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003488 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003489 self.break_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003490 self.label.to_tokens(tokens);
3491 self.expr.to_tokens(tokens);
3492 }
3493 }
3494
Michael Layzell734adb42017-06-07 16:58:31 -04003495 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003496 impl ToTokens for ExprContinue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003497 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003498 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003499 self.continue_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003500 self.label.to_tokens(tokens);
3501 }
3502 }
3503
Michael Layzell734adb42017-06-07 16:58:31 -04003504 #[cfg(feature = "full")]
David Tolnayc246cd32017-12-28 23:14:32 -05003505 impl ToTokens for ExprReturn {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003506 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003507 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003508 self.return_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003509 self.expr.to_tokens(tokens);
3510 }
3511 }
3512
Michael Layzell734adb42017-06-07 16:58:31 -04003513 #[cfg(feature = "full")]
David Tolnay8c91b882017-12-28 23:04:32 -05003514 impl ToTokens for ExprMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003515 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003516 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003517 self.mac.to_tokens(tokens);
3518 }
3519 }
3520
3521 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003522 impl ToTokens for ExprStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003523 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003524 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003525 self.path.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003526 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003527 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003528 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003529 if self.rest.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -07003530 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003531 self.rest.to_tokens(tokens);
3532 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003533 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003534 }
3535 }
3536
Michael Layzell734adb42017-06-07 16:58:31 -04003537 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003538 impl ToTokens for ExprRepeat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003539 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003540 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003541 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003542 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003543 self.expr.to_tokens(tokens);
3544 self.semi_token.to_tokens(tokens);
David Tolnay84d80442018-01-07 01:03:20 -08003545 self.len.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003546 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003547 }
3548 }
3549
David Tolnaye98775f2017-12-28 23:17:00 -05003550 #[cfg(feature = "full")]
Michael Layzell93c36282017-06-04 20:43:14 -04003551 impl ToTokens for ExprGroup {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003552 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003553 outer_attrs_to_tokens(&self.attrs, tokens);
Michael Layzell93c36282017-06-04 20:43:14 -04003554 self.group_token.surround(tokens, |tokens| {
3555 self.expr.to_tokens(tokens);
3556 });
3557 }
3558 }
3559
Alex Crichton62a0a592017-05-22 13:58:53 -07003560 impl ToTokens for ExprParen {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003561 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003562 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003563 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003564 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003565 self.expr.to_tokens(tokens);
3566 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003567 }
3568 }
3569
Michael Layzell734adb42017-06-07 16:58:31 -04003570 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003571 impl ToTokens for ExprTry {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003572 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003573 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003574 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003575 self.question_token.to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003576 }
3577 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07003578
David Tolnay2ae520a2017-12-29 11:19:50 -05003579 impl ToTokens for ExprVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003580 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003581 self.tts.to_tokens(tokens);
3582 }
3583 }
3584
Michael Layzell734adb42017-06-07 16:58:31 -04003585 #[cfg(feature = "full")]
David Tolnaybcd498f2017-12-29 12:02:33 -05003586 impl ToTokens for Label {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003587 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaybcd498f2017-12-29 12:02:33 -05003588 self.name.to_tokens(tokens);
3589 self.colon_token.to_tokens(tokens);
3590 }
3591 }
3592
3593 #[cfg(feature = "full")]
David Tolnay055a7042016-10-02 19:23:54 -07003594 impl ToTokens for FieldValue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003595 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003596 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003597 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003598 if let Some(ref colon_token) = self.colon_token {
3599 colon_token.to_tokens(tokens);
David Tolnay276690f2016-10-30 12:06:59 -07003600 self.expr.to_tokens(tokens);
3601 }
David Tolnay055a7042016-10-02 19:23:54 -07003602 }
3603 }
3604
Michael Layzell734adb42017-06-07 16:58:31 -04003605 #[cfg(feature = "full")]
David Tolnayb4ad3b52016-10-01 21:58:13 -07003606 impl ToTokens for Arm {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003607 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003608 tokens.append_all(&self.attrs);
David Tolnay18cc4d42018-03-31 18:47:20 +02003609 self.leading_vert.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003610 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003611 if let Some((ref if_token, ref guard)) = self.guard {
3612 if_token.to_tokens(tokens);
3613 guard.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003614 }
David Tolnaydfb91432018-03-31 19:19:44 +02003615 self.fat_arrow_token.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003616 self.body.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003617 self.comma.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003618 }
3619 }
3620
Michael Layzell734adb42017-06-07 16:58:31 -04003621 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003622 impl ToTokens for PatWild {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003623 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003624 self.underscore_token.to_tokens(tokens);
3625 }
3626 }
3627
Michael Layzell734adb42017-06-07 16:58:31 -04003628 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003629 impl ToTokens for PatIdent {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003630 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay24237fb2017-12-29 02:15:26 -05003631 self.by_ref.to_tokens(tokens);
David Tolnayefc96fb2017-12-29 02:03:15 -05003632 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003633 self.ident.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003634 if let Some((ref at_token, ref subpat)) = self.subpat {
3635 at_token.to_tokens(tokens);
3636 subpat.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003637 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003638 }
3639 }
3640
Michael Layzell734adb42017-06-07 16:58:31 -04003641 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003642 impl ToTokens for PatStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003643 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003644 self.path.to_tokens(tokens);
3645 self.brace_token.surround(tokens, |tokens| {
3646 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003647 // NOTE: We need a comma before the dot2 token if it is present.
3648 if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003649 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003650 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003651 self.dot2_token.to_tokens(tokens);
3652 });
3653 }
3654 }
3655
Michael Layzell734adb42017-06-07 16:58:31 -04003656 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003657 impl ToTokens for PatTupleStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003658 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003659 self.path.to_tokens(tokens);
3660 self.pat.to_tokens(tokens);
3661 }
3662 }
3663
Michael Layzell734adb42017-06-07 16:58:31 -04003664 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003665 impl ToTokens for PatPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003666 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay12f3b6f2018-09-01 16:10:53 -07003667 private::print_path(tokens, &self.qself, &self.path);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003668 }
3669 }
3670
Michael Layzell734adb42017-06-07 16:58:31 -04003671 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003672 impl ToTokens for PatTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003673 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003674 self.paren_token.surround(tokens, |tokens| {
David Tolnay41871922017-12-29 01:53:45 -05003675 self.front.to_tokens(tokens);
3676 if let Some(ref dot2_token) = self.dot2_token {
3677 if !self.front.empty_or_trailing() {
3678 // Ensure there is a comma before the .. token.
David Tolnayf8db7ba2017-11-11 22:52:16 -08003679 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003680 }
David Tolnay41871922017-12-29 01:53:45 -05003681 dot2_token.to_tokens(tokens);
3682 self.comma_token.to_tokens(tokens);
3683 if self.comma_token.is_none() && !self.back.is_empty() {
3684 // Ensure there is a comma after the .. token.
3685 <Token![,]>::default().to_tokens(tokens);
3686 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07003687 }
David Tolnay41871922017-12-29 01:53:45 -05003688 self.back.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003689 });
3690 }
3691 }
3692
Michael Layzell734adb42017-06-07 16:58:31 -04003693 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003694 impl ToTokens for PatBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003695 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003696 self.box_token.to_tokens(tokens);
3697 self.pat.to_tokens(tokens);
3698 }
3699 }
3700
Michael Layzell734adb42017-06-07 16:58:31 -04003701 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003702 impl ToTokens for PatRef {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003703 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003704 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003705 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003706 self.pat.to_tokens(tokens);
3707 }
3708 }
3709
Michael Layzell734adb42017-06-07 16:58:31 -04003710 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003711 impl ToTokens for PatLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003712 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003713 self.expr.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 PatRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003719 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003720 self.lo.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003721 match self.limits {
3722 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
David Tolnay7ac699c2018-08-24 14:00:58 -04003723 RangeLimits::Closed(ref t) => Token![...](t.spans).to_tokens(tokens),
David Tolnay475288a2017-12-19 22:59:44 -08003724 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003725 self.hi.to_tokens(tokens);
3726 }
3727 }
3728
Michael Layzell734adb42017-06-07 16:58:31 -04003729 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003730 impl ToTokens for PatSlice {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003731 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003732 self.bracket_token.surround(tokens, |tokens| {
3733 self.front.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003734
3735 // If we need a comma before the middle or standalone .. token,
3736 // then make sure it's present.
David Tolnay51382052017-12-27 13:46:21 -05003737 if !self.front.empty_or_trailing()
3738 && (self.middle.is_some() || self.dot2_token.is_some())
Michael Layzell3936ceb2017-07-08 00:28:36 -04003739 {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003740 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003741 }
3742
3743 // If we have an identifier, we always need a .. token.
3744 if self.middle.is_some() {
3745 self.middle.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -07003746 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003747 } else if self.dot2_token.is_some() {
3748 self.dot2_token.to_tokens(tokens);
3749 }
3750
3751 // Make sure we have a comma before the back half.
3752 if !self.back.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07003753 TokensOrDefault(&self.comma_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003754 self.back.to_tokens(tokens);
3755 } else {
3756 self.comma_token.to_tokens(tokens);
3757 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003758 })
David Tolnayb4ad3b52016-10-01 21:58:13 -07003759 }
3760 }
3761
Michael Layzell734adb42017-06-07 16:58:31 -04003762 #[cfg(feature = "full")]
David Tolnay323279a2017-12-29 11:26:32 -05003763 impl ToTokens for PatMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003764 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay323279a2017-12-29 11:26:32 -05003765 self.mac.to_tokens(tokens);
3766 }
3767 }
3768
3769 #[cfg(feature = "full")]
David Tolnay2ae520a2017-12-29 11:19:50 -05003770 impl ToTokens for PatVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003771 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003772 self.tts.to_tokens(tokens);
3773 }
3774 }
3775
3776 #[cfg(feature = "full")]
David Tolnay8d9e81a2016-10-03 22:36:32 -07003777 impl ToTokens for FieldPat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003778 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay5d7098a2017-12-29 01:35:24 -05003779 if let Some(ref colon_token) = self.colon_token {
David Tolnay85b69a42017-12-27 20:43:10 -05003780 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003781 colon_token.to_tokens(tokens);
David Tolnay8d9e81a2016-10-03 22:36:32 -07003782 }
3783 self.pat.to_tokens(tokens);
3784 }
3785 }
3786
Michael Layzell734adb42017-06-07 16:58:31 -04003787 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003788 impl ToTokens for Block {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003789 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003790 self.brace_token.surround(tokens, |tokens| {
3791 tokens.append_all(&self.stmts);
3792 });
David Tolnay42602292016-10-01 22:25:45 -07003793 }
3794 }
3795
Michael Layzell734adb42017-06-07 16:58:31 -04003796 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003797 impl ToTokens for Stmt {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003798 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay42602292016-10-01 22:25:45 -07003799 match *self {
David Tolnay191e0582016-10-02 18:31:09 -07003800 Stmt::Local(ref local) => local.to_tokens(tokens),
David Tolnay42602292016-10-01 22:25:45 -07003801 Stmt::Item(ref item) => item.to_tokens(tokens),
3802 Stmt::Expr(ref expr) => expr.to_tokens(tokens),
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003803 Stmt::Semi(ref expr, ref semi) => {
David Tolnay42602292016-10-01 22:25:45 -07003804 expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003805 semi.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -07003806 }
David Tolnay42602292016-10-01 22:25:45 -07003807 }
3808 }
3809 }
David Tolnay191e0582016-10-02 18:31:09 -07003810
Michael Layzell734adb42017-06-07 16:58:31 -04003811 #[cfg(feature = "full")]
David Tolnay191e0582016-10-02 18:31:09 -07003812 impl ToTokens for Local {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003813 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003814 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003815 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003816 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003817 if let Some((ref colon_token, ref ty)) = self.ty {
3818 colon_token.to_tokens(tokens);
3819 ty.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003820 }
David Tolnay8b4d3022017-12-29 12:11:10 -05003821 if let Some((ref eq_token, ref init)) = self.init {
3822 eq_token.to_tokens(tokens);
3823 init.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003824 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003825 self.semi_token.to_tokens(tokens);
David Tolnay191e0582016-10-02 18:31:09 -07003826 }
3827 }
David Tolnayf4bbbd92016-09-23 14:41:55 -07003828}