blob: 419a8c17b0edadc8c7a926d06b56ac5fcdcf1287 [file] [log] [blame]
David Tolnay55535012018-01-05 16:39:23 -08001// Copyright 2018 Syn Developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
David Tolnayf4bbbd92016-09-23 14:41:55 -07009use super::*;
David Tolnaye303b7c2018-05-20 16:46:35 -070010use proc_macro2::{Span, TokenStream};
David Tolnay94d2b792018-04-29 12:26:10 -070011use punctuated::Punctuated;
David Tolnay14982012017-12-29 00:49:51 -050012#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -050013use std::hash::{Hash, Hasher};
David Tolnay2ae520a2017-12-29 11:19:50 -050014#[cfg(feature = "full")]
15use std::mem;
David Tolnay94d2b792018-04-29 12:26:10 -070016#[cfg(feature = "extra-traits")]
17use tt::TokenStreamHelper;
David Tolnayf4bbbd92016-09-23 14:41:55 -070018
Alex Crichton62a0a592017-05-22 13:58:53 -070019ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -080020 /// A Rust expression.
David Tolnay614a0142018-01-07 10:25:43 -080021 ///
David Tolnay461d98e2018-01-07 11:07:19 -080022 /// *This type is available if Syn is built with the `"derive"` or `"full"`
23 /// feature.*
24 ///
David Tolnay614a0142018-01-07 10:25:43 -080025 /// # Syntax tree enums
26 ///
27 /// This type is a syntax tree enum. In Syn this and other syntax tree enums
28 /// are designed to be traversed using the following rebinding idiom.
29 ///
30 /// ```
31 /// # use syn::Expr;
32 /// #
33 /// # fn example(expr: Expr) {
34 /// # const IGNORE: &str = stringify! {
35 /// let expr: Expr = /* ... */;
36 /// # };
37 /// match expr {
38 /// Expr::MethodCall(expr) => {
39 /// /* ... */
40 /// }
41 /// Expr::Cast(expr) => {
42 /// /* ... */
43 /// }
44 /// Expr::IfLet(expr) => {
45 /// /* ... */
46 /// }
47 /// /* ... */
48 /// # _ => {}
49 /// }
50 /// # }
51 /// ```
52 ///
53 /// We begin with a variable `expr` of type `Expr` that has no fields
54 /// (because it is an enum), and by matching on it and rebinding a variable
55 /// with the same name `expr` we effectively imbue our variable with all of
56 /// the data fields provided by the variant that it turned out to be. So for
57 /// example above if we ended up in the `MethodCall` case then we get to use
58 /// `expr.receiver`, `expr.args` etc; if we ended up in the `IfLet` case we
59 /// get to use `expr.pat`, `expr.then_branch`, `expr.else_branch`.
60 ///
61 /// The pattern is similar if the input expression is borrowed:
62 ///
63 /// ```
64 /// # use syn::Expr;
65 /// #
66 /// # fn example(expr: &Expr) {
67 /// match *expr {
68 /// Expr::MethodCall(ref expr) => {
69 /// # }
70 /// # _ => {}
71 /// # }
72 /// # }
73 /// ```
74 ///
75 /// This approach avoids repeating the variant names twice on every line.
76 ///
77 /// ```
78 /// # use syn::{Expr, ExprMethodCall};
79 /// #
80 /// # fn example(expr: Expr) {
81 /// # match expr {
82 /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => { // repetitive
83 /// # }
84 /// # _ => {}
85 /// # }
86 /// # }
87 /// ```
88 ///
89 /// In general, the name to which a syntax tree enum variant is bound should
90 /// be a suitable name for the complete syntax tree enum type.
91 ///
92 /// ```
93 /// # use syn::{Expr, ExprField};
94 /// #
95 /// # fn example(discriminant: &ExprField) {
96 /// // Binding is called `base` which is the name I would use if I were
97 /// // assigning `*discriminant.base` without an `if let`.
98 /// if let Expr::Tuple(ref base) = *discriminant.base {
99 /// # }
100 /// # }
101 /// ```
102 ///
103 /// A sign that you may not be choosing the right variable names is if you
104 /// see names getting repeated in your code, like accessing
105 /// `receiver.receiver` or `pat.pat` or `cond.cond`.
David Tolnay8c91b882017-12-28 23:04:32 -0500106 pub enum Expr {
David Tolnaya454c8f2018-01-07 01:01:10 -0800107 /// A box expression: `box f`.
David Tolnay461d98e2018-01-07 11:07:19 -0800108 ///
109 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400110 pub Box(ExprBox #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500111 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800112 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500113 pub expr: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700114 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500115
David Tolnaya454c8f2018-01-07 01:01:10 -0800116 /// A placement expression: `place <- value`.
David Tolnay461d98e2018-01-07 11:07:19 -0800117 ///
118 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400119 pub InPlace(ExprInPlace #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500120 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700121 pub place: Box<Expr>,
David Tolnay8701a5c2017-12-28 23:31:10 -0500122 pub arrow_token: Token![<-],
Alex Crichton62a0a592017-05-22 13:58:53 -0700123 pub value: Box<Expr>,
124 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500125
David Tolnaya454c8f2018-01-07 01:01:10 -0800126 /// A slice literal expression: `[a, b, c, d]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800127 ///
128 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400129 pub Array(ExprArray #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500130 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500131 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500132 pub elems: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700133 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500134
David Tolnaya454c8f2018-01-07 01:01:10 -0800135 /// A function call expression: `invoke(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800136 ///
137 /// *This type is available if Syn is built with the `"derive"` or
138 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700139 pub Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -0500140 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700141 pub func: Box<Expr>,
David Tolnay32954ef2017-12-26 22:43:16 -0500142 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500143 pub args: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700144 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500145
David Tolnaya454c8f2018-01-07 01:01:10 -0800146 /// A method call expression: `x.foo::<T>(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800147 ///
148 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400149 pub MethodCall(ExprMethodCall #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500150 pub attrs: Vec<Attribute>,
David Tolnay76418512017-12-28 23:47:47 -0500151 pub receiver: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800152 pub dot_token: Token![.],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500153 pub method: Ident,
David Tolnayd60cfec2017-12-29 00:21:38 -0500154 pub turbofish: Option<MethodTurbofish>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500155 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500156 pub args: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700157 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500158
David Tolnaya454c8f2018-01-07 01:01:10 -0800159 /// A tuple expression: `(a, b, c, d)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800160 ///
161 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay05362582017-12-26 01:33:57 -0500162 pub Tuple(ExprTuple #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500163 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500164 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500165 pub elems: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700166 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500167
David Tolnaya454c8f2018-01-07 01:01:10 -0800168 /// A binary operation: `a + b`, `a * b`.
David Tolnay461d98e2018-01-07 11:07:19 -0800169 ///
170 /// *This type is available if Syn is built with the `"derive"` or
171 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700172 pub Binary(ExprBinary {
David Tolnay8c91b882017-12-28 23:04:32 -0500173 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700174 pub left: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500175 pub op: BinOp,
Alex Crichton62a0a592017-05-22 13:58:53 -0700176 pub right: Box<Expr>,
177 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500178
David Tolnaya454c8f2018-01-07 01:01:10 -0800179 /// A unary operation: `!x`, `*x`.
David Tolnay461d98e2018-01-07 11:07:19 -0800180 ///
181 /// *This type is available if Syn is built with the `"derive"` or
182 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700183 pub Unary(ExprUnary {
David Tolnay8c91b882017-12-28 23:04:32 -0500184 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700185 pub op: UnOp,
186 pub expr: Box<Expr>,
187 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500188
David Tolnaya454c8f2018-01-07 01:01:10 -0800189 /// A literal in place of an expression: `1`, `"foo"`.
David Tolnay461d98e2018-01-07 11:07:19 -0800190 ///
191 /// *This type is available if Syn is built with the `"derive"` or
192 /// `"full"` feature.*
David Tolnay8c91b882017-12-28 23:04:32 -0500193 pub Lit(ExprLit {
194 pub attrs: Vec<Attribute>,
195 pub lit: Lit,
196 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500197
David Tolnaya454c8f2018-01-07 01:01:10 -0800198 /// A cast expression: `foo as f64`.
David Tolnay461d98e2018-01-07 11:07:19 -0800199 ///
200 /// *This type is available if Syn is built with the `"derive"` or
201 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700202 pub Cast(ExprCast {
David Tolnay8c91b882017-12-28 23:04:32 -0500203 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700204 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800205 pub as_token: Token![as],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800206 pub ty: Box<Type>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700207 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500208
David Tolnaya454c8f2018-01-07 01:01:10 -0800209 /// A type ascription expression: `foo: f64`.
David Tolnay461d98e2018-01-07 11:07:19 -0800210 ///
211 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay0cf94f22017-12-28 23:46:26 -0500212 pub Type(ExprType #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500213 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700214 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800215 pub colon_token: Token![:],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800216 pub ty: Box<Type>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700217 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500218
David Tolnaya454c8f2018-01-07 01:01:10 -0800219 /// An `if` expression with an optional `else` block: `if expr { ... }
220 /// else { ... }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700221 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800222 /// The `else` branch expression may only be an `If`, `IfLet`, or
223 /// `Block` expression, not any of the other types of expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800224 ///
225 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400226 pub If(ExprIf #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500227 pub attrs: Vec<Attribute>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500228 pub if_token: Token![if],
Alex Crichton62a0a592017-05-22 13:58:53 -0700229 pub cond: Box<Expr>,
David Tolnay2ccf32a2017-12-29 00:34:26 -0500230 pub then_branch: Block,
231 pub else_branch: Option<(Token![else], Box<Expr>)>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700232 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500233
David Tolnaya454c8f2018-01-07 01:01:10 -0800234 /// An `if let` expression with an optional `else` block: `if let pat =
235 /// expr { ... } else { ... }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700236 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800237 /// The `else` branch expression may only be an `If`, `IfLet`, or
238 /// `Block` expression, not any of the other types of expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800239 ///
240 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400241 pub IfLet(ExprIfLet #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500242 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800243 pub if_token: Token![if],
244 pub let_token: Token![let],
David Tolnay5b5b7d22018-03-31 21:05:00 +0200245 pub pats: Punctuated<Pat, Token![|]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800246 pub eq_token: Token![=],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500247 pub expr: Box<Expr>,
David Tolnay2ccf32a2017-12-29 00:34:26 -0500248 pub then_branch: Block,
249 pub else_branch: Option<(Token![else], Box<Expr>)>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700250 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500251
David Tolnaya454c8f2018-01-07 01:01:10 -0800252 /// A while loop: `while expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800253 ///
254 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400255 pub While(ExprWhile #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500256 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500257 pub label: Option<Label>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800258 pub while_token: Token![while],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500259 pub cond: Box<Expr>,
260 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700261 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500262
David Tolnaya454c8f2018-01-07 01:01:10 -0800263 /// A while-let loop: `while let pat = expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800264 ///
265 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400266 pub WhileLet(ExprWhileLet #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500267 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500268 pub label: Option<Label>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800269 pub while_token: Token![while],
270 pub let_token: Token![let],
David Tolnay5b5b7d22018-03-31 21:05:00 +0200271 pub pats: Punctuated<Pat, Token![|]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800272 pub eq_token: Token![=],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500273 pub expr: Box<Expr>,
274 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700275 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500276
David Tolnaya454c8f2018-01-07 01:01:10 -0800277 /// A for loop: `for pat in expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800278 ///
279 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400280 pub ForLoop(ExprForLoop #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500281 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500282 pub label: Option<Label>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500283 pub for_token: Token![for],
Alex Crichton62a0a592017-05-22 13:58:53 -0700284 pub pat: Box<Pat>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500285 pub in_token: Token![in],
Alex Crichton62a0a592017-05-22 13:58:53 -0700286 pub expr: Box<Expr>,
287 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700288 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500289
David Tolnaya454c8f2018-01-07 01:01:10 -0800290 /// Conditionless loop: `loop { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800291 ///
292 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400293 pub Loop(ExprLoop #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500294 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500295 pub label: Option<Label>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500296 pub loop_token: Token![loop],
297 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700298 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500299
David Tolnaya454c8f2018-01-07 01:01:10 -0800300 /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800301 ///
302 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400303 pub Match(ExprMatch #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500304 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800305 pub match_token: Token![match],
Alex Crichton62a0a592017-05-22 13:58:53 -0700306 pub expr: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500307 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700308 pub arms: Vec<Arm>,
309 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500310
David Tolnaya454c8f2018-01-07 01:01:10 -0800311 /// A closure expression: `|a, b| a + b`.
David Tolnay461d98e2018-01-07 11:07:19 -0800312 ///
313 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400314 pub Closure(ExprClosure #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500315 pub attrs: Vec<Attribute>,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +0900316 pub asyncness: Option<Token![async]>,
David Tolnay13d4c0e2018-03-31 20:53:59 +0200317 pub movability: Option<Token![static]>,
David Tolnayefc96fb2017-12-29 02:03:15 -0500318 pub capture: Option<Token![move]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800319 pub or1_token: Token![|],
David Tolnayf2cfd722017-12-31 18:02:51 -0500320 pub inputs: Punctuated<FnArg, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800321 pub or2_token: Token![|],
David Tolnay7f675742017-12-27 22:43:21 -0500322 pub output: ReturnType,
323 pub body: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700324 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500325
David Tolnaya454c8f2018-01-07 01:01:10 -0800326 /// An unsafe block: `unsafe { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800327 ///
328 /// *This type is available if Syn is built with the `"full"` feature.*
Nika Layzell640832a2017-12-04 13:37:09 -0500329 pub Unsafe(ExprUnsafe #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500330 pub attrs: Vec<Attribute>,
Nika Layzell640832a2017-12-04 13:37:09 -0500331 pub unsafe_token: Token![unsafe],
332 pub block: Block,
333 }),
334
David Tolnaya454c8f2018-01-07 01:01:10 -0800335 /// A blocked scope: `{ ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800336 ///
337 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400338 pub Block(ExprBlock #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500339 pub attrs: Vec<Attribute>,
David Tolnay1d8e9962018-08-24 19:04:20 -0400340 pub label: Option<Label>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700341 pub block: Block,
342 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700343
David Tolnaya454c8f2018-01-07 01:01:10 -0800344 /// An assignment expression: `a = compute()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800345 ///
346 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400347 pub Assign(ExprAssign #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500348 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700349 pub left: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800350 pub eq_token: Token![=],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500351 pub right: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700352 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500353
David Tolnaya454c8f2018-01-07 01:01:10 -0800354 /// A compound assignment expression: `counter += 1`.
David Tolnay461d98e2018-01-07 11:07:19 -0800355 ///
356 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400357 pub AssignOp(ExprAssignOp #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500358 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700359 pub left: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500360 pub op: BinOp,
Alex Crichton62a0a592017-05-22 13:58:53 -0700361 pub right: Box<Expr>,
362 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500363
David Tolnaya454c8f2018-01-07 01:01:10 -0800364 /// Access of a named struct field (`obj.k`) or unnamed tuple struct
David Tolnay85b69a42017-12-27 20:43:10 -0500365 /// field (`obj.0`).
David Tolnay461d98e2018-01-07 11:07:19 -0800366 ///
367 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd5147742018-06-30 10:09:52 -0700368 pub Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -0500369 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -0500370 pub base: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800371 pub dot_token: Token![.],
David Tolnay85b69a42017-12-27 20:43:10 -0500372 pub member: Member,
Alex Crichton62a0a592017-05-22 13:58:53 -0700373 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500374
David Tolnay05658502018-01-07 09:56:37 -0800375 /// A square bracketed indexing expression: `vector[2]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800376 ///
377 /// *This type is available if Syn is built with the `"derive"` or
378 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700379 pub Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -0500380 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700381 pub expr: Box<Expr>,
David Tolnay32954ef2017-12-26 22:43:16 -0500382 pub bracket_token: token::Bracket,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500383 pub index: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700384 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500385
David Tolnaya454c8f2018-01-07 01:01:10 -0800386 /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800387 ///
388 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400389 pub Range(ExprRange #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500390 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700391 pub from: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700392 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500393 pub to: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700394 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700395
David Tolnaya454c8f2018-01-07 01:01:10 -0800396 /// A path like `std::mem::replace` possibly containing generic
397 /// parameters and a qualified self-type.
Alex Crichton62a0a592017-05-22 13:58:53 -0700398 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800399 /// A plain identifier like `x` is a path of length 1.
David Tolnay461d98e2018-01-07 11:07:19 -0800400 ///
401 /// *This type is available if Syn is built with the `"derive"` or
402 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700403 pub Path(ExprPath {
David Tolnay8c91b882017-12-28 23:04:32 -0500404 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700405 pub qself: Option<QSelf>,
406 pub path: Path,
407 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700408
David Tolnaya454c8f2018-01-07 01:01:10 -0800409 /// A referencing operation: `&a` or `&mut a`.
David Tolnay461d98e2018-01-07 11:07:19 -0800410 ///
411 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay00674ba2018-03-31 18:14:11 +0200412 pub Reference(ExprReference #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500413 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800414 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500415 pub mutability: Option<Token![mut]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700416 pub expr: Box<Expr>,
417 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500418
David Tolnaya454c8f2018-01-07 01:01:10 -0800419 /// A `break`, with an optional label to break and an optional
420 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800421 ///
422 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400423 pub Break(ExprBreak #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500424 pub attrs: Vec<Attribute>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500425 pub break_token: Token![break],
David Tolnay63e3dee2017-06-03 20:13:17 -0700426 pub label: Option<Lifetime>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700427 pub expr: Option<Box<Expr>>,
428 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500429
David Tolnaya454c8f2018-01-07 01:01:10 -0800430 /// A `continue`, with an optional label.
David Tolnay461d98e2018-01-07 11:07:19 -0800431 ///
432 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400433 pub Continue(ExprContinue #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500434 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800435 pub continue_token: Token![continue],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500436 pub label: Option<Lifetime>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700437 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500438
David Tolnaya454c8f2018-01-07 01:01:10 -0800439 /// A `return`, with an optional value to be returned.
David Tolnay461d98e2018-01-07 11:07:19 -0800440 ///
441 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayc246cd32017-12-28 23:14:32 -0500442 pub Return(ExprReturn #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500443 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800444 pub return_token: Token![return],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500445 pub expr: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700446 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700447
David Tolnaya454c8f2018-01-07 01:01:10 -0800448 /// A macro invocation expression: `format!("{}", q)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800449 ///
450 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay8c91b882017-12-28 23:04:32 -0500451 pub Macro(ExprMacro #full {
452 pub attrs: Vec<Attribute>,
453 pub mac: Macro,
454 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700455
David Tolnaya454c8f2018-01-07 01:01:10 -0800456 /// A struct literal expression: `Point { x: 1, y: 1 }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700457 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800458 /// The `rest` provides the value of the remaining fields as in `S { a:
459 /// 1, b: 1, ..rest }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800460 ///
461 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400462 pub Struct(ExprStruct #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500463 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700464 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500465 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500466 pub fields: Punctuated<FieldValue, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500467 pub dot2_token: Option<Token![..]>,
468 pub rest: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700469 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700470
David Tolnaya454c8f2018-01-07 01:01:10 -0800471 /// An array literal constructed from one repeated element: `[0u8; N]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800472 ///
473 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400474 pub Repeat(ExprRepeat #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500475 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500476 pub bracket_token: token::Bracket,
Alex Crichton62a0a592017-05-22 13:58:53 -0700477 pub expr: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500478 pub semi_token: Token![;],
David Tolnay84d80442018-01-07 01:03:20 -0800479 pub len: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700480 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700481
David Tolnaya454c8f2018-01-07 01:01:10 -0800482 /// A parenthesized expression: `(a + b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800483 ///
484 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay9374bc02018-01-27 18:49:36 -0800485 pub Paren(ExprParen {
David Tolnay8c91b882017-12-28 23:04:32 -0500486 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500487 pub paren_token: token::Paren,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500488 pub expr: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700489 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700490
David Tolnaya454c8f2018-01-07 01:01:10 -0800491 /// An expression contained within invisible delimiters.
Michael Layzell93c36282017-06-04 20:43:14 -0400492 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800493 /// This variant is important for faithfully representing the precedence
494 /// of expressions and is related to `None`-delimited spans in a
495 /// `TokenStream`.
David Tolnay461d98e2018-01-07 11:07:19 -0800496 ///
497 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaye98775f2017-12-28 23:17:00 -0500498 pub Group(ExprGroup #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500499 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500500 pub group_token: token::Group,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500501 pub expr: Box<Expr>,
Michael Layzell93c36282017-06-04 20:43:14 -0400502 }),
503
David Tolnaya454c8f2018-01-07 01:01:10 -0800504 /// A try-expression: `expr?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800505 ///
506 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400507 pub Try(ExprTry #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500508 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700509 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800510 pub question_token: Token![?],
Alex Crichton62a0a592017-05-22 13:58:53 -0700511 }),
Arnavion02ef13f2017-04-25 00:54:31 -0700512
David Tolnay02a9c6f2018-08-24 18:58:45 -0400513 /// An async block: `async { ... }`.
514 ///
515 /// *This type is available if Syn is built with the `"full"` feature.*
516 pub Async(ExprAsync #full {
517 pub attrs: Vec<Attribute>,
518 pub async_token: Token![async],
519 pub capture: Option<Token![move]>,
520 pub block: Block,
521 }),
522
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400523 /// A try block: `try { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800524 ///
525 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400526 pub TryBlock(ExprTryBlock #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500527 pub attrs: Vec<Attribute>,
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400528 pub try_token: Token![try],
Alex Crichton62a0a592017-05-22 13:58:53 -0700529 pub block: Block,
530 }),
Alex Crichtonfe110462017-06-01 12:49:27 -0700531
David Tolnaya454c8f2018-01-07 01:01:10 -0800532 /// A yield expression: `yield expr`.
David Tolnay461d98e2018-01-07 11:07:19 -0800533 ///
534 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonfe110462017-06-01 12:49:27 -0700535 pub Yield(ExprYield #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500536 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800537 pub yield_token: Token![yield],
Alex Crichtonfe110462017-06-01 12:49:27 -0700538 pub expr: Option<Box<Expr>>,
539 }),
David Tolnay2ae520a2017-12-29 11:19:50 -0500540
David Tolnaya454c8f2018-01-07 01:01:10 -0800541 /// Tokens in expression position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800542 ///
543 /// *This type is available if Syn is built with the `"derive"` or
544 /// `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500545 pub Verbatim(ExprVerbatim #manual_extra_traits {
546 pub tts: TokenStream,
547 }),
548 }
549}
550
551#[cfg(feature = "extra-traits")]
552impl Eq for ExprVerbatim {}
553
554#[cfg(feature = "extra-traits")]
555impl PartialEq for ExprVerbatim {
556 fn eq(&self, other: &Self) -> bool {
557 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
558 }
559}
560
561#[cfg(feature = "extra-traits")]
562impl Hash for ExprVerbatim {
563 fn hash<H>(&self, state: &mut H)
564 where
565 H: Hasher,
566 {
567 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700568 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700569}
570
David Tolnay8c91b882017-12-28 23:04:32 -0500571impl Expr {
572 // Not public API.
573 #[doc(hidden)]
David Tolnay096d4982017-12-28 23:18:18 -0500574 #[cfg(feature = "full")]
David Tolnay2ae520a2017-12-29 11:19:50 -0500575 pub fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
David Tolnay8c91b882017-12-28 23:04:32 -0500576 match *self {
David Tolnay61037c62018-01-05 16:21:03 -0800577 Expr::Box(ExprBox { ref mut attrs, .. })
578 | Expr::InPlace(ExprInPlace { ref mut attrs, .. })
579 | Expr::Array(ExprArray { ref mut attrs, .. })
580 | Expr::Call(ExprCall { ref mut attrs, .. })
581 | Expr::MethodCall(ExprMethodCall { ref mut attrs, .. })
582 | Expr::Tuple(ExprTuple { ref mut attrs, .. })
583 | Expr::Binary(ExprBinary { ref mut attrs, .. })
584 | Expr::Unary(ExprUnary { ref mut attrs, .. })
585 | Expr::Lit(ExprLit { ref mut attrs, .. })
586 | Expr::Cast(ExprCast { ref mut attrs, .. })
587 | Expr::Type(ExprType { ref mut attrs, .. })
588 | Expr::If(ExprIf { ref mut attrs, .. })
589 | Expr::IfLet(ExprIfLet { ref mut attrs, .. })
590 | Expr::While(ExprWhile { ref mut attrs, .. })
591 | Expr::WhileLet(ExprWhileLet { ref mut attrs, .. })
592 | Expr::ForLoop(ExprForLoop { ref mut attrs, .. })
593 | Expr::Loop(ExprLoop { ref mut attrs, .. })
594 | Expr::Match(ExprMatch { ref mut attrs, .. })
595 | Expr::Closure(ExprClosure { ref mut attrs, .. })
596 | Expr::Unsafe(ExprUnsafe { ref mut attrs, .. })
597 | Expr::Block(ExprBlock { ref mut attrs, .. })
598 | Expr::Assign(ExprAssign { ref mut attrs, .. })
599 | Expr::AssignOp(ExprAssignOp { ref mut attrs, .. })
600 | Expr::Field(ExprField { ref mut attrs, .. })
601 | Expr::Index(ExprIndex { ref mut attrs, .. })
602 | Expr::Range(ExprRange { ref mut attrs, .. })
603 | Expr::Path(ExprPath { ref mut attrs, .. })
David Tolnay00674ba2018-03-31 18:14:11 +0200604 | Expr::Reference(ExprReference { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800605 | Expr::Break(ExprBreak { ref mut attrs, .. })
606 | Expr::Continue(ExprContinue { ref mut attrs, .. })
607 | Expr::Return(ExprReturn { ref mut attrs, .. })
608 | Expr::Macro(ExprMacro { ref mut attrs, .. })
609 | Expr::Struct(ExprStruct { ref mut attrs, .. })
610 | Expr::Repeat(ExprRepeat { ref mut attrs, .. })
611 | Expr::Paren(ExprParen { ref mut attrs, .. })
612 | Expr::Group(ExprGroup { ref mut attrs, .. })
613 | Expr::Try(ExprTry { ref mut attrs, .. })
David Tolnay02a9c6f2018-08-24 18:58:45 -0400614 | Expr::Async(ExprAsync { ref mut attrs, .. })
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400615 | Expr::TryBlock(ExprTryBlock { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800616 | Expr::Yield(ExprYield { ref mut attrs, .. }) => mem::replace(attrs, new),
David Tolnay2ae520a2017-12-29 11:19:50 -0500617 Expr::Verbatim(_) => {
618 // TODO
619 Vec::new()
620 }
David Tolnay8c91b882017-12-28 23:04:32 -0500621 }
622 }
623}
624
David Tolnay85b69a42017-12-27 20:43:10 -0500625ast_enum! {
626 /// A struct or tuple struct field accessed in a struct literal or field
627 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800628 ///
629 /// *This type is available if Syn is built with the `"derive"` or `"full"`
630 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500631 pub enum Member {
632 /// A named field like `self.x`.
633 Named(Ident),
634 /// An unnamed field like `self.0`.
635 Unnamed(Index),
636 }
637}
638
David Tolnay85b69a42017-12-27 20:43:10 -0500639ast_struct! {
640 /// The index of an unnamed tuple struct field.
David Tolnay461d98e2018-01-07 11:07:19 -0800641 ///
642 /// *This type is available if Syn is built with the `"derive"` or `"full"`
643 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500644 pub struct Index #manual_extra_traits {
645 pub index: u32,
646 pub span: Span,
647 }
648}
649
David Tolnay14982012017-12-29 00:49:51 -0500650impl From<usize> for Index {
651 fn from(index: usize) -> Index {
David Tolnay34071ba2018-05-20 20:00:41 -0700652 assert!(index < u32::max_value() as usize);
David Tolnay14982012017-12-29 00:49:51 -0500653 Index {
654 index: index as u32,
Alex Crichton9a4dca22018-03-28 06:32:19 -0700655 span: Span::call_site(),
David Tolnay14982012017-12-29 00:49:51 -0500656 }
657 }
658}
659
660#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500661impl Eq for Index {}
662
David Tolnay14982012017-12-29 00:49:51 -0500663#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500664impl PartialEq for Index {
665 fn eq(&self, other: &Self) -> bool {
666 self.index == other.index
667 }
668}
669
David Tolnay14982012017-12-29 00:49:51 -0500670#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500671impl Hash for Index {
672 fn hash<H: Hasher>(&self, state: &mut H) {
673 self.index.hash(state);
674 }
675}
676
677#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700678ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800679 /// The `::<>` explicit type parameters passed to a method call:
680 /// `parse::<u64>()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800681 ///
682 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500683 pub struct MethodTurbofish {
684 pub colon2_token: Token![::],
685 pub lt_token: Token![<],
David Tolnayf2cfd722017-12-31 18:02:51 -0500686 pub args: Punctuated<GenericMethodArgument, Token![,]>,
David Tolnayd60cfec2017-12-29 00:21:38 -0500687 pub gt_token: Token![>],
688 }
689}
690
691#[cfg(feature = "full")]
692ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800693 /// An individual generic argument to a method, like `T`.
David Tolnay461d98e2018-01-07 11:07:19 -0800694 ///
695 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500696 pub enum GenericMethodArgument {
David Tolnaya454c8f2018-01-07 01:01:10 -0800697 /// A type argument.
David Tolnayd60cfec2017-12-29 00:21:38 -0500698 Type(Type),
David Tolnaya454c8f2018-01-07 01:01:10 -0800699 /// A const expression. Must be inside of a block.
David Tolnayd60cfec2017-12-29 00:21:38 -0500700 ///
701 /// NOTE: Identity expressions are represented as Type arguments, as
702 /// they are indistinguishable syntactically.
703 Const(Expr),
704 }
705}
706
707#[cfg(feature = "full")]
708ast_struct! {
Alex Crichton62a0a592017-05-22 13:58:53 -0700709 /// A field-value pair in a struct literal.
David Tolnay461d98e2018-01-07 11:07:19 -0800710 ///
711 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700712 pub struct FieldValue {
David Tolnay85b69a42017-12-27 20:43:10 -0500713 /// Attributes tagged on the field.
714 pub attrs: Vec<Attribute>,
715
716 /// Name or index of the field.
717 pub member: Member,
718
David Tolnay5d7098a2017-12-29 01:35:24 -0500719 /// The colon in `Struct { x: x }`. If written in shorthand like
720 /// `Struct { x }`, there is no colon.
David Tolnay85b69a42017-12-27 20:43:10 -0500721 pub colon_token: Option<Token![:]>,
Clar Charrd22b5702017-03-10 15:24:56 -0500722
Alex Crichton62a0a592017-05-22 13:58:53 -0700723 /// Value of the field.
724 pub expr: Expr,
Alex Crichton62a0a592017-05-22 13:58:53 -0700725 }
David Tolnay055a7042016-10-02 19:23:54 -0700726}
727
Michael Layzell734adb42017-06-07 16:58:31 -0400728#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700729ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800730 /// A lifetime labeling a `for`, `while`, or `loop`.
David Tolnay461d98e2018-01-07 11:07:19 -0800731 ///
732 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaybcd498f2017-12-29 12:02:33 -0500733 pub struct Label {
734 pub name: Lifetime,
735 pub colon_token: Token![:],
736 }
737}
738
739#[cfg(feature = "full")]
740ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800741 /// A braced block containing Rust statements.
David Tolnay461d98e2018-01-07 11:07:19 -0800742 ///
743 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700744 pub struct Block {
David Tolnay32954ef2017-12-26 22:43:16 -0500745 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700746 /// Statements in a block
747 pub stmts: Vec<Stmt>,
748 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700749}
750
Michael Layzell734adb42017-06-07 16:58:31 -0400751#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700752ast_enum! {
753 /// A statement, usually ending in a semicolon.
David Tolnay461d98e2018-01-07 11:07:19 -0800754 ///
755 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700756 pub enum Stmt {
757 /// A local (let) binding.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800758 Local(Local),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700759
Alex Crichton62a0a592017-05-22 13:58:53 -0700760 /// An item definition.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800761 Item(Item),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700762
Alex Crichton62a0a592017-05-22 13:58:53 -0700763 /// Expr without trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800764 Expr(Expr),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700765
David Tolnaya454c8f2018-01-07 01:01:10 -0800766 /// Expression with trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800767 Semi(Expr, Token![;]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700768 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700769}
770
Michael Layzell734adb42017-06-07 16:58:31 -0400771#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700772ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800773 /// A local `let` binding: `let x: u64 = s.parse()?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800774 ///
775 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700776 pub struct Local {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500777 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800778 pub let_token: Token![let],
David Tolnay5b5b7d22018-03-31 21:05:00 +0200779 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500780 pub ty: Option<(Token![:], Box<Type>)>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500781 pub init: Option<(Token![=], Box<Expr>)>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500782 pub semi_token: Token![;],
Alex Crichton62a0a592017-05-22 13:58:53 -0700783 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700784}
785
Michael Layzell734adb42017-06-07 16:58:31 -0400786#[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700787ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800788 /// A pattern in a local binding, function signature, match expression, or
789 /// various other places.
David Tolnay614a0142018-01-07 10:25:43 -0800790 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800791 /// *This type is available if Syn is built with the `"full"` feature.*
792 ///
David Tolnay614a0142018-01-07 10:25:43 -0800793 /// # Syntax tree enum
794 ///
795 /// This type is a [syntax tree enum].
796 ///
797 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
Alex Crichton62a0a592017-05-22 13:58:53 -0700798 // Clippy false positive
799 // https://github.com/Manishearth/rust-clippy/issues/1241
800 #[cfg_attr(feature = "cargo-clippy", allow(enum_variant_names))]
801 pub enum Pat {
David Tolnaya454c8f2018-01-07 01:01:10 -0800802 /// A pattern that matches any value: `_`.
David Tolnay461d98e2018-01-07 11:07:19 -0800803 ///
804 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700805 pub Wild(PatWild {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800806 pub underscore_token: Token![_],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700807 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700808
David Tolnaya454c8f2018-01-07 01:01:10 -0800809 /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
David Tolnay461d98e2018-01-07 11:07:19 -0800810 ///
811 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700812 pub Ident(PatIdent {
David Tolnay24237fb2017-12-29 02:15:26 -0500813 pub by_ref: Option<Token![ref]>,
814 pub mutability: Option<Token![mut]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700815 pub ident: Ident,
David Tolnay8b4d3022017-12-29 12:11:10 -0500816 pub subpat: Option<(Token![@], Box<Pat>)>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700817 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700818
David Tolnaya454c8f2018-01-07 01:01:10 -0800819 /// A struct or struct variant pattern: `Variant { x, y, .. }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800820 ///
821 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700822 pub Struct(PatStruct {
823 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500824 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500825 pub fields: Punctuated<FieldPat, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800826 pub dot2_token: Option<Token![..]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700827 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700828
David Tolnaya454c8f2018-01-07 01:01:10 -0800829 /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800830 ///
831 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700832 pub TupleStruct(PatTupleStruct {
833 pub path: Path,
834 pub pat: PatTuple,
835 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700836
David Tolnaya454c8f2018-01-07 01:01:10 -0800837 /// A path pattern like `Color::Red`, optionally qualified with a
838 /// self-type.
839 ///
840 /// Unquailfied path patterns can legally refer to variants, structs,
841 /// constants or associated constants. Quailfied path patterns like
842 /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
843 /// associated constants.
David Tolnay461d98e2018-01-07 11:07:19 -0800844 ///
845 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700846 pub Path(PatPath {
847 pub qself: Option<QSelf>,
848 pub path: Path,
849 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700850
David Tolnaya454c8f2018-01-07 01:01:10 -0800851 /// A tuple pattern: `(a, b)`.
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 Tuple(PatTuple {
David Tolnay32954ef2017-12-26 22:43:16 -0500855 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500856 pub front: Punctuated<Pat, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500857 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500858 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500859 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700860 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800861
862 /// A box pattern: `box v`.
David Tolnay461d98e2018-01-07 11:07:19 -0800863 ///
864 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700865 pub Box(PatBox {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800866 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500867 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700868 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800869
870 /// A reference pattern: `&mut (first, second)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800871 ///
872 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700873 pub Ref(PatRef {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800874 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500875 pub mutability: Option<Token![mut]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500876 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700877 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800878
879 /// A literal pattern: `0`.
880 ///
881 /// This holds an `Expr` rather than a `Lit` because negative numbers
882 /// are represented as an `Expr::Unary`.
David Tolnay461d98e2018-01-07 11:07:19 -0800883 ///
884 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700885 pub Lit(PatLit {
886 pub expr: Box<Expr>,
887 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800888
889 /// A range pattern: `1..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800890 ///
891 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700892 pub Range(PatRange {
893 pub lo: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700894 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500895 pub hi: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700896 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800897
898 /// A dynamically sized slice pattern: `[a, b, i.., y, z]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800899 ///
900 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700901 pub Slice(PatSlice {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500902 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500903 pub front: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700904 pub middle: Option<Box<Pat>>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500905 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500906 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500907 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700908 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800909
910 /// A macro in expression position.
David Tolnay461d98e2018-01-07 11:07:19 -0800911 ///
912 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay323279a2017-12-29 11:26:32 -0500913 pub Macro(PatMacro {
914 pub mac: Macro,
915 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800916
917 /// Tokens in pattern position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800918 ///
919 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500920 pub Verbatim(PatVerbatim #manual_extra_traits {
921 pub tts: TokenStream,
922 }),
923 }
924}
925
David Tolnayc43b44e2017-12-30 23:55:54 -0500926#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500927impl Eq for PatVerbatim {}
928
David Tolnayc43b44e2017-12-30 23:55:54 -0500929#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500930impl PartialEq for PatVerbatim {
931 fn eq(&self, other: &Self) -> bool {
932 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
933 }
934}
935
David Tolnayc43b44e2017-12-30 23:55:54 -0500936#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500937impl Hash for PatVerbatim {
938 fn hash<H>(&self, state: &mut H)
939 where
940 H: Hasher,
941 {
942 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700943 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700944}
945
Michael Layzell734adb42017-06-07 16:58:31 -0400946#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700947ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800948 /// One arm of a `match` expression: `0...10 => { return true; }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700949 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800950 /// As in:
Alex Crichton62a0a592017-05-22 13:58:53 -0700951 ///
David Tolnaybcf26022017-12-25 22:10:52 -0500952 /// ```rust
David Tolnaya454c8f2018-01-07 01:01:10 -0800953 /// # fn f() -> bool {
David Tolnaybcf26022017-12-25 22:10:52 -0500954 /// # let n = 0;
Alex Crichton62a0a592017-05-22 13:58:53 -0700955 /// match n {
David Tolnaya454c8f2018-01-07 01:01:10 -0800956 /// 0...10 => {
957 /// return true;
958 /// }
959 /// // ...
David Tolnaybcf26022017-12-25 22:10:52 -0500960 /// # _ => {}
Alex Crichton62a0a592017-05-22 13:58:53 -0700961 /// }
David Tolnaya454c8f2018-01-07 01:01:10 -0800962 /// # false
David Tolnaybcf26022017-12-25 22:10:52 -0500963 /// # }
Alex Crichton62a0a592017-05-22 13:58:53 -0700964 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800965 ///
966 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700967 pub struct Arm {
968 pub attrs: Vec<Attribute>,
David Tolnay18cc4d42018-03-31 18:47:20 +0200969 pub leading_vert: Option<Token![|]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500970 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500971 pub guard: Option<(Token![if], Box<Expr>)>,
David Tolnaydfb91432018-03-31 19:19:44 +0200972 pub fat_arrow_token: Token![=>],
Alex Crichton62a0a592017-05-22 13:58:53 -0700973 pub body: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800974 pub comma: Option<Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700975 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700976}
977
Michael Layzell734adb42017-06-07 16:58:31 -0400978#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700979ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800980 /// Limit types of a range, inclusive or exclusive.
David Tolnay461d98e2018-01-07 11:07:19 -0800981 ///
982 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton2e0229c2017-05-23 09:34:50 -0700983 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700984 pub enum RangeLimits {
David Tolnaya454c8f2018-01-07 01:01:10 -0800985 /// Inclusive at the beginning, exclusive at the end.
David Tolnayf8db7ba2017-11-11 22:52:16 -0800986 HalfOpen(Token![..]),
David Tolnaya454c8f2018-01-07 01:01:10 -0800987 /// Inclusive at the beginning and end.
David Tolnaybe55d7b2017-12-17 23:41:20 -0800988 Closed(Token![..=]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700989 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700990}
991
Michael Layzell734adb42017-06-07 16:58:31 -0400992#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700993ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800994 /// A single field in a struct pattern.
Alex Crichton62a0a592017-05-22 13:58:53 -0700995 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800996 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
997 /// 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 -0800998 ///
999 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -07001000 pub struct FieldPat {
David Tolnay4a3f59a2017-12-28 21:21:12 -05001001 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -05001002 pub member: Member,
David Tolnay4a3f59a2017-12-28 21:21:12 -05001003 pub colon_token: Option<Token![:]>,
Alex Crichton62a0a592017-05-22 13:58:53 -07001004 pub pat: Box<Pat>,
Alex Crichton62a0a592017-05-22 13:58:53 -07001005 }
David Tolnayf4bbbd92016-09-23 14:41:55 -07001006}
1007
Michael Layzell3936ceb2017-07-08 00:28:36 -04001008#[cfg(any(feature = "parsing", feature = "printing"))]
1009#[cfg(feature = "full")]
Alex Crichton03b30272017-08-28 09:35:24 -07001010fn arm_expr_requires_comma(expr: &Expr) -> bool {
David Tolnay01218d12018-08-29 18:13:07 -07001011 // see https://github.com/rust-lang/rust/blob/eb8f2586e/src/libsyntax/parse/classify.rs#L17-L37
David Tolnay8c91b882017-12-28 23:04:32 -05001012 match *expr {
1013 Expr::Unsafe(..)
1014 | Expr::Block(..)
1015 | Expr::If(..)
1016 | Expr::IfLet(..)
1017 | Expr::Match(..)
1018 | Expr::While(..)
1019 | Expr::WhileLet(..)
1020 | Expr::Loop(..)
1021 | Expr::ForLoop(..)
David Tolnay02a9c6f2018-08-24 18:58:45 -04001022 | Expr::Async(..)
David Tolnayfb2dd4b2018-08-24 16:45:34 -04001023 | Expr::TryBlock(..) => false,
Alex Crichton03b30272017-08-28 09:35:24 -07001024 _ => true,
Michael Layzell3936ceb2017-07-08 00:28:36 -04001025 }
1026}
1027
David Tolnayb9c8e322016-09-23 20:48:37 -07001028#[cfg(feature = "parsing")]
1029pub mod parsing {
1030 use super::*;
David Tolnay60291082018-08-28 09:54:49 -07001031 use path;
David Tolnay2ccf32a2017-12-29 00:34:26 -05001032 #[cfg(feature = "full")]
David Tolnay056de302018-01-05 14:29:05 -08001033 use path::parsing::ty_no_eq_after;
David Tolnayb9c8e322016-09-23 20:48:37 -07001034
David Tolnay9389c382018-08-27 09:13:37 -07001035 use parse::{Parse, ParseStream, Result};
Michael Layzell734adb42017-06-07 16:58:31 -04001036 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001037 use synom::ext::IdentExt;
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001038
David Tolnay9389c382018-08-27 09:13:37 -07001039 macro_rules! named2 {
1040 ($name:ident ($($arg:ident : $argty:ty),*) -> $ret:ty, $($rest:tt)*) => {
1041 fn $name(input: ParseStream $(, $arg : $argty)*) -> Result<$ret> {
1042 named!(_synom ($($arg : $argty),*) -> $ret, $($rest)*);
1043 input.step_cursor(|cursor| _synom(*cursor $(, $arg)*))
1044 }
1045 };
1046 ($name:ident -> $ret:ty, $($rest:tt)*) => {
1047 fn $name(input: ParseStream) -> Result<$ret> {
1048 named!(_synom -> $ret, $($rest)*);
1049 input.step_cursor(|cursor| _synom(*cursor))
1050 }
1051 };
1052 }
1053
David Tolnaybcf26022017-12-25 22:10:52 -05001054 // When we're parsing expressions which occur before blocks, like in an if
1055 // statement's condition, we cannot parse a struct literal.
1056 //
1057 // Struct literals are ambiguous in certain positions
1058 // https://github.com/rust-lang/rfcs/pull/92
David Tolnay9389c382018-08-27 09:13:37 -07001059 #[derive(Copy, Clone)]
1060 pub struct AllowStruct(bool);
1061
1062 #[derive(Copy, Clone)]
1063 pub struct AllowBlock(bool);
David Tolnayaf2557e2016-10-24 11:52:21 -07001064
David Tolnay01218d12018-08-29 18:13:07 -07001065 #[derive(Copy, Clone, PartialEq, PartialOrd)]
1066 enum Precedence {
1067 Any,
1068 Assign,
1069 Placement,
1070 Range,
1071 Or,
1072 And,
1073 Compare,
1074 BitOr,
1075 BitXor,
1076 BitAnd,
1077 Shift,
1078 Arithmetic,
1079 Term,
1080 Cast,
1081 }
1082
1083 impl Precedence {
1084 fn of(op: &BinOp) -> Self {
1085 match *op {
1086 BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic,
1087 BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term,
1088 BinOp::And(_) => Precedence::And,
1089 BinOp::Or(_) => Precedence::Or,
1090 BinOp::BitXor(_) => Precedence::BitXor,
1091 BinOp::BitAnd(_) => Precedence::BitAnd,
1092 BinOp::BitOr(_) => Precedence::BitOr,
1093 BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
1094 BinOp::Eq(_) | BinOp::Lt(_) | BinOp::Le(_) | BinOp::Ne(_) | BinOp::Ge(_) | BinOp::Gt(_) => Precedence::Compare,
1095 BinOp::AddEq(_) | BinOp::SubEq(_) | BinOp::MulEq(_) | BinOp::DivEq(_) | BinOp::RemEq(_) | BinOp::BitXorEq(_) | BinOp::BitAndEq(_) | BinOp::BitOrEq(_) | BinOp::ShlEq(_) | BinOp::ShrEq(_) => Precedence::Assign,
1096 }
1097 }
1098 }
1099
David Tolnay9389c382018-08-27 09:13:37 -07001100 impl Parse for Expr {
1101 fn parse(input: ParseStream) -> Result<Self> {
1102 ambiguous_expr(input, AllowStruct(true), AllowBlock(true))
Alex Crichton954046c2017-05-30 21:49:42 -07001103 }
1104 }
1105
Michael Layzell734adb42017-06-07 16:58:31 -04001106 #[cfg(feature = "full")]
David Tolnay9fb0aed2018-08-27 10:23:12 -07001107 fn expr_no_struct(input: ParseStream) -> Result<Expr> {
1108 ambiguous_expr(input, AllowStruct(false), AllowBlock(true))
1109 }
David Tolnayaf2557e2016-10-24 11:52:21 -07001110
David Tolnay01218d12018-08-29 18:13:07 -07001111 #[cfg(feature = "full")]
1112 fn parse_expr(input: ParseStream, mut lhs: Expr, allow_struct: AllowStruct, allow_block: AllowBlock, base: Precedence) -> Result<Expr> {
1113 loop {
1114 if input.fork().parse::<BinOp>().ok().map_or(false, |op| Precedence::of(&op) >= base) {
1115 let op: BinOp = input.parse()?;
1116 let precedence = Precedence::of(&op);
1117 let mut rhs = unary_expr(input, allow_struct, allow_block)?;
1118 loop {
1119 let next = peek_precedence(input);
1120 if next > precedence || next == precedence && precedence == Precedence::Assign {
1121 rhs = parse_expr(input, rhs, allow_struct, allow_block, next)?;
1122 } else {
1123 break;
1124 }
1125 }
1126 lhs = Expr::Binary(ExprBinary {
1127 attrs: Vec::new(),
1128 left: Box::new(lhs),
1129 op: op,
1130 right: Box::new(rhs),
1131 });
1132 } else if Precedence::Assign >= base && input.peek(Token![=]) && !input.peek(Token![==]) && !input.peek(Token![=>]) {
1133 let eq_token: Token![=] = input.parse()?;
1134 let mut rhs = unary_expr(input, allow_struct, allow_block)?;
1135 loop {
1136 let next = peek_precedence(input);
1137 if next >= Precedence::Assign {
1138 rhs = parse_expr(input, rhs, allow_struct, allow_block, next)?;
1139 } else {
1140 break;
1141 }
1142 }
1143 lhs = Expr::Assign(ExprAssign {
1144 attrs: Vec::new(),
1145 left: Box::new(lhs),
1146 eq_token: eq_token,
1147 right: Box::new(rhs),
1148 });
1149 } else if Precedence::Placement >= base && input.peek(Token![<-]) {
1150 let arrow_token: Token![<-] = input.parse()?;
1151 let mut rhs = unary_expr(input, allow_struct, allow_block)?;
1152 loop {
1153 let next = peek_precedence(input);
1154 if next > Precedence::Placement {
1155 rhs = parse_expr(input, rhs, allow_struct, allow_block, next)?;
1156 } else {
1157 break;
1158 }
1159 }
1160 lhs = Expr::InPlace(ExprInPlace {
1161 attrs: Vec::new(),
1162 place: Box::new(lhs),
1163 arrow_token: arrow_token,
1164 value: Box::new(rhs),
1165 });
1166 } else if Precedence::Range >= base && input.peek(Token![..]) {
1167 let limits: RangeLimits = input.parse()?;
1168 let rhs = if input.is_empty()
1169 || input.peek(Token![,])
1170 || input.peek(Token![;])
1171 || !allow_struct.0 && input.peek(token::Brace)
1172 {
1173 None
1174 } else {
1175 // We don't want to allow blocks in the rhs if we don't
1176 // allow structs.
1177 let allow_block = AllowBlock(allow_struct.0);
1178 let mut rhs = unary_expr(input, allow_struct, allow_block)?;
1179 loop {
1180 let next = peek_precedence(input);
1181 if next > Precedence::Range {
1182 rhs = parse_expr(input, rhs, allow_struct, allow_block, next)?;
1183 } else {
1184 break;
1185 }
1186 }
1187 Some(rhs)
1188 };
1189 lhs = Expr::Range(ExprRange {
1190 attrs: Vec::new(),
1191 from: Some(Box::new(lhs)),
1192 limits: limits,
1193 to: rhs.map(Box::new),
1194 });
1195 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1196 let as_token: Token![as] = input.parse()?;
1197 let ty = input.call(Type::without_plus)?;
1198 lhs = Expr::Cast(ExprCast {
1199 attrs: Vec::new(),
1200 expr: Box::new(lhs),
1201 as_token: as_token,
1202 ty: Box::new(ty),
1203 });
1204 } else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) {
1205 let colon_token: Token![:] = input.parse()?;
1206 let ty = input.call(Type::without_plus)?;
1207 lhs = Expr::Type(ExprType {
1208 attrs: Vec::new(),
1209 expr: Box::new(lhs),
1210 colon_token: colon_token,
1211 ty: Box::new(ty),
1212 });
1213 } else {
1214 break;
1215 }
1216 }
1217 Ok(lhs)
1218 }
1219
1220 #[cfg(feature = "full")]
1221 fn peek_precedence(input: ParseStream) -> Precedence {
1222 if let Ok(op) = input.fork().parse() {
1223 Precedence::of(&op)
1224 } else if input.peek(Token![=]) && !input.peek(Token![==]) && !input.peek(Token![=>]) {
1225 Precedence::Assign
1226 } else if input.peek(Token![<-]) {
1227 Precedence::Placement
1228 } else if input.peek(Token![..]) {
1229 Precedence::Range
1230 } else if input.peek(Token![as]) || input.peek(Token![:]) && !input.peek(Token![::]) {
1231 Precedence::Cast
1232 } else {
1233 Precedence::Any
1234 }
1235 }
1236
David Tolnaybcf26022017-12-25 22:10:52 -05001237 // Parse an arbitrary expression.
Michael Layzell734adb42017-06-07 16:58:31 -04001238 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001239 fn ambiguous_expr(
1240 input: ParseStream,
1241 allow_struct: AllowStruct,
1242 allow_block: AllowBlock,
1243 ) -> Result<Expr> {
David Tolnay01218d12018-08-29 18:13:07 -07001244 //assign_expr(input, allow_struct, allow_block)
1245 let lhs = unary_expr(input, allow_struct, allow_block)?;
1246 parse_expr(input, lhs, allow_struct, allow_block, Precedence::Any)
Michael Layzellb78f3b52017-06-04 19:03:03 -04001247 }
1248
Michael Layzell734adb42017-06-07 16:58:31 -04001249 #[cfg(not(feature = "full"))]
David Tolnay60291082018-08-28 09:54:49 -07001250 fn ambiguous_expr(
1251 input: ParseStream,
1252 allow_struct: AllowStruct,
1253 allow_block: AllowBlock,
1254 ) -> Result<Expr> {
David Tolnay8c91b882017-12-28 23:04:32 -05001255 // NOTE: We intentionally skip assign_expr, placement_expr, and
David Tolnay9389c382018-08-27 09:13:37 -07001256 // range_expr as they are only parsed in full mode.
1257 or_expr(input, allow_struct, allow_block)
Michael Layzell734adb42017-06-07 16:58:31 -04001258 }
1259
David Tolnaybcf26022017-12-25 22:10:52 -05001260 // <UnOp> <trailer>
1261 // & <trailer>
1262 // &mut <trailer>
1263 // box <trailer>
Michael Layzell734adb42017-06-07 16:58:31 -04001264 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001265 fn unary_expr(
1266 input: ParseStream,
1267 allow_struct: AllowStruct,
1268 allow_block: AllowBlock,
1269 ) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001270 let ahead = input.fork();
1271 ahead.call(Attribute::parse_outer)?;
1272 if ahead.peek(Token![&])
1273 || ahead.peek(Token![box])
1274 || ahead.peek(Token![*])
1275 || ahead.peek(Token![!])
1276 || ahead.peek(Token![-])
1277 {
1278 let attrs = input.call(Attribute::parse_outer)?;
1279 if input.peek(Token![&]) {
1280 Ok(Expr::Reference(ExprReference {
1281 attrs: attrs,
1282 and_token: input.parse()?,
1283 mutability: input.parse()?,
1284 expr: Box::new(unary_expr(input, allow_struct, AllowBlock(true))?),
1285 }))
1286 } else if input.peek(Token![box]) {
1287 Ok(Expr::Box(ExprBox {
1288 attrs: attrs,
1289 box_token: input.parse()?,
1290 expr: Box::new(unary_expr(input, allow_struct, AllowBlock(true))?),
1291 }))
1292 } else {
1293 Ok(Expr::Unary(ExprUnary {
1294 attrs: attrs,
1295 op: input.parse()?,
1296 expr: Box::new(unary_expr(input, allow_struct, AllowBlock(true))?),
1297 }))
1298 }
1299 } else {
1300 trailer_expr(input, allow_struct, allow_block)
1301 }
1302 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001303
Michael Layzell734adb42017-06-07 16:58:31 -04001304 // XXX: This duplication is ugly
1305 #[cfg(not(feature = "full"))]
David Tolnay60291082018-08-28 09:54:49 -07001306 fn unary_expr(
1307 input: ParseStream,
1308 allow_struct: AllowStruct,
1309 allow_block: AllowBlock,
1310 ) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001311 let ahead = input.fork();
1312 ahead.call(Attribute::parse_outer)?;
1313 if ahead.peek(Token![*]) || ahead.peek(Token![!]) || ahead.peek(Token![-]) {
1314 Ok(Expr::Unary(ExprUnary {
1315 attrs: input.call(Attribute::parse_outer)?,
1316 op: input.parse()?,
1317 expr: Box::new(unary_expr(input, allow_struct, AllowBlock(true))?),
1318 }))
1319 } else {
1320 trailer_expr(input, allow_struct, allow_block)
1321 }
1322 }
Michael Layzell734adb42017-06-07 16:58:31 -04001323
David Tolnayd997aef2018-07-21 18:42:31 -07001324 #[cfg(feature = "full")]
David Tolnay5d314dc2018-07-21 16:40:01 -07001325 fn take_outer(attrs: &mut Vec<Attribute>) -> Vec<Attribute> {
1326 let mut outer = Vec::new();
1327 let mut inner = Vec::new();
1328 for attr in mem::replace(attrs, Vec::new()) {
1329 match attr.style {
1330 AttrStyle::Outer => outer.push(attr),
1331 AttrStyle::Inner(_) => inner.push(attr),
1332 }
1333 }
1334 *attrs = inner;
1335 outer
1336 }
1337
David Tolnaybcf26022017-12-25 22:10:52 -05001338 // <atom> (..<args>) ...
1339 // <atom> . <ident> (..<args>) ...
1340 // <atom> . <ident> ...
1341 // <atom> . <lit> ...
1342 // <atom> [ <expr> ] ...
1343 // <atom> ? ...
Michael Layzell734adb42017-06-07 16:58:31 -04001344 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001345 fn trailer_expr(
1346 input: ParseStream,
1347 allow_struct: AllowStruct,
1348 allow_block: AllowBlock,
1349 ) -> Result<Expr> {
David Tolnay1501f7e2018-08-27 14:21:03 -07001350 let mut e = atom_expr(input, allow_struct, allow_block)?;
1351
1352 let mut attrs = e.replace_attrs(Vec::new());
1353 let outer_attrs = take_outer(&mut attrs);
1354 e.replace_attrs(attrs);
1355
David Tolnay01218d12018-08-29 18:13:07 -07001356 e = trailer_helper(input, e)?;
1357
1358 let mut attrs = outer_attrs;
1359 attrs.extend(e.replace_attrs(Vec::new()));
1360 e.replace_attrs(attrs);
1361 Ok(e)
1362 }
1363
1364 #[cfg(feature = "full")]
1365 fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
David Tolnay1501f7e2018-08-27 14:21:03 -07001366 loop {
1367 if input.peek(token::Paren) {
1368 let content;
1369 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001370 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001371 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001372 paren_token: parenthesized!(content in input),
1373 args: content.parse_terminated(<Expr as Parse>::parse)?,
1374 });
1375 } else if input.peek(Token![.]) && !input.peek(Token![..]) {
1376 let dot_token: Token![.] = input.parse()?;
1377 let member: Member = input.parse()?;
1378 let turbofish = if member.is_named() && input.peek(Token![::]) {
1379 Some(MethodTurbofish {
1380 colon2_token: input.parse()?,
1381 lt_token: input.parse()?,
1382 args: {
1383 let mut args = Punctuated::new();
1384 loop {
1385 if input.peek(Token![>]) {
1386 break;
1387 }
1388 let value = input.parse()?;
1389 args.push_value(value);
1390 if input.peek(Token![>]) {
1391 break;
1392 }
1393 let punct = input.parse()?;
1394 args.push_punct(punct);
1395 }
1396 args
1397 },
1398 gt_token: input.parse()?,
1399 })
1400 } else {
1401 None
1402 };
1403
1404 if turbofish.is_some() || input.peek(token::Paren) {
1405 if let Member::Named(method) = member {
1406 let content;
1407 e = Expr::MethodCall(ExprMethodCall {
1408 attrs: Vec::new(),
1409 receiver: Box::new(e),
1410 dot_token: dot_token,
1411 method: method,
1412 turbofish: turbofish,
1413 paren_token: parenthesized!(content in input),
1414 args: content.parse_terminated(<Expr as Parse>::parse)?,
1415 });
1416 continue;
1417 }
1418 }
1419
1420 e = Expr::Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -05001421 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001422 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001423 dot_token: dot_token,
David Tolnay85b69a42017-12-27 20:43:10 -05001424 member: member,
David Tolnay1501f7e2018-08-27 14:21:03 -07001425 });
1426 } else if input.peek(token::Bracket) {
1427 let content;
1428 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001429 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001430 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001431 bracket_token: bracketed!(content in input),
1432 index: content.parse()?,
1433 });
1434 } else if input.peek(Token![?]) {
1435 e = Expr::Try(ExprTry {
David Tolnay8c91b882017-12-28 23:04:32 -05001436 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001437 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001438 question_token: input.parse()?,
1439 });
1440 } else {
1441 break;
1442 }
1443 }
David Tolnay1501f7e2018-08-27 14:21:03 -07001444 Ok(e)
1445 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001446
Michael Layzell734adb42017-06-07 16:58:31 -04001447 // XXX: Duplication == ugly
1448 #[cfg(not(feature = "full"))]
David Tolnay60291082018-08-28 09:54:49 -07001449 fn trailer_expr(
1450 input: ParseStream,
1451 allow_struct: AllowStruct,
1452 allow_block: AllowBlock,
1453 ) -> Result<Expr> {
David Tolnay1501f7e2018-08-27 14:21:03 -07001454 let mut e = atom_expr(input, allow_struct, allow_block)?;
1455
1456 loop {
1457 if input.peek(token::Paren) {
1458 let content;
1459 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001460 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001461 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001462 paren_token: parenthesized!(content in input),
1463 args: content.parse_terminated(<Expr as Parse>::parse)?,
1464 });
1465 } else if input.peek(Token![.]) {
1466 e = Expr::Field(ExprField {
David Tolnayd5147742018-06-30 10:09:52 -07001467 attrs: Vec::new(),
1468 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001469 dot_token: input.parse()?,
1470 member: input.parse()?,
1471 });
1472 } else if input.peek(token::Bracket) {
1473 let content;
1474 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001475 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001476 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001477 bracket_token: bracketed!(content in input),
1478 index: content.parse()?,
1479 });
1480 } else {
1481 break;
1482 }
1483 }
1484
1485 Ok(e)
1486 }
Michael Layzell734adb42017-06-07 16:58:31 -04001487
David Tolnaya454c8f2018-01-07 01:01:10 -08001488 // Parse all atomic expressions which don't have to worry about precedence
David Tolnaybcf26022017-12-25 22:10:52 -05001489 // interactions, as they are fully contained.
Michael Layzell734adb42017-06-07 16:58:31 -04001490 #[cfg(feature = "full")]
David Tolnay9389c382018-08-27 09:13:37 -07001491 named2!(atom_expr(allow_struct: AllowStruct, allow_block: AllowBlock) -> Expr, alt!(
David Tolnay8c91b882017-12-28 23:04:32 -05001492 syn!(ExprGroup) => { Expr::Group } // must be placed first
Michael Layzell93c36282017-06-04 20:43:14 -04001493 |
David Tolnay8c91b882017-12-28 23:04:32 -05001494 syn!(ExprLit) => { Expr::Lit } // must be before expr_struct
Michael Layzellb78f3b52017-06-04 19:03:03 -04001495 |
Yusuke Sasaki851062f2018-08-01 06:28:28 +09001496 // must be before ExprStruct
David Tolnay02a9c6f2018-08-24 18:58:45 -04001497 syn!(ExprAsync) => { Expr::Async }
Yusuke Sasaki851062f2018-08-01 06:28:28 +09001498 |
David Tolnayf7177052018-08-24 15:31:50 -04001499 // must be before ExprStruct
David Tolnayfb2dd4b2018-08-24 16:45:34 -04001500 syn!(ExprTryBlock) => { Expr::TryBlock }
David Tolnayf7177052018-08-24 15:31:50 -04001501 |
Michael Layzellb78f3b52017-06-04 19:03:03 -04001502 // must be before expr_path
David Tolnay9389c382018-08-27 09:13:37 -07001503 cond_reduce!(allow_struct.0, syn!(ExprStruct)) => { Expr::Struct }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001504 |
David Tolnay8c91b882017-12-28 23:04:32 -05001505 syn!(ExprParen) => { Expr::Paren } // must be before expr_tup
Michael Layzellb78f3b52017-06-04 19:03:03 -04001506 |
David Tolnay8c91b882017-12-28 23:04:32 -05001507 syn!(ExprMacro) => { Expr::Macro } // must be before expr_path
Michael Layzellb78f3b52017-06-04 19:03:03 -04001508 |
David Tolnay60291082018-08-28 09:54:49 -07001509 shim!(expr_break, allow_struct) => { Expr::Break } // must be before expr_path
Michael Layzellb78f3b52017-06-04 19:03:03 -04001510 |
David Tolnay8c91b882017-12-28 23:04:32 -05001511 syn!(ExprContinue) => { Expr::Continue } // must be before expr_path
Michael Layzellb78f3b52017-06-04 19:03:03 -04001512 |
David Tolnay60291082018-08-28 09:54:49 -07001513 shim!(expr_ret, allow_struct) => { Expr::Return } // must be before expr_path
Michael Layzellb78f3b52017-06-04 19:03:03 -04001514 |
David Tolnay8c91b882017-12-28 23:04:32 -05001515 syn!(ExprArray) => { Expr::Array }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001516 |
David Tolnay8c91b882017-12-28 23:04:32 -05001517 syn!(ExprTuple) => { Expr::Tuple }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001518 |
David Tolnay8c91b882017-12-28 23:04:32 -05001519 syn!(ExprIf) => { Expr::If }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001520 |
David Tolnay8c91b882017-12-28 23:04:32 -05001521 syn!(ExprIfLet) => { Expr::IfLet }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001522 |
David Tolnay8c91b882017-12-28 23:04:32 -05001523 syn!(ExprWhile) => { Expr::While }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001524 |
David Tolnay8c91b882017-12-28 23:04:32 -05001525 syn!(ExprWhileLet) => { Expr::WhileLet }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001526 |
David Tolnay8c91b882017-12-28 23:04:32 -05001527 syn!(ExprForLoop) => { Expr::ForLoop }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001528 |
David Tolnay8c91b882017-12-28 23:04:32 -05001529 syn!(ExprLoop) => { Expr::Loop }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001530 |
David Tolnay8c91b882017-12-28 23:04:32 -05001531 syn!(ExprMatch) => { Expr::Match }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001532 |
David Tolnay8c91b882017-12-28 23:04:32 -05001533 syn!(ExprYield) => { Expr::Yield }
Alex Crichtonfe110462017-06-01 12:49:27 -07001534 |
David Tolnay8c91b882017-12-28 23:04:32 -05001535 syn!(ExprUnsafe) => { Expr::Unsafe }
Nika Layzell640832a2017-12-04 13:37:09 -05001536 |
David Tolnay60291082018-08-28 09:54:49 -07001537 shim!(expr_closure, allow_struct) => { Expr::Closure }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001538 |
David Tolnay9389c382018-08-27 09:13:37 -07001539 cond_reduce!(allow_block.0, syn!(ExprBlock)) => { Expr::Block }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001540 |
1541 // NOTE: This is the prefix-form of range
David Tolnay60291082018-08-28 09:54:49 -07001542 shim!(expr_range, allow_struct) => { Expr::Range }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001543 |
David Tolnay8c91b882017-12-28 23:04:32 -05001544 syn!(ExprPath) => { Expr::Path }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001545 |
David Tolnay8c91b882017-12-28 23:04:32 -05001546 syn!(ExprRepeat) => { Expr::Repeat }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001547 ));
1548
Michael Layzell734adb42017-06-07 16:58:31 -04001549 #[cfg(not(feature = "full"))]
David Tolnay9389c382018-08-27 09:13:37 -07001550 named2!(atom_expr(_allow_struct: AllowStruct, _allow_block: AllowBlock) -> Expr, alt!(
David Tolnaye98775f2017-12-28 23:17:00 -05001551 syn!(ExprLit) => { Expr::Lit }
Michael Layzell734adb42017-06-07 16:58:31 -04001552 |
David Tolnay9374bc02018-01-27 18:49:36 -08001553 syn!(ExprParen) => { Expr::Paren }
1554 |
David Tolnay8c91b882017-12-28 23:04:32 -05001555 syn!(ExprPath) => { Expr::Path }
Michael Layzell734adb42017-06-07 16:58:31 -04001556 ));
1557
Michael Layzell734adb42017-06-07 16:58:31 -04001558 #[cfg(feature = "full")]
David Tolnay01218d12018-08-29 18:13:07 -07001559 fn expr_early(input: ParseStream) -> Result<Expr> {
1560 let mut attrs = input.call(Attribute::parse_outer)?;
1561 let mut expr = if input.peek(Token![if]) {
1562 if input.peek2(Token![let]) {
1563 Expr::IfLet(input.parse()?)
1564 } else {
1565 Expr::If(input.parse()?)
1566 }
1567 } else if input.peek(Token![while]) {
1568 if input.peek2(Token![let]) {
1569 Expr::WhileLet(input.parse()?)
1570 } else {
1571 Expr::While(input.parse()?)
1572 }
1573 } else if input.peek(Token![for]) {
1574 Expr::ForLoop(input.parse()?)
1575 } else if input.peek(Token![loop]) {
1576 Expr::Loop(input.parse()?)
1577 } else if input.peek(Token![match]) {
1578 Expr::Match(input.parse()?)
1579 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
1580 Expr::TryBlock(input.parse()?)
1581 } else if input.peek(Token![unsafe]) {
1582 Expr::Unsafe(input.parse()?)
1583 } else if input.peek(token::Brace) {
1584 Expr::Block(input.parse()?)
1585 } else {
1586 let allow_struct = AllowStruct(true);
1587 let allow_block = AllowBlock(true);
1588 let mut expr = unary_expr(input, allow_struct, allow_block)?;
1589
1590 attrs.extend(expr.replace_attrs(Vec::new()));
1591 expr.replace_attrs(attrs);
1592
1593 return parse_expr(input, expr, allow_struct, allow_block, Precedence::Any);
1594 };
1595
1596 if input.peek(Token![.]) || input.peek(Token![?]) {
1597 expr = trailer_helper(input, expr)?;
1598
1599 attrs.extend(expr.replace_attrs(Vec::new()));
1600 expr.replace_attrs(attrs);
1601
1602 let allow_struct = AllowStruct(true);
1603 let allow_block = AllowBlock(true);
1604 return parse_expr(input, expr, allow_struct, allow_block, Precedence::Any);
1605 }
1606
1607 attrs.extend(expr.replace_attrs(Vec::new()));
1608 expr.replace_attrs(attrs);
1609 Ok(expr)
1610 }
Michael Layzell35418782017-06-07 09:20:25 -04001611
David Tolnay60291082018-08-28 09:54:49 -07001612 impl Parse for ExprLit {
David Tolnayeb981bb2018-07-21 19:31:38 -07001613 #[cfg(not(feature = "full"))]
David Tolnay60291082018-08-28 09:54:49 -07001614 fn parse(input: ParseStream) -> Result<Self> {
1615 Ok(ExprLit {
David Tolnayeb981bb2018-07-21 19:31:38 -07001616 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07001617 lit: input.parse()?,
David Tolnayeb981bb2018-07-21 19:31:38 -07001618 })
David Tolnay60291082018-08-28 09:54:49 -07001619 }
David Tolnayeb981bb2018-07-21 19:31:38 -07001620
1621 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001622 fn parse(input: ParseStream) -> Result<Self> {
1623 Ok(ExprLit {
1624 attrs: input.call(Attribute::parse_outer)?,
1625 lit: input.parse()?,
David Tolnay8c91b882017-12-28 23:04:32 -05001626 })
David Tolnay60291082018-08-28 09:54:49 -07001627 }
David Tolnay8c91b882017-12-28 23:04:32 -05001628 }
1629
1630 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001631 impl Parse for ExprMacro {
1632 fn parse(input: ParseStream) -> Result<Self> {
1633 Ok(ExprMacro {
1634 attrs: input.call(Attribute::parse_outer)?,
1635 mac: input.parse()?,
David Tolnay8c91b882017-12-28 23:04:32 -05001636 })
David Tolnay60291082018-08-28 09:54:49 -07001637 }
David Tolnay8c91b882017-12-28 23:04:32 -05001638 }
1639
David Tolnaye98775f2017-12-28 23:17:00 -05001640 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001641 impl Parse for ExprGroup {
1642 fn parse(input: ParseStream) -> Result<Self> {
1643 let content;
1644 Ok(ExprGroup {
David Tolnay8c91b882017-12-28 23:04:32 -05001645 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07001646 group_token: grouped!(content in input),
1647 expr: content.parse()?,
David Tolnaybb4ca9f2017-12-26 12:28:58 -05001648 })
David Tolnay60291082018-08-28 09:54:49 -07001649 }
Michael Layzell93c36282017-06-04 20:43:14 -04001650 }
1651
David Tolnay60291082018-08-28 09:54:49 -07001652 impl Parse for ExprParen {
David Tolnayeb981bb2018-07-21 19:31:38 -07001653 #[cfg(not(feature = "full"))]
David Tolnay60291082018-08-28 09:54:49 -07001654 fn parse(input: ParseStream) -> Result<Self> {
1655 let content;
1656 Ok(ExprParen {
David Tolnayeb981bb2018-07-21 19:31:38 -07001657 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07001658 paren_token: parenthesized!(content in input),
1659 expr: content.parse()?,
David Tolnayeb981bb2018-07-21 19:31:38 -07001660 })
David Tolnay60291082018-08-28 09:54:49 -07001661 }
David Tolnayeb981bb2018-07-21 19:31:38 -07001662
1663 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001664 fn parse(input: ParseStream) -> Result<Self> {
1665 let outer_attrs = input.call(Attribute::parse_outer)?;
1666
1667 let content;
1668 let paren_token = parenthesized!(content in input);
1669 let inner_attrs = content.call(Attribute::parse_inner)?;
1670 let expr: Expr = content.parse()?;
1671
1672 Ok(ExprParen {
David Tolnay5d314dc2018-07-21 16:40:01 -07001673 attrs: {
1674 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07001675 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07001676 attrs
1677 },
David Tolnay60291082018-08-28 09:54:49 -07001678 paren_token: paren_token,
1679 expr: Box::new(expr),
David Tolnaybb4ca9f2017-12-26 12:28:58 -05001680 })
David Tolnay60291082018-08-28 09:54:49 -07001681 }
Alex Crichton954046c2017-05-30 21:49:42 -07001682 }
David Tolnay89e05672016-10-02 14:39:42 -07001683
Michael Layzell734adb42017-06-07 16:58:31 -04001684 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001685 impl Parse for ExprArray {
1686 fn parse(input: ParseStream) -> Result<Self> {
1687 let outer_attrs = input.call(Attribute::parse_outer)?;
1688
1689 let content;
1690 let bracket_token = bracketed!(content in input);
1691 let inner_attrs = content.call(Attribute::parse_inner)?;
1692 let elems = content.parse_terminated(<Expr as Parse>::parse)?;
1693
1694 Ok(ExprArray {
David Tolnay5d314dc2018-07-21 16:40:01 -07001695 attrs: {
1696 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07001697 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07001698 attrs
1699 },
David Tolnay60291082018-08-28 09:54:49 -07001700 bracket_token: bracket_token,
1701 elems: elems,
Michael Layzell92639a52017-06-01 00:07:44 -04001702 })
David Tolnay60291082018-08-28 09:54:49 -07001703 }
Alex Crichton954046c2017-05-30 21:49:42 -07001704 }
David Tolnayfa0edf22016-09-23 22:58:24 -07001705
Michael Layzell734adb42017-06-07 16:58:31 -04001706 #[cfg(feature = "full")]
David Tolnay1501f7e2018-08-27 14:21:03 -07001707 impl Parse for GenericMethodArgument {
David Tolnayd60cfec2017-12-29 00:21:38 -05001708 // TODO parse const generics as well
David Tolnay1501f7e2018-08-27 14:21:03 -07001709 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay60291082018-08-28 09:54:49 -07001710 input
1711 .parse_synom(ty_no_eq_after)
1712 .map(GenericMethodArgument::Type)
David Tolnay1501f7e2018-08-27 14:21:03 -07001713 }
David Tolnayd60cfec2017-12-29 00:21:38 -05001714 }
1715
1716 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001717 impl Parse for ExprTuple {
1718 fn parse(input: ParseStream) -> Result<Self> {
1719 let outer_attrs = input.call(Attribute::parse_outer)?;
1720
1721 let content;
1722 let paren_token = parenthesized!(content in input);
1723 let inner_attrs = content.call(Attribute::parse_inner)?;
1724 let elems = content.parse_terminated(<Expr as Parse>::parse)?;
1725
1726 Ok(ExprTuple {
David Tolnay5d314dc2018-07-21 16:40:01 -07001727 attrs: {
1728 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07001729 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07001730 attrs
1731 },
David Tolnay60291082018-08-28 09:54:49 -07001732 paren_token: paren_token,
1733 elems: elems,
Michael Layzell92639a52017-06-01 00:07:44 -04001734 })
David Tolnay60291082018-08-28 09:54:49 -07001735 }
Alex Crichton954046c2017-05-30 21:49:42 -07001736 }
David Tolnayfa0edf22016-09-23 22:58:24 -07001737
Michael Layzell734adb42017-06-07 16:58:31 -04001738 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001739 impl Parse for ExprIfLet {
1740 fn parse(input: ParseStream) -> Result<Self> {
1741 Ok(ExprIfLet {
David Tolnay8c91b882017-12-28 23:04:32 -05001742 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07001743 if_token: input.parse()?,
1744 let_token: input.parse()?,
1745 pats: {
1746 let mut pats = Punctuated::new();
1747 let value: Pat = input.parse()?;
1748 pats.push_value(value);
1749 while input.peek(Token![|])
1750 && !input.peek(Token![||])
1751 && !input.peek(Token![|=])
1752 {
1753 let punct = input.parse()?;
1754 pats.push_punct(punct);
1755 let value: Pat = input.parse()?;
1756 pats.push_value(value);
1757 }
1758 pats
Michael Layzell92639a52017-06-01 00:07:44 -04001759 },
David Tolnay60291082018-08-28 09:54:49 -07001760 eq_token: input.parse()?,
1761 expr: Box::new(input.call(expr_no_struct)?),
1762 then_branch: input.parse()?,
1763 else_branch: {
1764 if input.peek(Token![else]) {
1765 Some(input.call(else_block)?)
1766 } else {
1767 None
1768 }
1769 },
Michael Layzell92639a52017-06-01 00:07:44 -04001770 })
David Tolnay60291082018-08-28 09:54:49 -07001771 }
David Tolnay29f9ce12016-10-02 20:58:40 -07001772 }
1773
Michael Layzell734adb42017-06-07 16:58:31 -04001774 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001775 impl Parse for ExprIf {
1776 fn parse(input: ParseStream) -> Result<Self> {
1777 Ok(ExprIf {
David Tolnay8c91b882017-12-28 23:04:32 -05001778 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07001779 if_token: input.parse()?,
1780 cond: Box::new(input.call(expr_no_struct)?),
1781 then_branch: input.parse()?,
1782 else_branch: {
1783 if input.peek(Token![else]) {
1784 Some(input.call(else_block)?)
1785 } else {
1786 None
1787 }
Michael Layzell92639a52017-06-01 00:07:44 -04001788 },
Michael Layzell92639a52017-06-01 00:07:44 -04001789 })
David Tolnay60291082018-08-28 09:54:49 -07001790 }
Alex Crichton954046c2017-05-30 21:49:42 -07001791 }
David Tolnaybb6feae2016-10-02 21:25:20 -07001792
Michael Layzell734adb42017-06-07 16:58:31 -04001793 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001794 fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
1795 let else_token: Token![else] = input.parse()?;
1796
1797 let lookahead = input.lookahead1();
1798 let else_branch = if input.peek(Token![if]) {
1799 if input.peek2(Token![let]) {
1800 input.parse().map(Expr::IfLet)?
1801 } else {
1802 input.parse().map(Expr::If)?
1803 }
1804 } else if input.peek(token::Brace) {
1805 Expr::Block(ExprBlock {
1806 attrs: Vec::new(),
1807 label: None,
1808 block: input.parse()?,
1809 })
1810 } else {
1811 return Err(lookahead.error());
1812 };
1813
1814 Ok((else_token, Box::new(else_branch)))
1815 }
David Tolnay939766a2016-09-23 23:48:12 -07001816
Michael Layzell734adb42017-06-07 16:58:31 -04001817 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001818 impl Parse for ExprForLoop {
1819 fn parse(input: ParseStream) -> Result<Self> {
1820 let outer_attrs = input.call(Attribute::parse_outer)?;
1821 let label: Option<Label> = input.parse()?;
1822 let for_token: Token![for] = input.parse()?;
1823 let pat: Pat = input.parse()?;
1824 let in_token: Token![in] = input.parse()?;
1825 let expr: Expr = input.call(expr_no_struct)?;
1826
1827 let content;
1828 let brace_token = braced!(content in input);
1829 let inner_attrs = content.call(Attribute::parse_inner)?;
1830 let stmts = content.call(Block::parse_within)?;
1831
1832 Ok(ExprForLoop {
David Tolnay5d314dc2018-07-21 16:40:01 -07001833 attrs: {
1834 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07001835 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07001836 attrs
1837 },
David Tolnaybcd498f2017-12-29 12:02:33 -05001838 label: label,
David Tolnay60291082018-08-28 09:54:49 -07001839 for_token: for_token,
David Tolnay5d314dc2018-07-21 16:40:01 -07001840 pat: Box::new(pat),
David Tolnay60291082018-08-28 09:54:49 -07001841 in_token: in_token,
David Tolnay5d314dc2018-07-21 16:40:01 -07001842 expr: Box::new(expr),
1843 body: Block {
David Tolnay60291082018-08-28 09:54:49 -07001844 brace_token: brace_token,
1845 stmts: stmts,
David Tolnay5d314dc2018-07-21 16:40:01 -07001846 },
Michael Layzell92639a52017-06-01 00:07:44 -04001847 })
David Tolnay60291082018-08-28 09:54:49 -07001848 }
Alex Crichton954046c2017-05-30 21:49:42 -07001849 }
Gregory Katze5f35682016-09-27 14:20:55 -04001850
Michael Layzell734adb42017-06-07 16:58:31 -04001851 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001852 impl Parse for ExprLoop {
1853 fn parse(input: ParseStream) -> Result<Self> {
1854 let outer_attrs = input.call(Attribute::parse_outer)?;
1855 let label: Option<Label> = input.parse()?;
1856 let loop_token: Token![loop] = input.parse()?;
1857
1858 let content;
1859 let brace_token = braced!(content in input);
1860 let inner_attrs = content.call(Attribute::parse_inner)?;
1861 let stmts = content.call(Block::parse_within)?;
1862
1863 Ok(ExprLoop {
David Tolnay5d314dc2018-07-21 16:40:01 -07001864 attrs: {
1865 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07001866 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07001867 attrs
1868 },
David Tolnaybcd498f2017-12-29 12:02:33 -05001869 label: label,
David Tolnay60291082018-08-28 09:54:49 -07001870 loop_token: loop_token,
David Tolnay5d314dc2018-07-21 16:40:01 -07001871 body: Block {
David Tolnay60291082018-08-28 09:54:49 -07001872 brace_token: brace_token,
1873 stmts: stmts,
David Tolnay5d314dc2018-07-21 16:40:01 -07001874 },
Michael Layzell92639a52017-06-01 00:07:44 -04001875 })
David Tolnay60291082018-08-28 09:54:49 -07001876 }
Alex Crichton954046c2017-05-30 21:49:42 -07001877 }
1878
Michael Layzell734adb42017-06-07 16:58:31 -04001879 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001880 impl Parse for ExprMatch {
1881 fn parse(input: ParseStream) -> Result<Self> {
1882 let outer_attrs = input.call(Attribute::parse_outer)?;
1883 let match_token: Token![match] = input.parse()?;
1884 let expr = expr_no_struct(input)?;
1885
1886 let content;
1887 let brace_token = braced!(content in input);
1888 let inner_attrs = content.call(Attribute::parse_inner)?;
1889
1890 let mut arms = Vec::new();
1891 while !content.is_empty() {
1892 arms.push(content.parse()?);
1893 }
1894
1895 Ok(ExprMatch {
David Tolnay5d314dc2018-07-21 16:40:01 -07001896 attrs: {
1897 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07001898 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07001899 attrs
1900 },
David Tolnay60291082018-08-28 09:54:49 -07001901 match_token: match_token,
1902 expr: Box::new(expr),
1903 brace_token: brace_token,
1904 arms: arms,
Michael Layzell92639a52017-06-01 00:07:44 -04001905 })
David Tolnay60291082018-08-28 09:54:49 -07001906 }
Alex Crichton954046c2017-05-30 21:49:42 -07001907 }
David Tolnay1978c672016-10-27 22:05:52 -07001908
Michael Layzell734adb42017-06-07 16:58:31 -04001909 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001910 impl Parse for ExprTryBlock {
1911 fn parse(input: ParseStream) -> Result<Self> {
1912 Ok(ExprTryBlock {
David Tolnay8c91b882017-12-28 23:04:32 -05001913 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07001914 try_token: input.parse()?,
1915 block: input.parse()?,
David Tolnaybb4ca9f2017-12-26 12:28:58 -05001916 })
David Tolnay60291082018-08-28 09:54:49 -07001917 }
Alex Crichton954046c2017-05-30 21:49:42 -07001918 }
Arnavion02ef13f2017-04-25 00:54:31 -07001919
Michael Layzell734adb42017-06-07 16:58:31 -04001920 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001921 impl Parse for ExprYield {
1922 fn parse(input: ParseStream) -> Result<Self> {
1923 Ok(ExprYield {
David Tolnay8c91b882017-12-28 23:04:32 -05001924 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07001925 yield_token: input.parse()?,
1926 expr: {
1927 if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
1928 Some(input.parse()?)
1929 } else {
1930 None
1931 }
1932 },
Alex Crichtonfe110462017-06-01 12:49:27 -07001933 })
David Tolnay60291082018-08-28 09:54:49 -07001934 }
Alex Crichtonfe110462017-06-01 12:49:27 -07001935 }
1936
1937 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001938 impl Parse for Arm {
1939 fn parse(input: ParseStream) -> Result<Self> {
1940 let requires_comma;
1941 Ok(Arm {
1942 attrs: input.call(Attribute::parse_outer)?,
1943 leading_vert: input.parse()?,
1944 pats: {
1945 let mut pats = Punctuated::new();
1946 let value: Pat = input.parse()?;
1947 pats.push_value(value);
1948 loop {
1949 if !input.peek(Token![|]) {
1950 break;
1951 }
1952 let punct = input.parse()?;
1953 pats.push_punct(punct);
1954 let value: Pat = input.parse()?;
1955 pats.push_value(value);
1956 }
1957 pats
1958 },
1959 guard: {
1960 if input.peek(Token![if]) {
1961 let if_token: Token![if] = input.parse()?;
1962 let guard: Expr = input.parse()?;
1963 Some((if_token, Box::new(guard)))
1964 } else {
1965 None
1966 }
1967 },
1968 fat_arrow_token: input.parse()?,
1969 body: {
David Tolnay01218d12018-08-29 18:13:07 -07001970 let body = input.call(expr_early)?;
David Tolnay60291082018-08-28 09:54:49 -07001971 requires_comma = arm_expr_requires_comma(&body);
1972 Box::new(body)
1973 },
1974 comma: {
1975 if requires_comma && !input.is_empty() {
1976 Some(input.parse()?)
1977 } else {
1978 input.parse()?
1979 }
1980 },
Michael Layzell92639a52017-06-01 00:07:44 -04001981 })
David Tolnay60291082018-08-28 09:54:49 -07001982 }
Alex Crichton954046c2017-05-30 21:49:42 -07001983 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07001984
Michael Layzell734adb42017-06-07 16:58:31 -04001985 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001986 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
1987 let attrs = input.call(Attribute::parse_outer)?;
1988 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 {
2025 let body = ambiguous_expr(input, allow_struct, AllowBlock(true))?;
2026 (ReturnType::Default, body)
2027 };
2028
2029 Ok(ExprClosure {
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002030 attrs: attrs,
2031 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 Tolnay60291082018-08-28 09:54:49 -07002043 impl Parse for ExprAsync {
2044 fn parse(input: ParseStream) -> Result<Self> {
2045 Ok(ExprAsync {
2046 attrs: input.call(Attribute::parse_outer)?,
2047 async_token: input.parse()?,
2048 capture: input.parse()?,
2049 block: input.parse()?,
2050 })
2051 }
2052 }
Gregory Katz3e562cc2016-09-28 18:33:02 -04002053
Michael Layzell734adb42017-06-07 16:58:31 -04002054 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002055 fn fn_arg(input: ParseStream) -> Result<FnArg> {
2056 let pat: Pat = input.parse()?;
2057
2058 if input.peek(Token![:]) {
2059 Ok(FnArg::Captured(ArgCaptured {
2060 pat: pat,
2061 colon_token: input.parse()?,
2062 ty: input.parse()?,
2063 }))
2064 } else {
2065 Ok(FnArg::Inferred(pat))
2066 }
2067 }
2068
2069 #[cfg(feature = "full")]
2070 impl Parse for ExprWhile {
2071 fn parse(input: ParseStream) -> Result<Self> {
2072 let outer_attrs = input.call(Attribute::parse_outer)?;
2073 let label: Option<Label> = input.parse()?;
2074 let while_token: Token![while] = input.parse()?;
2075 let cond = expr_no_struct(input)?;
2076
2077 let content;
2078 let brace_token = braced!(content in input);
2079 let inner_attrs = content.call(Attribute::parse_inner)?;
2080 let stmts = content.call(Block::parse_within)?;
2081
2082 Ok(ExprWhile {
David Tolnay5d314dc2018-07-21 16:40:01 -07002083 attrs: {
2084 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07002085 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07002086 attrs
2087 },
2088 label: label,
David Tolnay60291082018-08-28 09:54:49 -07002089 while_token: while_token,
Michael Layzell92639a52017-06-01 00:07:44 -04002090 cond: Box::new(cond),
David Tolnay5d314dc2018-07-21 16:40:01 -07002091 body: Block {
David Tolnay60291082018-08-28 09:54:49 -07002092 brace_token: brace_token,
2093 stmts: stmts,
David Tolnay5d314dc2018-07-21 16:40:01 -07002094 },
Michael Layzell92639a52017-06-01 00:07:44 -04002095 })
David Tolnay60291082018-08-28 09:54:49 -07002096 }
Alex Crichton954046c2017-05-30 21:49:42 -07002097 }
2098
Michael Layzell734adb42017-06-07 16:58:31 -04002099 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002100 impl Parse for ExprWhileLet {
2101 fn parse(input: ParseStream) -> Result<Self> {
2102 let outer_attrs = input.call(Attribute::parse_outer)?;
2103 let label: Option<Label> = input.parse()?;
2104 let while_token: Token![while] = input.parse()?;
2105 let let_token: Token![let] = input.parse()?;
2106
2107 let mut pats = Punctuated::new();
2108 let value: Pat = input.parse()?;
2109 pats.push_value(value);
2110 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2111 let punct = input.parse()?;
2112 pats.push_punct(punct);
2113 let value: Pat = input.parse()?;
2114 pats.push_value(value);
2115 }
2116
2117 let eq_token: Token![=] = input.parse()?;
2118 let expr = expr_no_struct(input)?;
2119
2120 let content;
2121 let brace_token = braced!(content in input);
2122 let inner_attrs = content.call(Attribute::parse_inner)?;
2123 let stmts = content.call(Block::parse_within)?;
2124
2125 Ok(ExprWhileLet {
David Tolnay5d314dc2018-07-21 16:40:01 -07002126 attrs: {
2127 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07002128 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07002129 attrs
2130 },
David Tolnaybcd498f2017-12-29 12:02:33 -05002131 label: label,
David Tolnay60291082018-08-28 09:54:49 -07002132 while_token: while_token,
2133 let_token: let_token,
David Tolnay5d314dc2018-07-21 16:40:01 -07002134 pats: pats,
David Tolnay60291082018-08-28 09:54:49 -07002135 eq_token: eq_token,
2136 expr: Box::new(expr),
David Tolnay5d314dc2018-07-21 16:40:01 -07002137 body: Block {
David Tolnay60291082018-08-28 09:54:49 -07002138 brace_token: brace_token,
2139 stmts: stmts,
David Tolnay5d314dc2018-07-21 16:40:01 -07002140 },
David Tolnaybcd498f2017-12-29 12:02:33 -05002141 })
David Tolnay60291082018-08-28 09:54:49 -07002142 }
David Tolnaybcd498f2017-12-29 12:02:33 -05002143 }
2144
2145 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002146 impl Parse for Label {
2147 fn parse(input: ParseStream) -> Result<Self> {
2148 Ok(Label {
2149 name: input.parse()?,
2150 colon_token: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04002151 })
David Tolnay60291082018-08-28 09:54:49 -07002152 }
Alex Crichton954046c2017-05-30 21:49:42 -07002153 }
2154
Michael Layzell734adb42017-06-07 16:58:31 -04002155 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002156 impl Parse for Option<Label> {
2157 fn parse(input: ParseStream) -> Result<Self> {
2158 if input.peek(Lifetime) {
2159 input.parse().map(Some)
2160 } else {
2161 Ok(None)
2162 }
2163 }
2164 }
2165
2166 #[cfg(feature = "full")]
2167 impl Parse for ExprContinue {
2168 fn parse(input: ParseStream) -> Result<Self> {
2169 Ok(ExprContinue {
2170 attrs: input.call(Attribute::parse_outer)?,
2171 continue_token: input.parse()?,
2172 label: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04002173 })
David Tolnay60291082018-08-28 09:54:49 -07002174 }
Alex Crichton954046c2017-05-30 21:49:42 -07002175 }
Gregory Katzfd6935d2016-09-30 22:51:25 -04002176
Michael Layzell734adb42017-06-07 16:58:31 -04002177 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002178 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2179 Ok(ExprBreak {
2180 attrs: input.call(Attribute::parse_outer)?,
2181 break_token: input.parse()?,
2182 label: input.parse()?,
2183 expr: {
2184 if input.is_empty()
2185 || input.peek(Token![,])
2186 || input.peek(Token![;])
2187 || !allow_struct.0 && input.peek(token::Brace)
2188 {
2189 None
2190 } else {
2191 // We can't allow blocks after a `break` expression when we
2192 // wouldn't allow structs, as this expression is ambiguous.
2193 let allow_block = AllowBlock(allow_struct.0);
2194 let expr = ambiguous_expr(input, allow_struct, allow_block)?;
2195 Some(Box::new(expr))
Michael Layzell92639a52017-06-01 00:07:44 -04002196 }
David Tolnay60291082018-08-28 09:54:49 -07002197 },
2198 })
Alex Crichton954046c2017-05-30 21:49:42 -07002199 }
2200
Michael Layzell734adb42017-06-07 16:58:31 -04002201 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002202 fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
2203 Ok(ExprReturn {
2204 attrs: input.call(Attribute::parse_outer)?,
2205 return_token: input.parse()?,
2206 expr: {
2207 if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
2208 None
2209 } else {
2210 // NOTE: return is greedy and eats blocks after it even when in a
2211 // position where structs are not allowed, such as in if statement
2212 // conditions. For example:
2213 //
2214 // if return { println!("A") } {} // Prints "A"
2215 let expr = ambiguous_expr(input, allow_struct, AllowBlock(true))?;
2216 Some(Box::new(expr))
2217 }
2218 },
2219 })
2220 }
2221
2222 #[cfg(feature = "full")]
2223 impl Parse for ExprStruct {
2224 fn parse(input: ParseStream) -> Result<Self> {
2225 let outer_attrs = input.call(Attribute::parse_outer)?;
2226 let path: Path = input.parse()?;
2227
2228 let content;
2229 let brace_token = braced!(content in input);
2230 let inner_attrs = content.call(Attribute::parse_inner)?;
2231
2232 let mut fields = Punctuated::new();
2233 loop {
2234 let attrs = content.call(Attribute::parse_outer)?;
2235 if content.fork().parse::<Member>().is_err() {
2236 if attrs.is_empty() {
2237 break;
2238 } else {
2239 return Err(content.error("expected struct field"));
2240 }
2241 }
2242
2243 let member: Member = content.parse()?;
2244 let (colon_token, value) = if content.peek(Token![:]) || !member.is_named() {
2245 let colon_token: Token![:] = content.parse()?;
2246 let value: Expr = content.parse()?;
2247 (Some(colon_token), value)
2248 } else if let Member::Named(ref ident) = member {
2249 let value = Expr::Path(ExprPath {
David Tolnayc42b90a2018-01-18 23:11:37 -08002250 attrs: Vec::new(),
2251 qself: None,
David Tolnay60291082018-08-28 09:54:49 -07002252 path: Path::from(ident.clone()),
2253 });
2254 (None, value)
2255 } else {
2256 unreachable!()
2257 };
2258
2259 fields.push(FieldValue {
2260 attrs: attrs,
2261 member: member,
2262 colon_token: colon_token,
2263 expr: value,
2264 });
2265
2266 if !content.peek(Token![,]) {
2267 break;
2268 }
2269 let punct: Token![,] = content.parse()?;
2270 fields.push_punct(punct);
2271 }
2272
2273 let (dot2_token, rest) = if fields.empty_or_trailing() && content.peek(Token![..]) {
2274 let dot2_token: Token![..] = content.parse()?;
2275 let rest: Expr = content.parse()?;
2276 (Some(dot2_token), Some(Box::new(rest)))
2277 } else {
2278 (None, None)
2279 };
2280
2281 Ok(ExprStruct {
2282 attrs: {
2283 let mut attrs = outer_attrs;
2284 attrs.extend(inner_attrs);
2285 attrs
2286 },
2287 brace_token: brace_token,
2288 path: path,
2289 fields: fields,
2290 dot2_token: dot2_token,
2291 rest: rest,
Michael Layzell92639a52017-06-01 00:07:44 -04002292 })
David Tolnay60291082018-08-28 09:54:49 -07002293 }
Alex Crichton954046c2017-05-30 21:49:42 -07002294 }
David Tolnay055a7042016-10-02 19:23:54 -07002295
Michael Layzell734adb42017-06-07 16:58:31 -04002296 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002297 impl Parse for ExprRepeat {
2298 fn parse(input: ParseStream) -> Result<Self> {
2299 let outer_attrs = input.call(Attribute::parse_outer)?;
2300
2301 let content;
2302 let bracket_token = bracketed!(content in input);
2303 let inner_attrs = content.call(Attribute::parse_inner)?;
2304 let expr: Expr = content.parse()?;
2305 let semi_token: Token![;] = content.parse()?;
2306 let len: Expr = content.parse()?;
2307
2308 Ok(ExprRepeat {
David Tolnay5d314dc2018-07-21 16:40:01 -07002309 attrs: {
2310 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07002311 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07002312 attrs
2313 },
David Tolnay60291082018-08-28 09:54:49 -07002314 bracket_token: bracket_token,
2315 expr: Box::new(expr),
2316 semi_token: semi_token,
2317 len: Box::new(len),
Michael Layzell92639a52017-06-01 00:07:44 -04002318 })
David Tolnay60291082018-08-28 09:54:49 -07002319 }
Alex Crichton954046c2017-05-30 21:49:42 -07002320 }
David Tolnay055a7042016-10-02 19:23:54 -07002321
Michael Layzell734adb42017-06-07 16:58:31 -04002322 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002323 impl Parse for ExprUnsafe {
2324 fn parse(input: ParseStream) -> Result<Self> {
2325 let outer_attrs = input.call(Attribute::parse_outer)?;
2326 let unsafe_token: Token![unsafe] = input.parse()?;
2327
2328 let content;
2329 let brace_token = braced!(content in input);
2330 let inner_attrs = content.call(Attribute::parse_inner)?;
2331 let stmts = content.call(Block::parse_within)?;
2332
2333 Ok(ExprUnsafe {
David Tolnayc4be3512018-08-27 06:25:44 -07002334 attrs: {
2335 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07002336 attrs.extend(inner_attrs);
David Tolnayc4be3512018-08-27 06:25:44 -07002337 attrs
2338 },
David Tolnay60291082018-08-28 09:54:49 -07002339 unsafe_token: unsafe_token,
David Tolnayc4be3512018-08-27 06:25:44 -07002340 block: Block {
David Tolnay60291082018-08-28 09:54:49 -07002341 brace_token: brace_token,
2342 stmts: stmts,
David Tolnayc4be3512018-08-27 06:25:44 -07002343 },
Nika Layzell640832a2017-12-04 13:37:09 -05002344 })
David Tolnay60291082018-08-28 09:54:49 -07002345 }
Nika Layzell640832a2017-12-04 13:37:09 -05002346 }
2347
2348 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002349 impl Parse for ExprBlock {
2350 fn parse(input: ParseStream) -> Result<Self> {
2351 let outer_attrs = input.call(Attribute::parse_outer)?;
2352 let label: Option<Label> = input.parse()?;
2353
2354 let content;
2355 let brace_token = braced!(content in input);
2356 let inner_attrs = content.call(Attribute::parse_inner)?;
2357 let stmts = content.call(Block::parse_within)?;
2358
2359 Ok(ExprBlock {
David Tolnay5d314dc2018-07-21 16:40:01 -07002360 attrs: {
2361 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07002362 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07002363 attrs
2364 },
David Tolnay1d8e9962018-08-24 19:04:20 -04002365 label: label,
David Tolnay5d314dc2018-07-21 16:40:01 -07002366 block: Block {
David Tolnay60291082018-08-28 09:54:49 -07002367 brace_token: brace_token,
2368 stmts: stmts,
David Tolnay5d314dc2018-07-21 16:40:01 -07002369 },
Michael Layzell92639a52017-06-01 00:07:44 -04002370 })
David Tolnay60291082018-08-28 09:54:49 -07002371 }
Alex Crichton954046c2017-05-30 21:49:42 -07002372 }
David Tolnay89e05672016-10-02 14:39:42 -07002373
Michael Layzell734adb42017-06-07 16:58:31 -04002374 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002375 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2376 Ok(ExprRange {
David Tolnay8c91b882017-12-28 23:04:32 -05002377 attrs: Vec::new(),
2378 from: None,
David Tolnay60291082018-08-28 09:54:49 -07002379 limits: input.parse()?,
2380 to: {
2381 if input.is_empty()
2382 || input.peek(Token![,])
2383 || input.peek(Token![;])
2384 || !allow_struct.0 && input.peek(token::Brace)
2385 {
2386 None
2387 } else {
2388 let to = ambiguous_expr(input, allow_struct, AllowBlock(allow_struct.0))?;
2389 Some(Box::new(to))
2390 }
2391 },
2392 })
2393 }
David Tolnay438c9052016-10-07 23:24:48 -07002394
Michael Layzell734adb42017-06-07 16:58:31 -04002395 #[cfg(feature = "full")]
David Tolnayc4c631e2018-08-27 10:44:37 -07002396 impl Parse for RangeLimits {
2397 fn parse(input: ParseStream) -> Result<Self> {
2398 let lookahead = input.lookahead1();
2399 if lookahead.peek(Token![..=]) {
2400 input.parse().map(RangeLimits::Closed)
2401 } else if lookahead.peek(Token![...]) {
2402 let dot3: Token![...] = input.parse()?;
2403 Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2404 } else if lookahead.peek(Token![..]) {
2405 input.parse().map(RangeLimits::HalfOpen)
2406 } else {
2407 Err(lookahead.error())
2408 }
2409 }
Alex Crichton954046c2017-05-30 21:49:42 -07002410 }
David Tolnay438c9052016-10-07 23:24:48 -07002411
David Tolnay60291082018-08-28 09:54:49 -07002412 impl Parse for ExprPath {
2413 fn parse(input: ParseStream) -> Result<Self> {
2414 #[cfg(not(feature = "full"))]
2415 let attrs = Vec::new();
2416 #[cfg(feature = "full")]
2417 let attrs = input.call(Attribute::parse_outer)?;
David Tolnayeb981bb2018-07-21 19:31:38 -07002418
David Tolnay60291082018-08-28 09:54:49 -07002419 let (qself, path) = path::parsing::qpath(input, true)?;
2420
2421 Ok(ExprPath {
David Tolnay73c9b522018-07-21 15:58:40 -07002422 attrs: attrs,
David Tolnay60291082018-08-28 09:54:49 -07002423 qself: qself,
2424 path: path,
Michael Layzell92639a52017-06-01 00:07:44 -04002425 })
David Tolnay60291082018-08-28 09:54:49 -07002426 }
Alex Crichton954046c2017-05-30 21:49:42 -07002427 }
David Tolnay42602292016-10-01 22:25:45 -07002428
Michael Layzell734adb42017-06-07 16:58:31 -04002429 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002430 impl Parse for Block {
2431 fn parse(input: ParseStream) -> Result<Self> {
2432 let content;
2433 Ok(Block {
2434 brace_token: braced!(content in input),
2435 stmts: content.call(Block::parse_within)?,
Michael Layzell92639a52017-06-01 00:07:44 -04002436 })
David Tolnay60291082018-08-28 09:54:49 -07002437 }
Alex Crichton954046c2017-05-30 21:49:42 -07002438 }
David Tolnay939766a2016-09-23 23:48:12 -07002439
Michael Layzell734adb42017-06-07 16:58:31 -04002440 #[cfg(feature = "full")]
Alex Crichton954046c2017-05-30 21:49:42 -07002441 impl Block {
David Tolnay9389c382018-08-27 09:13:37 -07002442 pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> {
2443 input.step_cursor(|cursor| Self::old_parse_within(*cursor))
2444 }
2445
2446 named!(old_parse_within -> Vec<Stmt>, do_parse!(
David Tolnay4699a312017-12-27 14:39:22 -05002447 many0!(punct!(;)) >>
David Tolnaydc03aec2017-12-30 01:54:18 -05002448 mut standalone: many0!(do_parse!(
2449 stmt: syn!(Stmt) >>
2450 many0!(punct!(;)) >>
2451 (stmt)
2452 )) >>
Alex Crichton70bbd592017-08-27 10:40:03 -07002453 last: option!(do_parse!(
David Tolnayf8106f82018-08-25 21:17:45 -04002454 attrs: many0!(Attribute::old_parse_outer) >>
Alex Crichton70bbd592017-08-27 10:40:03 -07002455 mut e: syn!(Expr) >>
2456 ({
David Tolnay2ae520a2017-12-29 11:19:50 -05002457 e.replace_attrs(attrs);
David Tolnay1f0b7b82018-01-06 16:07:14 -08002458 Stmt::Expr(e)
Alex Crichton70bbd592017-08-27 10:40:03 -07002459 })
2460 )) >>
Michael Layzell92639a52017-06-01 00:07:44 -04002461 (match last {
2462 None => standalone,
2463 Some(last) => {
Alex Crichton70bbd592017-08-27 10:40:03 -07002464 standalone.push(last);
Michael Layzell92639a52017-06-01 00:07:44 -04002465 standalone
2466 }
2467 })
2468 ));
Alex Crichton954046c2017-05-30 21:49:42 -07002469 }
2470
Michael Layzell734adb42017-06-07 16:58:31 -04002471 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002472 impl Parse for Stmt {
2473 fn parse(input: ParseStream) -> Result<Self> {
2474 let ahead = input.fork();
2475 ahead.call(Attribute::parse_outer)?;
David Tolnay939766a2016-09-23 23:48:12 -07002476
David Tolnay60291082018-08-28 09:54:49 -07002477 // TODO: better error messages
2478 if {
2479 let ahead = ahead.fork();
2480 // Only parse braces here; paren and bracket will get parsed as
2481 // expression statements
2482 ahead.call(Path::parse_mod_style).is_ok()
2483 && ahead.parse::<Token![!]>().is_ok()
2484 && (ahead.peek(token::Brace) || ahead.peek(Ident))
2485 } {
2486 stmt_mac(input)
2487 } else if ahead.peek(Token![let]) {
2488 stmt_local(input).map(Stmt::Local)
2489 } else if ahead.peek(Token![pub])
2490 || ahead.peek(Token![crate]) && !ahead.peek2(Token![::])
2491 || ahead.peek(Token![extern]) && !ahead.peek2(Token![::])
2492 || ahead.peek(Token![use])
2493 || ahead.peek(Token![static]) && (ahead.peek2(Token![mut]) || ahead.peek2(Ident))
2494 || ahead.peek(Token![const])
2495 || ahead.peek(Token![unsafe]) && !ahead.peek2(token::Brace)
2496 || ahead.peek(Token![async]) && (ahead.peek2(Token![extern]) || ahead.peek2(Token![fn]))
2497 || ahead.peek(Token![fn])
2498 || ahead.peek(Token![mod])
2499 || ahead.peek(Token![type])
2500 || ahead.peek(Token![existential]) && ahead.peek2(Token![type])
2501 || ahead.peek(Token![struct])
2502 || ahead.peek(Token![enum])
2503 || ahead.peek(Token![union]) && ahead.peek2(Ident)
2504 || ahead.peek(Token![auto]) && ahead.peek2(Token![trait])
2505 || ahead.peek(Token![trait])
2506 || ahead.peek(Token![default]) && (ahead.peek2(Token![unsafe]) || ahead.peek2(Token![impl]))
2507 || ahead.peek(Token![impl])
2508 || ahead.peek(Token![macro])
2509 {
2510 input.parse().map(Stmt::Item)
Michael Layzell35418782017-06-07 09:20:25 -04002511 } else {
David Tolnay01218d12018-08-29 18:13:07 -07002512 input.call(stmt_expr)
Michael Layzell35418782017-06-07 09:20:25 -04002513 }
David Tolnay60291082018-08-28 09:54:49 -07002514 }
Alex Crichton954046c2017-05-30 21:49:42 -07002515 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07002516
Michael Layzell734adb42017-06-07 16:58:31 -04002517 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002518 fn stmt_mac(input: ParseStream) -> Result<Stmt> {
2519 let attrs = input.call(Attribute::parse_outer)?;
2520 let path = input.call(Path::parse_mod_style)?;
2521 let bang_token: Token![!] = input.parse()?;
2522 let ident: Option<Ident> = input.parse()?;
2523 let (delimiter, tts) = mac::parse_delimiter(input)?;
2524 let semi_token: Option<Token![;]> = input.parse()?;
2525
2526 Ok(Stmt::Item(Item::Macro(ItemMacro {
2527 attrs: attrs,
2528 ident: ident,
2529 mac: Macro {
2530 path: path,
2531 bang_token: bang_token,
2532 delimiter: delimiter,
2533 tts: tts,
2534 },
2535 semi_token: semi_token,
2536 })))
Alex Crichton954046c2017-05-30 21:49:42 -07002537 }
David Tolnay84aa0752016-10-02 23:01:13 -07002538
Michael Layzell734adb42017-06-07 16:58:31 -04002539 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002540 fn stmt_local(input: ParseStream) -> Result<Local> {
2541 Ok(Local {
2542 attrs: input.call(Attribute::parse_outer)?,
2543 let_token: input.parse()?,
2544 pats: {
2545 let mut pats = Punctuated::new();
2546 let value: Pat = input.parse()?;
2547 pats.push_value(value);
2548 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2549 let punct = input.parse()?;
2550 pats.push_punct(punct);
2551 let value: Pat = input.parse()?;
2552 pats.push_value(value);
2553 }
2554 pats
2555 },
2556 ty: {
2557 if input.peek(Token![:]) {
2558 let colon_token: Token![:] = input.parse()?;
2559 let ty: Type = input.parse()?;
2560 Some((colon_token, Box::new(ty)))
2561 } else {
2562 None
2563 }
2564 },
2565 init: {
2566 if input.peek(Token![=]) {
2567 let eq_token: Token![=] = input.parse()?;
2568 let init: Expr = input.parse()?;
2569 Some((eq_token, Box::new(init)))
2570 } else {
2571 None
2572 }
2573 },
2574 semi_token: input.parse()?,
2575 })
2576 }
2577
2578 #[cfg(feature = "full")]
David Tolnay01218d12018-08-29 18:13:07 -07002579 fn stmt_expr(input: ParseStream) -> Result<Stmt> {
David Tolnay60291082018-08-28 09:54:49 -07002580 let mut attrs = input.call(Attribute::parse_outer)?;
David Tolnay01218d12018-08-29 18:13:07 -07002581 let mut e = expr_early(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002582
2583 attrs.extend(e.replace_attrs(Vec::new()));
2584 e.replace_attrs(attrs);
2585
2586 if input.peek(Token![;]) {
David Tolnay01218d12018-08-29 18:13:07 -07002587 return Ok(Stmt::Semi(e, input.parse()?));
David Tolnay60291082018-08-28 09:54:49 -07002588 }
David Tolnay60291082018-08-28 09:54:49 -07002589
David Tolnay01218d12018-08-29 18:13:07 -07002590 match e {
2591 Expr::IfLet(_) |
2592 Expr::If(_) |
2593 Expr::WhileLet(_) |
2594 Expr::While(_) |
2595 Expr::ForLoop(_) |
2596 Expr::Loop(_) |
2597 Expr::Match(_) |
2598 Expr::TryBlock(_) |
2599 Expr::Yield(_) |
2600 Expr::Unsafe(_) |
2601 Expr::Block(_) => Ok(Stmt::Expr(e)),
2602 _ => {
2603 Err(input.error("expected semicolon"))
2604 }
2605 }
David Tolnay60291082018-08-28 09:54:49 -07002606 }
2607
2608 #[cfg(feature = "full")]
2609 impl Parse for Pat {
2610 fn parse(input: ParseStream) -> Result<Self> {
2611 // TODO: better error messages
2612 let lookahead = input.lookahead1();
2613 if lookahead.peek(Token![_]) {
2614 input.parse().map(Pat::Wild)
2615 } else if lookahead.peek(Token![box]) {
2616 input.parse().map(Pat::Box)
2617 } else if input.fork().parse::<PatRange>().is_ok() {
2618 // must be before Pat::Lit
2619 input.parse().map(Pat::Range)
2620 } else if input.fork().parse::<PatTupleStruct>().is_ok() {
2621 // must be before Pat::Ident
2622 input.parse().map(Pat::TupleStruct)
2623 } else if input.fork().parse::<PatStruct>().is_ok() {
2624 // must be before Pat::Ident
2625 input.parse().map(Pat::Struct)
2626 } else if input.fork().parse::<PatMacro>().is_ok() {
2627 // must be before Pat::Ident
2628 input.parse().map(Pat::Macro)
2629 } else if input.fork().parse::<PatLit>().is_ok() {
2630 // must be before Pat::Ident
2631 input.parse().map(Pat::Lit)
2632 } else if input.fork().parse::<PatIdent>().is_ok() {
2633 input.parse().map(Pat::Ident)
2634 } else if input.fork().parse::<PatPath>().is_ok() {
2635 input.parse().map(Pat::Path)
2636 } else if lookahead.peek(token::Paren) {
2637 input.parse().map(Pat::Tuple)
2638 } else if lookahead.peek(Token![&]) {
2639 input.parse().map(Pat::Ref)
2640 } else if lookahead.peek(token::Bracket) {
2641 input.parse().map(Pat::Slice)
2642 } else {
2643 Err(lookahead.error())
2644 }
2645 }
2646 }
2647
2648 #[cfg(feature = "full")]
2649 impl Parse for PatWild {
2650 fn parse(input: ParseStream) -> Result<Self> {
2651 Ok(PatWild {
2652 underscore_token: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04002653 })
David Tolnay60291082018-08-28 09:54:49 -07002654 }
Alex Crichton954046c2017-05-30 21:49:42 -07002655 }
2656
Michael Layzell734adb42017-06-07 16:58:31 -04002657 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002658 impl Parse for PatBox {
2659 fn parse(input: ParseStream) -> Result<Self> {
2660 Ok(PatBox {
2661 box_token: input.parse()?,
2662 pat: input.parse()?,
2663 })
2664 }
2665 }
2666
2667 #[cfg(feature = "full")]
2668 impl Parse for PatIdent {
2669 fn parse(input: ParseStream) -> Result<Self> {
2670 Ok(PatIdent {
2671 by_ref: input.parse()?,
2672 mutability: input.parse()?,
2673 ident: {
2674 let ident = if input.peek(Ident) || input.peek(Token![self]) {
2675 input.call(Ident::parse_any2)?
2676 } else {
2677 return Err(input.error("expected identifier or `self`"));
2678 };
2679 if input.peek(Token![<]) || input.peek(Token![::]) {
2680 return Err(input.error("unexpected token"));
2681 }
2682 ident
2683 },
2684 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 })
2694 }
2695 }
2696
2697 #[cfg(feature = "full")]
2698 impl Parse for PatTupleStruct {
2699 fn parse(input: ParseStream) -> Result<Self> {
2700 Ok(PatTupleStruct {
2701 path: input.parse()?,
2702 pat: input.parse()?,
2703 })
2704 }
2705 }
2706
2707 #[cfg(feature = "full")]
2708 impl Parse for PatStruct {
2709 fn parse(input: ParseStream) -> Result<Self> {
2710 let path: Path = input.parse()?;
2711
2712 let content;
2713 let brace_token = braced!(content in input);
2714
2715 let mut fields = Punctuated::new();
2716 while !content.is_empty() && !content.peek(Token![..]) {
2717 let value: FieldPat = content.parse()?;
2718 fields.push_value(value);
2719 if !content.peek(Token![,]) {
2720 break;
2721 }
2722 let punct: Token![,] = content.parse()?;
2723 fields.push_punct(punct);
2724 }
2725
2726 let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) {
2727 Some(content.parse()?)
2728 } else {
2729 None
2730 };
2731
2732 Ok(PatStruct {
2733 path: path,
2734 brace_token: brace_token,
2735 fields: fields,
2736 dot2_token: dot2_token,
2737 })
2738 }
2739 }
2740
2741 #[cfg(feature = "full")]
2742 impl Parse for FieldPat {
2743 fn parse(input: ParseStream) -> Result<Self> {
2744 let boxed: Option<Token![box]> = input.parse()?;
2745 let by_ref: Option<Token![ref]> = input.parse()?;
2746 let mutability: Option<Token![mut]> = input.parse()?;
2747 let member: Member = input.parse()?;
2748
2749 if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
2750 || member.is_unnamed()
2751 {
2752 return Ok(FieldPat {
2753 attrs: Vec::new(),
2754 member: member,
2755 colon_token: input.parse()?,
2756 pat: input.parse()?,
2757 });
2758 }
2759
2760 let ident = match member {
2761 Member::Named(ident) => ident,
2762 Member::Unnamed(_) => unreachable!(),
2763 };
2764
2765 let mut pat = Pat::Ident(PatIdent {
David Tolnay24237fb2017-12-29 02:15:26 -05002766 by_ref: by_ref,
David Tolnayefc96fb2017-12-29 02:03:15 -05002767 mutability: mutability,
David Tolnay60291082018-08-28 09:54:49 -07002768 ident: ident.clone(),
2769 subpat: None,
2770 });
Alex Crichton954046c2017-05-30 21:49:42 -07002771
David Tolnay60291082018-08-28 09:54:49 -07002772 if let Some(boxed) = boxed {
2773 pat = Pat::Box(PatBox {
Michael Layzell92639a52017-06-01 00:07:44 -04002774 pat: Box::new(pat),
David Tolnay60291082018-08-28 09:54:49 -07002775 box_token: boxed,
2776 });
2777 }
2778
2779 Ok(FieldPat {
2780 member: Member::Named(ident),
2781 pat: Box::new(pat),
2782 attrs: Vec::new(),
2783 colon_token: None,
2784 })
2785 }
Alex Crichton954046c2017-05-30 21:49:42 -07002786 }
2787
David Tolnay1501f7e2018-08-27 14:21:03 -07002788 impl Parse for Member {
2789 fn parse(input: ParseStream) -> Result<Self> {
2790 if input.peek(Ident) {
2791 input.parse().map(Member::Named)
2792 } else if input.peek(LitInt) {
2793 input.parse().map(Member::Unnamed)
2794 } else {
2795 Err(input.error("expected identifier or integer"))
2796 }
2797 }
David Tolnay85b69a42017-12-27 20:43:10 -05002798 }
2799
David Tolnay1501f7e2018-08-27 14:21:03 -07002800 impl Parse for Index {
2801 fn parse(input: ParseStream) -> Result<Self> {
2802 let lit: LitInt = input.parse()?;
2803 if let IntSuffix::None = lit.suffix() {
2804 Ok(Index {
2805 index: lit.value() as u32,
2806 span: lit.span(),
2807 })
2808 } else {
2809 Err(input.error("expected unsuffixed integer"))
2810 }
2811 }
David Tolnay85b69a42017-12-27 20:43:10 -05002812 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07002813
Michael Layzell734adb42017-06-07 16:58:31 -04002814 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002815 impl Parse for PatPath {
2816 fn parse(input: ParseStream) -> Result<Self> {
2817 let p: ExprPath = input.parse()?;
2818 Ok(PatPath {
2819 qself: p.qself,
2820 path: p.path,
2821 })
2822 }
Alex Crichton954046c2017-05-30 21:49:42 -07002823 }
David Tolnay9636c052016-10-02 17:11:17 -07002824
Michael Layzell734adb42017-06-07 16:58:31 -04002825 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002826 impl Parse for PatTuple {
2827 fn parse(input: ParseStream) -> Result<Self> {
2828 let content;
2829 let paren_token = parenthesized!(content in input);
2830
2831 let mut front = Punctuated::new();
2832 let mut dot2_token = None::<Token![..]>;
2833 let mut comma_token = None::<Token![,]>;
2834 loop {
2835 if content.is_empty() {
2836 break;
Michael Layzell92639a52017-06-01 00:07:44 -04002837 }
David Tolnay60291082018-08-28 09:54:49 -07002838 if content.peek(Token![..]) {
2839 dot2_token = Some(content.parse()?);
2840 comma_token = content.parse()?;
2841 break;
2842 }
2843 let value: Pat = content.parse()?;
2844 front.push_value(value);
2845 if content.is_empty() {
2846 break;
2847 }
2848 let punct = content.parse()?;
2849 front.push_punct(punct);
2850 }
David Tolnayfbb73232016-10-03 01:00:06 -07002851
David Tolnay60291082018-08-28 09:54:49 -07002852 let back = if comma_token.is_some() {
2853 content.parse_synom(Punctuated::parse_terminated)?
Michael Layzell92639a52017-06-01 00:07:44 -04002854 } else {
David Tolnay60291082018-08-28 09:54:49 -07002855 Punctuated::new()
2856 };
2857
2858 Ok(PatTuple {
2859 paren_token: paren_token,
2860 front: front,
2861 dot2_token: dot2_token,
2862 comma_token: comma_token,
2863 back: back,
Michael Layzell92639a52017-06-01 00:07:44 -04002864 })
David Tolnay60291082018-08-28 09:54:49 -07002865 }
Alex Crichton954046c2017-05-30 21:49:42 -07002866 }
David Tolnaye1310902016-10-29 23:40:00 -07002867
Michael Layzell734adb42017-06-07 16:58:31 -04002868 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002869 impl Parse for PatRef {
2870 fn parse(input: ParseStream) -> Result<Self> {
2871 Ok(PatRef {
2872 and_token: input.parse()?,
2873 mutability: input.parse()?,
2874 pat: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04002875 })
David Tolnay60291082018-08-28 09:54:49 -07002876 }
Alex Crichton954046c2017-05-30 21:49:42 -07002877 }
David Tolnaye1310902016-10-29 23:40:00 -07002878
Michael Layzell734adb42017-06-07 16:58:31 -04002879 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002880 impl Parse for PatLit {
2881 fn parse(input: ParseStream) -> Result<Self> {
2882 if input.peek(Lit) || input.peek(Token![-]) && input.peek2(Lit) {
2883 Ok(PatLit {
2884 expr: input.call(pat_lit_expr)?,
2885 })
2886 } else {
2887 Err(input.error("expected literal pattern"))
2888 }
2889 }
2890 }
2891
2892 #[cfg(feature = "full")]
2893 impl Parse for PatRange {
2894 fn parse(input: ParseStream) -> Result<Self> {
2895 Ok(PatRange {
2896 lo: input.call(pat_lit_expr)?,
2897 limits: input.parse()?,
2898 hi: input.call(pat_lit_expr)?,
2899 })
2900 }
2901 }
2902
2903 #[cfg(feature = "full")]
2904 fn pat_lit_expr(input: ParseStream) -> Result<Box<Expr>> {
2905 let neg: Option<Token![-]> = input.parse()?;
2906
2907 let lookahead = input.lookahead1();
2908 let expr = if lookahead.peek(Lit) {
2909 Expr::Lit(input.parse()?)
2910 } else if lookahead.peek(Ident)
2911 || lookahead.peek(Token![::])
2912 || lookahead.peek(Token![<])
2913 || lookahead.peek(Token![self])
2914 || lookahead.peek(Token![Self])
2915 || lookahead.peek(Token![super])
2916 || lookahead.peek(Token![extern])
2917 || lookahead.peek(Token![crate])
2918 {
2919 Expr::Path(input.parse()?)
2920 } else {
2921 return Err(lookahead.error());
2922 };
2923
2924 Ok(Box::new(if let Some(neg) = neg {
David Tolnay8c91b882017-12-28 23:04:32 -05002925 Expr::Unary(ExprUnary {
2926 attrs: Vec::new(),
David Tolnayc29b9892017-12-27 22:58:14 -05002927 op: UnOp::Neg(neg),
David Tolnay60291082018-08-28 09:54:49 -07002928 expr: Box::new(expr),
David Tolnay3bc597f2017-12-31 02:31:11 -05002929 })
David Tolnay0ad9e9f2016-10-29 22:20:02 -07002930 } else {
David Tolnay60291082018-08-28 09:54:49 -07002931 expr
2932 }))
Alex Crichton954046c2017-05-30 21:49:42 -07002933 }
David Tolnay323279a2017-12-29 11:26:32 -05002934
2935 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002936 impl Parse for PatSlice {
2937 fn parse(input: ParseStream) -> Result<Self> {
2938 let content;
2939 let bracket_token = bracketed!(content in input);
2940
2941 let mut front = Punctuated::new();
2942 let mut middle = None;
2943 loop {
2944 if content.is_empty() || content.peek(Token![..]) {
2945 break;
2946 }
2947 let value: Pat = content.parse()?;
2948 if content.peek(Token![..]) {
2949 middle = Some(Box::new(value));
2950 break;
2951 }
2952 front.push_value(value);
2953 if content.is_empty() {
2954 break;
2955 }
2956 let punct = content.parse()?;
2957 front.push_punct(punct);
2958 }
2959
2960 let dot2_token: Option<Token![..]> = content.parse()?;
2961 let mut comma_token = None::<Token![,]>;
2962 let mut back = Punctuated::new();
2963 if dot2_token.is_some() {
2964 comma_token = content.parse()?;
2965 if comma_token.is_some() {
2966 loop {
2967 if content.is_empty() {
2968 break;
2969 }
2970 let value: Pat = content.parse()?;
2971 back.push_value(value);
2972 if content.is_empty() {
2973 break;
2974 }
2975 let punct = content.parse()?;
2976 back.push_punct(punct);
2977 }
2978 }
2979 }
2980
2981 Ok(PatSlice {
2982 bracket_token: bracket_token,
2983 front: front,
2984 middle: middle,
2985 dot2_token: dot2_token,
2986 comma_token: comma_token,
2987 back: back,
2988 })
2989 }
2990 }
2991
2992 #[cfg(feature = "full")]
2993 impl Parse for PatMacro {
2994 fn parse(input: ParseStream) -> Result<Self> {
2995 Ok(PatMacro {
2996 mac: input.parse()?,
2997 })
2998 }
David Tolnay323279a2017-12-29 11:26:32 -05002999 }
David Tolnay1501f7e2018-08-27 14:21:03 -07003000
3001 #[cfg(feature = "full")]
3002 impl Member {
3003 fn is_named(&self) -> bool {
3004 match *self {
3005 Member::Named(_) => true,
3006 Member::Unnamed(_) => false,
3007 }
3008 }
David Tolnay60291082018-08-28 09:54:49 -07003009
3010 fn is_unnamed(&self) -> bool {
3011 match *self {
3012 Member::Named(_) => false,
3013 Member::Unnamed(_) => true,
3014 }
3015 }
David Tolnay1501f7e2018-08-27 14:21:03 -07003016 }
David Tolnayb9c8e322016-09-23 20:48:37 -07003017}
3018
David Tolnayf4bbbd92016-09-23 14:41:55 -07003019#[cfg(feature = "printing")]
3020mod printing {
3021 use super::*;
Michael Layzell734adb42017-06-07 16:58:31 -04003022 #[cfg(feature = "full")]
David Tolnay13b3d352016-10-03 00:31:15 -07003023 use attr::FilterAttrs;
Alex Crichtona74a1c82018-05-16 10:20:44 -07003024 use proc_macro2::{Literal, TokenStream};
3025 use quote::{ToTokens, TokenStreamExt};
David Tolnayf4bbbd92016-09-23 14:41:55 -07003026
David Tolnaybcf26022017-12-25 22:10:52 -05003027 // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
David Tolnayb6a0e7d2018-05-20 22:06:47 -07003028 // before appending it to `TokenStream`.
Michael Layzell3936ceb2017-07-08 00:28:36 -04003029 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003030 fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) {
David Tolnay8c91b882017-12-28 23:04:32 -05003031 if let Expr::Struct(_) = *e {
David Tolnay32954ef2017-12-26 22:43:16 -05003032 token::Paren::default().surround(tokens, |tokens| {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003033 e.to_tokens(tokens);
3034 });
3035 } else {
3036 e.to_tokens(tokens);
3037 }
3038 }
3039
David Tolnay8c91b882017-12-28 23:04:32 -05003040 #[cfg(feature = "full")]
David Tolnayd997aef2018-07-21 18:42:31 -07003041 fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
David Tolnay8c91b882017-12-28 23:04:32 -05003042 tokens.append_all(attrs.outer());
3043 }
Michael Layzell734adb42017-06-07 16:58:31 -04003044
David Tolnayd997aef2018-07-21 18:42:31 -07003045 #[cfg(feature = "full")]
3046 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3047 tokens.append_all(attrs.inner());
3048 }
3049
David Tolnay8c91b882017-12-28 23:04:32 -05003050 #[cfg(not(feature = "full"))]
David Tolnayd997aef2018-07-21 18:42:31 -07003051 fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3052
3053 #[cfg(not(feature = "full"))]
3054 fn inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
Alex Crichton62a0a592017-05-22 13:58:53 -07003055
Michael Layzell734adb42017-06-07 16:58:31 -04003056 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003057 impl ToTokens for ExprBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003058 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003059 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003060 self.box_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003061 self.expr.to_tokens(tokens);
3062 }
3063 }
3064
Michael Layzell734adb42017-06-07 16:58:31 -04003065 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003066 impl ToTokens for ExprInPlace {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003067 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003068 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8701a5c2017-12-28 23:31:10 -05003069 self.place.to_tokens(tokens);
3070 self.arrow_token.to_tokens(tokens);
3071 self.value.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003072 }
3073 }
3074
Michael Layzell734adb42017-06-07 16:58:31 -04003075 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003076 impl ToTokens for ExprArray {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003077 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003078 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003079 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003080 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003081 self.elems.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003082 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003083 }
3084 }
3085
3086 impl ToTokens for ExprCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003087 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003088 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003089 self.func.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003090 self.paren_token.surround(tokens, |tokens| {
3091 self.args.to_tokens(tokens);
3092 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003093 }
3094 }
3095
Michael Layzell734adb42017-06-07 16:58:31 -04003096 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003097 impl ToTokens for ExprMethodCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003098 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003099 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay76418512017-12-28 23:47:47 -05003100 self.receiver.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003101 self.dot_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003102 self.method.to_tokens(tokens);
David Tolnayd60cfec2017-12-29 00:21:38 -05003103 self.turbofish.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003104 self.paren_token.surround(tokens, |tokens| {
3105 self.args.to_tokens(tokens);
3106 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003107 }
3108 }
3109
Michael Layzell734adb42017-06-07 16:58:31 -04003110 #[cfg(feature = "full")]
David Tolnayd60cfec2017-12-29 00:21:38 -05003111 impl ToTokens for MethodTurbofish {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003112 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003113 self.colon2_token.to_tokens(tokens);
3114 self.lt_token.to_tokens(tokens);
3115 self.args.to_tokens(tokens);
3116 self.gt_token.to_tokens(tokens);
3117 }
3118 }
3119
3120 #[cfg(feature = "full")]
3121 impl ToTokens for GenericMethodArgument {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003122 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003123 match *self {
3124 GenericMethodArgument::Type(ref t) => t.to_tokens(tokens),
3125 GenericMethodArgument::Const(ref c) => c.to_tokens(tokens),
3126 }
3127 }
3128 }
3129
3130 #[cfg(feature = "full")]
David Tolnay05362582017-12-26 01:33:57 -05003131 impl ToTokens for ExprTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003132 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003133 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003134 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003135 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003136 self.elems.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003137 // If we only have one argument, we need a trailing comma to
David Tolnay05362582017-12-26 01:33:57 -05003138 // distinguish ExprTuple from ExprParen.
David Tolnaya0834b42018-01-01 21:30:02 -08003139 if self.elems.len() == 1 && !self.elems.trailing_punct() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003140 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003141 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003142 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003143 }
3144 }
3145
3146 impl ToTokens for ExprBinary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003147 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003148 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003149 self.left.to_tokens(tokens);
3150 self.op.to_tokens(tokens);
3151 self.right.to_tokens(tokens);
3152 }
3153 }
3154
3155 impl ToTokens for ExprUnary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003156 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003157 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003158 self.op.to_tokens(tokens);
3159 self.expr.to_tokens(tokens);
3160 }
3161 }
3162
David Tolnay8c91b882017-12-28 23:04:32 -05003163 impl ToTokens for ExprLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003164 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003165 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003166 self.lit.to_tokens(tokens);
3167 }
3168 }
3169
Alex Crichton62a0a592017-05-22 13:58:53 -07003170 impl ToTokens for ExprCast {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003171 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003172 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003173 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003174 self.as_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003175 self.ty.to_tokens(tokens);
3176 }
3177 }
3178
David Tolnay0cf94f22017-12-28 23:46:26 -05003179 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003180 impl ToTokens for ExprType {
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.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003184 self.colon_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003185 self.ty.to_tokens(tokens);
3186 }
3187 }
3188
Michael Layzell734adb42017-06-07 16:58:31 -04003189 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003190 fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>) {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003191 if let Some((ref else_token, ref else_)) = *else_ {
3192 else_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003193
3194 // If we are not one of the valid expressions to exist in an else
3195 // clause, wrap ourselves in a block.
David Tolnay2ccf32a2017-12-29 00:34:26 -05003196 match **else_ {
David Tolnay8c91b882017-12-28 23:04:32 -05003197 Expr::If(_) | Expr::IfLet(_) | Expr::Block(_) => {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003198 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003199 }
3200 _ => {
David Tolnay32954ef2017-12-26 22:43:16 -05003201 token::Brace::default().surround(tokens, |tokens| {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003202 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003203 });
3204 }
3205 }
3206 }
3207 }
3208
3209 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003210 impl ToTokens for ExprIf {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003211 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003212 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003213 self.if_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003214 wrap_bare_struct(tokens, &self.cond);
David Tolnay2ccf32a2017-12-29 00:34:26 -05003215 self.then_branch.to_tokens(tokens);
3216 maybe_wrap_else(tokens, &self.else_branch);
Alex Crichton62a0a592017-05-22 13:58:53 -07003217 }
3218 }
3219
Michael Layzell734adb42017-06-07 16:58:31 -04003220 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003221 impl ToTokens for ExprIfLet {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003222 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003223 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003224 self.if_token.to_tokens(tokens);
3225 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003226 self.pats.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003227 self.eq_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003228 wrap_bare_struct(tokens, &self.expr);
David Tolnay2ccf32a2017-12-29 00:34:26 -05003229 self.then_branch.to_tokens(tokens);
3230 maybe_wrap_else(tokens, &self.else_branch);
Alex Crichton62a0a592017-05-22 13:58:53 -07003231 }
3232 }
3233
Michael Layzell734adb42017-06-07 16:58:31 -04003234 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003235 impl ToTokens for ExprWhile {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003236 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003237 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003238 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003239 self.while_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003240 wrap_bare_struct(tokens, &self.cond);
David Tolnay5d314dc2018-07-21 16:40:01 -07003241 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003242 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003243 tokens.append_all(&self.body.stmts);
3244 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003245 }
3246 }
3247
Michael Layzell734adb42017-06-07 16:58:31 -04003248 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003249 impl ToTokens for ExprWhileLet {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003250 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003251 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003252 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003253 self.while_token.to_tokens(tokens);
3254 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003255 self.pats.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003256 self.eq_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003257 wrap_bare_struct(tokens, &self.expr);
David Tolnay5d314dc2018-07-21 16:40:01 -07003258 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003259 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003260 tokens.append_all(&self.body.stmts);
3261 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003262 }
3263 }
3264
Michael Layzell734adb42017-06-07 16:58:31 -04003265 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003266 impl ToTokens for ExprForLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003267 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003268 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003269 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003270 self.for_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003271 self.pat.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003272 self.in_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003273 wrap_bare_struct(tokens, &self.expr);
David Tolnay5d314dc2018-07-21 16:40:01 -07003274 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003275 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003276 tokens.append_all(&self.body.stmts);
3277 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003278 }
3279 }
3280
Michael Layzell734adb42017-06-07 16:58:31 -04003281 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003282 impl ToTokens for ExprLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003283 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003284 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003285 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003286 self.loop_token.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003287 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003288 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003289 tokens.append_all(&self.body.stmts);
3290 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003291 }
3292 }
3293
Michael Layzell734adb42017-06-07 16:58:31 -04003294 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003295 impl ToTokens for ExprMatch {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003296 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003297 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003298 self.match_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003299 wrap_bare_struct(tokens, &self.expr);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003300 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003301 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay51382052017-12-27 13:46:21 -05003302 for (i, arm) in self.arms.iter().enumerate() {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003303 arm.to_tokens(tokens);
3304 // Ensure that we have a comma after a non-block arm, except
3305 // for the last one.
3306 let is_last = i == self.arms.len() - 1;
Alex Crichton03b30272017-08-28 09:35:24 -07003307 if !is_last && arm_expr_requires_comma(&arm.body) && arm.comma.is_none() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003308 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003309 }
3310 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003311 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003312 }
3313 }
3314
Michael Layzell734adb42017-06-07 16:58:31 -04003315 #[cfg(feature = "full")]
David Tolnay02a9c6f2018-08-24 18:58:45 -04003316 impl ToTokens for ExprAsync {
3317 fn to_tokens(&self, tokens: &mut TokenStream) {
3318 outer_attrs_to_tokens(&self.attrs, tokens);
3319 self.async_token.to_tokens(tokens);
3320 self.capture.to_tokens(tokens);
3321 self.block.to_tokens(tokens);
3322 }
3323 }
3324
3325 #[cfg(feature = "full")]
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003326 impl ToTokens for ExprTryBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003327 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003328 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003329 self.try_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003330 self.block.to_tokens(tokens);
3331 }
3332 }
3333
Michael Layzell734adb42017-06-07 16:58:31 -04003334 #[cfg(feature = "full")]
Alex Crichtonfe110462017-06-01 12:49:27 -07003335 impl ToTokens for ExprYield {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003336 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003337 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonfe110462017-06-01 12:49:27 -07003338 self.yield_token.to_tokens(tokens);
3339 self.expr.to_tokens(tokens);
3340 }
3341 }
3342
3343 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003344 impl ToTokens for ExprClosure {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003345 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003346 outer_attrs_to_tokens(&self.attrs, tokens);
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09003347 self.asyncness.to_tokens(tokens);
David Tolnay13d4c0e2018-03-31 20:53:59 +02003348 self.movability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003349 self.capture.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003350 self.or1_token.to_tokens(tokens);
David Tolnay56080682018-01-06 14:01:52 -08003351 for input in self.inputs.pairs() {
3352 match **input.value() {
David Tolnay51382052017-12-27 13:46:21 -05003353 FnArg::Captured(ArgCaptured {
3354 ref pat,
3355 ty: Type::Infer(_),
3356 ..
3357 }) => {
Alex Crichton62a0a592017-05-22 13:58:53 -07003358 pat.to_tokens(tokens);
David Tolnay9636c052016-10-02 17:11:17 -07003359 }
David Tolnay56080682018-01-06 14:01:52 -08003360 _ => input.value().to_tokens(tokens),
David Tolnay3c2467c2016-10-02 17:55:08 -07003361 }
David Tolnayf2cfd722017-12-31 18:02:51 -05003362 input.punct().to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003363 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003364 self.or2_token.to_tokens(tokens);
David Tolnay7f675742017-12-27 22:43:21 -05003365 self.output.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003366 self.body.to_tokens(tokens);
3367 }
3368 }
3369
Michael Layzell734adb42017-06-07 16:58:31 -04003370 #[cfg(feature = "full")]
Nika Layzell640832a2017-12-04 13:37:09 -05003371 impl ToTokens for ExprUnsafe {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003372 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003373 outer_attrs_to_tokens(&self.attrs, tokens);
Nika Layzell640832a2017-12-04 13:37:09 -05003374 self.unsafe_token.to_tokens(tokens);
David Tolnayc4be3512018-08-27 06:25:44 -07003375 self.block.brace_token.surround(tokens, |tokens| {
3376 inner_attrs_to_tokens(&self.attrs, tokens);
3377 tokens.append_all(&self.block.stmts);
3378 });
Nika Layzell640832a2017-12-04 13:37:09 -05003379 }
3380 }
3381
3382 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003383 impl ToTokens for ExprBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003384 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003385 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay1d8e9962018-08-24 19:04:20 -04003386 self.label.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003387 self.block.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003388 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003389 tokens.append_all(&self.block.stmts);
3390 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003391 }
3392 }
3393
Michael Layzell734adb42017-06-07 16:58:31 -04003394 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003395 impl ToTokens for ExprAssign {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003396 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003397 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003398 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003399 self.eq_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003400 self.right.to_tokens(tokens);
3401 }
3402 }
3403
Michael Layzell734adb42017-06-07 16:58:31 -04003404 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003405 impl ToTokens for ExprAssignOp {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003406 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003407 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003408 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003409 self.op.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003410 self.right.to_tokens(tokens);
3411 }
3412 }
3413
3414 impl ToTokens for ExprField {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003415 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003416 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003417 self.base.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003418 self.dot_token.to_tokens(tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003419 self.member.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003420 }
3421 }
3422
David Tolnay85b69a42017-12-27 20:43:10 -05003423 impl ToTokens for Member {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003424 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay85b69a42017-12-27 20:43:10 -05003425 match *self {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003426 Member::Named(ref ident) => ident.to_tokens(tokens),
David Tolnay85b69a42017-12-27 20:43:10 -05003427 Member::Unnamed(ref index) => index.to_tokens(tokens),
3428 }
3429 }
3430 }
3431
David Tolnay85b69a42017-12-27 20:43:10 -05003432 impl ToTokens for Index {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003433 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichton9a4dca22018-03-28 06:32:19 -07003434 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
3435 lit.set_span(self.span);
3436 tokens.append(lit);
Alex Crichton62a0a592017-05-22 13:58:53 -07003437 }
3438 }
3439
3440 impl ToTokens for ExprIndex {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003441 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003442 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003443 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003444 self.bracket_token.surround(tokens, |tokens| {
3445 self.index.to_tokens(tokens);
3446 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003447 }
3448 }
3449
Michael Layzell734adb42017-06-07 16:58:31 -04003450 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003451 impl ToTokens for ExprRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003452 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003453 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003454 self.from.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003455 match self.limits {
3456 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
3457 RangeLimits::Closed(ref t) => t.to_tokens(tokens),
3458 }
Alex Crichton62a0a592017-05-22 13:58:53 -07003459 self.to.to_tokens(tokens);
3460 }
3461 }
3462
3463 impl ToTokens for ExprPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003464 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003465 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003466 ::PathTokens(&self.qself, &self.path).to_tokens(tokens)
Alex Crichton62a0a592017-05-22 13:58:53 -07003467 }
3468 }
3469
Michael Layzell734adb42017-06-07 16:58:31 -04003470 #[cfg(feature = "full")]
David Tolnay00674ba2018-03-31 18:14:11 +02003471 impl ToTokens for ExprReference {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003472 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003473 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003474 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003475 self.mutability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003476 self.expr.to_tokens(tokens);
3477 }
3478 }
3479
Michael Layzell734adb42017-06-07 16:58:31 -04003480 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003481 impl ToTokens for ExprBreak {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003482 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003483 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003484 self.break_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003485 self.label.to_tokens(tokens);
3486 self.expr.to_tokens(tokens);
3487 }
3488 }
3489
Michael Layzell734adb42017-06-07 16:58:31 -04003490 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003491 impl ToTokens for ExprContinue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003492 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003493 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003494 self.continue_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003495 self.label.to_tokens(tokens);
3496 }
3497 }
3498
Michael Layzell734adb42017-06-07 16:58:31 -04003499 #[cfg(feature = "full")]
David Tolnayc246cd32017-12-28 23:14:32 -05003500 impl ToTokens for ExprReturn {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003501 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003502 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003503 self.return_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003504 self.expr.to_tokens(tokens);
3505 }
3506 }
3507
Michael Layzell734adb42017-06-07 16:58:31 -04003508 #[cfg(feature = "full")]
David Tolnay8c91b882017-12-28 23:04:32 -05003509 impl ToTokens for ExprMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003510 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003511 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003512 self.mac.to_tokens(tokens);
3513 }
3514 }
3515
3516 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003517 impl ToTokens for ExprStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003518 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003519 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003520 self.path.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003521 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003522 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003523 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003524 if self.rest.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -07003525 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003526 self.rest.to_tokens(tokens);
3527 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003528 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003529 }
3530 }
3531
Michael Layzell734adb42017-06-07 16:58:31 -04003532 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003533 impl ToTokens for ExprRepeat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003534 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003535 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003536 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003537 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003538 self.expr.to_tokens(tokens);
3539 self.semi_token.to_tokens(tokens);
David Tolnay84d80442018-01-07 01:03:20 -08003540 self.len.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003541 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003542 }
3543 }
3544
David Tolnaye98775f2017-12-28 23:17:00 -05003545 #[cfg(feature = "full")]
Michael Layzell93c36282017-06-04 20:43:14 -04003546 impl ToTokens for ExprGroup {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003547 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003548 outer_attrs_to_tokens(&self.attrs, tokens);
Michael Layzell93c36282017-06-04 20:43:14 -04003549 self.group_token.surround(tokens, |tokens| {
3550 self.expr.to_tokens(tokens);
3551 });
3552 }
3553 }
3554
Alex Crichton62a0a592017-05-22 13:58:53 -07003555 impl ToTokens for ExprParen {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003556 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003557 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003558 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003559 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003560 self.expr.to_tokens(tokens);
3561 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003562 }
3563 }
3564
Michael Layzell734adb42017-06-07 16:58:31 -04003565 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003566 impl ToTokens for ExprTry {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003567 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003568 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003569 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003570 self.question_token.to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003571 }
3572 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07003573
David Tolnay2ae520a2017-12-29 11:19:50 -05003574 impl ToTokens for ExprVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003575 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003576 self.tts.to_tokens(tokens);
3577 }
3578 }
3579
Michael Layzell734adb42017-06-07 16:58:31 -04003580 #[cfg(feature = "full")]
David Tolnaybcd498f2017-12-29 12:02:33 -05003581 impl ToTokens for Label {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003582 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaybcd498f2017-12-29 12:02:33 -05003583 self.name.to_tokens(tokens);
3584 self.colon_token.to_tokens(tokens);
3585 }
3586 }
3587
3588 #[cfg(feature = "full")]
David Tolnay055a7042016-10-02 19:23:54 -07003589 impl ToTokens for FieldValue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003590 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003591 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003592 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003593 if let Some(ref colon_token) = self.colon_token {
3594 colon_token.to_tokens(tokens);
David Tolnay276690f2016-10-30 12:06:59 -07003595 self.expr.to_tokens(tokens);
3596 }
David Tolnay055a7042016-10-02 19:23:54 -07003597 }
3598 }
3599
Michael Layzell734adb42017-06-07 16:58:31 -04003600 #[cfg(feature = "full")]
David Tolnayb4ad3b52016-10-01 21:58:13 -07003601 impl ToTokens for Arm {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003602 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003603 tokens.append_all(&self.attrs);
David Tolnay18cc4d42018-03-31 18:47:20 +02003604 self.leading_vert.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003605 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003606 if let Some((ref if_token, ref guard)) = self.guard {
3607 if_token.to_tokens(tokens);
3608 guard.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003609 }
David Tolnaydfb91432018-03-31 19:19:44 +02003610 self.fat_arrow_token.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003611 self.body.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003612 self.comma.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003613 }
3614 }
3615
Michael Layzell734adb42017-06-07 16:58:31 -04003616 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003617 impl ToTokens for PatWild {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003618 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003619 self.underscore_token.to_tokens(tokens);
3620 }
3621 }
3622
Michael Layzell734adb42017-06-07 16:58:31 -04003623 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003624 impl ToTokens for PatIdent {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003625 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay24237fb2017-12-29 02:15:26 -05003626 self.by_ref.to_tokens(tokens);
David Tolnayefc96fb2017-12-29 02:03:15 -05003627 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003628 self.ident.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003629 if let Some((ref at_token, ref subpat)) = self.subpat {
3630 at_token.to_tokens(tokens);
3631 subpat.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003632 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003633 }
3634 }
3635
Michael Layzell734adb42017-06-07 16:58:31 -04003636 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003637 impl ToTokens for PatStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003638 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003639 self.path.to_tokens(tokens);
3640 self.brace_token.surround(tokens, |tokens| {
3641 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003642 // NOTE: We need a comma before the dot2 token if it is present.
3643 if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003644 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003645 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003646 self.dot2_token.to_tokens(tokens);
3647 });
3648 }
3649 }
3650
Michael Layzell734adb42017-06-07 16:58:31 -04003651 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003652 impl ToTokens for PatTupleStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003653 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003654 self.path.to_tokens(tokens);
3655 self.pat.to_tokens(tokens);
3656 }
3657 }
3658
Michael Layzell734adb42017-06-07 16:58:31 -04003659 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003660 impl ToTokens for PatPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003661 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003662 ::PathTokens(&self.qself, &self.path).to_tokens(tokens);
3663 }
3664 }
3665
Michael Layzell734adb42017-06-07 16:58:31 -04003666 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003667 impl ToTokens for PatTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003668 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003669 self.paren_token.surround(tokens, |tokens| {
David Tolnay41871922017-12-29 01:53:45 -05003670 self.front.to_tokens(tokens);
3671 if let Some(ref dot2_token) = self.dot2_token {
3672 if !self.front.empty_or_trailing() {
3673 // Ensure there is a comma before the .. token.
David Tolnayf8db7ba2017-11-11 22:52:16 -08003674 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003675 }
David Tolnay41871922017-12-29 01:53:45 -05003676 dot2_token.to_tokens(tokens);
3677 self.comma_token.to_tokens(tokens);
3678 if self.comma_token.is_none() && !self.back.is_empty() {
3679 // Ensure there is a comma after the .. token.
3680 <Token![,]>::default().to_tokens(tokens);
3681 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07003682 }
David Tolnay41871922017-12-29 01:53:45 -05003683 self.back.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003684 });
3685 }
3686 }
3687
Michael Layzell734adb42017-06-07 16:58:31 -04003688 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003689 impl ToTokens for PatBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003690 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003691 self.box_token.to_tokens(tokens);
3692 self.pat.to_tokens(tokens);
3693 }
3694 }
3695
Michael Layzell734adb42017-06-07 16:58:31 -04003696 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003697 impl ToTokens for PatRef {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003698 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003699 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003700 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003701 self.pat.to_tokens(tokens);
3702 }
3703 }
3704
Michael Layzell734adb42017-06-07 16:58:31 -04003705 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003706 impl ToTokens for PatLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003707 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003708 self.expr.to_tokens(tokens);
3709 }
3710 }
3711
Michael Layzell734adb42017-06-07 16:58:31 -04003712 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003713 impl ToTokens for PatRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003714 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003715 self.lo.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003716 match self.limits {
3717 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
David Tolnay7ac699c2018-08-24 14:00:58 -04003718 RangeLimits::Closed(ref t) => Token![...](t.spans).to_tokens(tokens),
David Tolnay475288a2017-12-19 22:59:44 -08003719 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003720 self.hi.to_tokens(tokens);
3721 }
3722 }
3723
Michael Layzell734adb42017-06-07 16:58:31 -04003724 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003725 impl ToTokens for PatSlice {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003726 fn to_tokens(&self, tokens: &mut TokenStream) {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003727 // XXX: This is a mess, and it will be so easy to screw it up. How
3728 // do we make this correct itself better?
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003729 self.bracket_token.surround(tokens, |tokens| {
3730 self.front.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003731
3732 // If we need a comma before the middle or standalone .. token,
3733 // then make sure it's present.
David Tolnay51382052017-12-27 13:46:21 -05003734 if !self.front.empty_or_trailing()
3735 && (self.middle.is_some() || self.dot2_token.is_some())
Michael Layzell3936ceb2017-07-08 00:28:36 -04003736 {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003737 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003738 }
3739
3740 // If we have an identifier, we always need a .. token.
3741 if self.middle.is_some() {
3742 self.middle.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -07003743 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003744 } else if self.dot2_token.is_some() {
3745 self.dot2_token.to_tokens(tokens);
3746 }
3747
3748 // Make sure we have a comma before the back half.
3749 if !self.back.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07003750 TokensOrDefault(&self.comma_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003751 self.back.to_tokens(tokens);
3752 } else {
3753 self.comma_token.to_tokens(tokens);
3754 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003755 })
David Tolnayb4ad3b52016-10-01 21:58:13 -07003756 }
3757 }
3758
Michael Layzell734adb42017-06-07 16:58:31 -04003759 #[cfg(feature = "full")]
David Tolnay323279a2017-12-29 11:26:32 -05003760 impl ToTokens for PatMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003761 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay323279a2017-12-29 11:26:32 -05003762 self.mac.to_tokens(tokens);
3763 }
3764 }
3765
3766 #[cfg(feature = "full")]
David Tolnay2ae520a2017-12-29 11:19:50 -05003767 impl ToTokens for PatVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003768 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003769 self.tts.to_tokens(tokens);
3770 }
3771 }
3772
3773 #[cfg(feature = "full")]
David Tolnay8d9e81a2016-10-03 22:36:32 -07003774 impl ToTokens for FieldPat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003775 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay5d7098a2017-12-29 01:35:24 -05003776 if let Some(ref colon_token) = self.colon_token {
David Tolnay85b69a42017-12-27 20:43:10 -05003777 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003778 colon_token.to_tokens(tokens);
David Tolnay8d9e81a2016-10-03 22:36:32 -07003779 }
3780 self.pat.to_tokens(tokens);
3781 }
3782 }
3783
Michael Layzell734adb42017-06-07 16:58:31 -04003784 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003785 impl ToTokens for Block {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003786 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003787 self.brace_token.surround(tokens, |tokens| {
3788 tokens.append_all(&self.stmts);
3789 });
David Tolnay42602292016-10-01 22:25:45 -07003790 }
3791 }
3792
Michael Layzell734adb42017-06-07 16:58:31 -04003793 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003794 impl ToTokens for Stmt {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003795 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay42602292016-10-01 22:25:45 -07003796 match *self {
David Tolnay191e0582016-10-02 18:31:09 -07003797 Stmt::Local(ref local) => local.to_tokens(tokens),
David Tolnay42602292016-10-01 22:25:45 -07003798 Stmt::Item(ref item) => item.to_tokens(tokens),
3799 Stmt::Expr(ref expr) => expr.to_tokens(tokens),
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003800 Stmt::Semi(ref expr, ref semi) => {
David Tolnay42602292016-10-01 22:25:45 -07003801 expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003802 semi.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -07003803 }
David Tolnay42602292016-10-01 22:25:45 -07003804 }
3805 }
3806 }
David Tolnay191e0582016-10-02 18:31:09 -07003807
Michael Layzell734adb42017-06-07 16:58:31 -04003808 #[cfg(feature = "full")]
David Tolnay191e0582016-10-02 18:31:09 -07003809 impl ToTokens for Local {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003810 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003811 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003812 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003813 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003814 if let Some((ref colon_token, ref ty)) = self.ty {
3815 colon_token.to_tokens(tokens);
3816 ty.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003817 }
David Tolnay8b4d3022017-12-29 12:11:10 -05003818 if let Some((ref eq_token, ref init)) = self.init {
3819 eq_token.to_tokens(tokens);
3820 init.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003821 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003822 self.semi_token.to_tokens(tokens);
David Tolnay191e0582016-10-02 18:31:09 -07003823 }
3824 }
David Tolnayf4bbbd92016-09-23 14:41:55 -07003825}