blob: c22683a18330a9cdaa15f0f65aaab51d52ad1552 [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 Tolnaybcf26022017-12-25 22:10:52 -05001039 // When we're parsing expressions which occur before blocks, like in an if
1040 // statement's condition, we cannot parse a struct literal.
1041 //
1042 // Struct literals are ambiguous in certain positions
1043 // https://github.com/rust-lang/rfcs/pull/92
David Tolnay9389c382018-08-27 09:13:37 -07001044 #[derive(Copy, Clone)]
1045 pub struct AllowStruct(bool);
1046
1047 #[derive(Copy, Clone)]
1048 pub struct AllowBlock(bool);
David Tolnayaf2557e2016-10-24 11:52:21 -07001049
David Tolnay01218d12018-08-29 18:13:07 -07001050 #[derive(Copy, Clone, PartialEq, PartialOrd)]
1051 enum Precedence {
1052 Any,
1053 Assign,
1054 Placement,
1055 Range,
1056 Or,
1057 And,
1058 Compare,
1059 BitOr,
1060 BitXor,
1061 BitAnd,
1062 Shift,
1063 Arithmetic,
1064 Term,
1065 Cast,
1066 }
1067
1068 impl Precedence {
1069 fn of(op: &BinOp) -> Self {
1070 match *op {
1071 BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic,
1072 BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term,
1073 BinOp::And(_) => Precedence::And,
1074 BinOp::Or(_) => Precedence::Or,
1075 BinOp::BitXor(_) => Precedence::BitXor,
1076 BinOp::BitAnd(_) => Precedence::BitAnd,
1077 BinOp::BitOr(_) => Precedence::BitOr,
1078 BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
1079 BinOp::Eq(_) | BinOp::Lt(_) | BinOp::Le(_) | BinOp::Ne(_) | BinOp::Ge(_) | BinOp::Gt(_) => Precedence::Compare,
1080 BinOp::AddEq(_) | BinOp::SubEq(_) | BinOp::MulEq(_) | BinOp::DivEq(_) | BinOp::RemEq(_) | BinOp::BitXorEq(_) | BinOp::BitAndEq(_) | BinOp::BitOrEq(_) | BinOp::ShlEq(_) | BinOp::ShrEq(_) => Precedence::Assign,
1081 }
1082 }
1083 }
1084
David Tolnay9389c382018-08-27 09:13:37 -07001085 impl Parse for Expr {
1086 fn parse(input: ParseStream) -> Result<Self> {
1087 ambiguous_expr(input, AllowStruct(true), AllowBlock(true))
Alex Crichton954046c2017-05-30 21:49:42 -07001088 }
1089 }
1090
Michael Layzell734adb42017-06-07 16:58:31 -04001091 #[cfg(feature = "full")]
David Tolnay9fb0aed2018-08-27 10:23:12 -07001092 fn expr_no_struct(input: ParseStream) -> Result<Expr> {
1093 ambiguous_expr(input, AllowStruct(false), AllowBlock(true))
1094 }
David Tolnayaf2557e2016-10-24 11:52:21 -07001095
David Tolnay01218d12018-08-29 18:13:07 -07001096 #[cfg(feature = "full")]
1097 fn parse_expr(input: ParseStream, mut lhs: Expr, allow_struct: AllowStruct, allow_block: AllowBlock, base: Precedence) -> Result<Expr> {
1098 loop {
1099 if input.fork().parse::<BinOp>().ok().map_or(false, |op| Precedence::of(&op) >= base) {
1100 let op: BinOp = input.parse()?;
1101 let precedence = Precedence::of(&op);
1102 let mut rhs = unary_expr(input, allow_struct, allow_block)?;
1103 loop {
1104 let next = peek_precedence(input);
1105 if next > precedence || next == precedence && precedence == Precedence::Assign {
1106 rhs = parse_expr(input, rhs, allow_struct, allow_block, next)?;
1107 } else {
1108 break;
1109 }
1110 }
1111 lhs = Expr::Binary(ExprBinary {
1112 attrs: Vec::new(),
1113 left: Box::new(lhs),
1114 op: op,
1115 right: Box::new(rhs),
1116 });
1117 } else if Precedence::Assign >= base && input.peek(Token![=]) && !input.peek(Token![==]) && !input.peek(Token![=>]) {
1118 let eq_token: Token![=] = input.parse()?;
1119 let mut rhs = unary_expr(input, allow_struct, allow_block)?;
1120 loop {
1121 let next = peek_precedence(input);
1122 if next >= Precedence::Assign {
1123 rhs = parse_expr(input, rhs, allow_struct, allow_block, next)?;
1124 } else {
1125 break;
1126 }
1127 }
1128 lhs = Expr::Assign(ExprAssign {
1129 attrs: Vec::new(),
1130 left: Box::new(lhs),
1131 eq_token: eq_token,
1132 right: Box::new(rhs),
1133 });
1134 } else if Precedence::Placement >= base && input.peek(Token![<-]) {
1135 let arrow_token: Token![<-] = input.parse()?;
1136 let mut rhs = unary_expr(input, allow_struct, allow_block)?;
1137 loop {
1138 let next = peek_precedence(input);
1139 if next > Precedence::Placement {
1140 rhs = parse_expr(input, rhs, allow_struct, allow_block, next)?;
1141 } else {
1142 break;
1143 }
1144 }
1145 lhs = Expr::InPlace(ExprInPlace {
1146 attrs: Vec::new(),
1147 place: Box::new(lhs),
1148 arrow_token: arrow_token,
1149 value: Box::new(rhs),
1150 });
1151 } else if Precedence::Range >= base && input.peek(Token![..]) {
1152 let limits: RangeLimits = input.parse()?;
1153 let rhs = if input.is_empty()
1154 || input.peek(Token![,])
1155 || input.peek(Token![;])
1156 || !allow_struct.0 && input.peek(token::Brace)
1157 {
1158 None
1159 } else {
1160 // We don't want to allow blocks in the rhs if we don't
1161 // allow structs.
1162 let allow_block = AllowBlock(allow_struct.0);
1163 let mut rhs = unary_expr(input, allow_struct, allow_block)?;
1164 loop {
1165 let next = peek_precedence(input);
1166 if next > Precedence::Range {
1167 rhs = parse_expr(input, rhs, allow_struct, allow_block, next)?;
1168 } else {
1169 break;
1170 }
1171 }
1172 Some(rhs)
1173 };
1174 lhs = Expr::Range(ExprRange {
1175 attrs: Vec::new(),
1176 from: Some(Box::new(lhs)),
1177 limits: limits,
1178 to: rhs.map(Box::new),
1179 });
1180 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1181 let as_token: Token![as] = input.parse()?;
1182 let ty = input.call(Type::without_plus)?;
1183 lhs = Expr::Cast(ExprCast {
1184 attrs: Vec::new(),
1185 expr: Box::new(lhs),
1186 as_token: as_token,
1187 ty: Box::new(ty),
1188 });
1189 } else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) {
1190 let colon_token: Token![:] = input.parse()?;
1191 let ty = input.call(Type::without_plus)?;
1192 lhs = Expr::Type(ExprType {
1193 attrs: Vec::new(),
1194 expr: Box::new(lhs),
1195 colon_token: colon_token,
1196 ty: Box::new(ty),
1197 });
1198 } else {
1199 break;
1200 }
1201 }
1202 Ok(lhs)
1203 }
1204
David Tolnay3e541292018-08-30 11:42:15 -07001205 #[cfg(not(feature = "full"))]
1206 fn parse_expr(input: ParseStream, mut lhs: Expr, allow_struct: AllowStruct, allow_block: AllowBlock, base: Precedence) -> Result<Expr> {
1207 loop {
1208 if input.fork().parse::<BinOp>().ok().map_or(false, |op| Precedence::of(&op) >= base) {
1209 let op: BinOp = input.parse()?;
1210 let precedence = Precedence::of(&op);
1211 let mut rhs = unary_expr(input, allow_struct, allow_block)?;
1212 loop {
1213 let next = peek_precedence(input);
1214 if next > precedence || next == precedence && precedence == Precedence::Assign {
1215 rhs = parse_expr(input, rhs, allow_struct, allow_block, next)?;
1216 } else {
1217 break;
1218 }
1219 }
1220 lhs = Expr::Binary(ExprBinary {
1221 attrs: Vec::new(),
1222 left: Box::new(lhs),
1223 op: op,
1224 right: Box::new(rhs),
1225 });
1226 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1227 let as_token: Token![as] = input.parse()?;
1228 let ty = input.call(Type::without_plus)?;
1229 lhs = Expr::Cast(ExprCast {
1230 attrs: Vec::new(),
1231 expr: Box::new(lhs),
1232 as_token: as_token,
1233 ty: Box::new(ty),
1234 });
1235 } else {
1236 break;
1237 }
1238 }
1239 Ok(lhs)
1240 }
1241
David Tolnay01218d12018-08-29 18:13:07 -07001242 fn peek_precedence(input: ParseStream) -> Precedence {
1243 if let Ok(op) = input.fork().parse() {
1244 Precedence::of(&op)
David Tolnay3e541292018-08-30 11:42:15 -07001245 } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
David Tolnay01218d12018-08-29 18:13:07 -07001246 Precedence::Assign
1247 } else if input.peek(Token![<-]) {
1248 Precedence::Placement
1249 } else if input.peek(Token![..]) {
1250 Precedence::Range
1251 } else if input.peek(Token![as]) || input.peek(Token![:]) && !input.peek(Token![::]) {
1252 Precedence::Cast
1253 } else {
1254 Precedence::Any
1255 }
1256 }
1257
David Tolnaybcf26022017-12-25 22:10:52 -05001258 // Parse an arbitrary expression.
David Tolnay60291082018-08-28 09:54:49 -07001259 fn ambiguous_expr(
1260 input: ParseStream,
1261 allow_struct: AllowStruct,
1262 allow_block: AllowBlock,
1263 ) -> Result<Expr> {
David Tolnay01218d12018-08-29 18:13:07 -07001264 let lhs = unary_expr(input, allow_struct, allow_block)?;
1265 parse_expr(input, lhs, allow_struct, allow_block, Precedence::Any)
Michael Layzellb78f3b52017-06-04 19:03:03 -04001266 }
1267
David Tolnaybcf26022017-12-25 22:10:52 -05001268 // <UnOp> <trailer>
1269 // & <trailer>
1270 // &mut <trailer>
1271 // box <trailer>
Michael Layzell734adb42017-06-07 16:58:31 -04001272 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001273 fn unary_expr(
1274 input: ParseStream,
1275 allow_struct: AllowStruct,
1276 allow_block: AllowBlock,
1277 ) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001278 let ahead = input.fork();
1279 ahead.call(Attribute::parse_outer)?;
1280 if ahead.peek(Token![&])
1281 || ahead.peek(Token![box])
1282 || ahead.peek(Token![*])
1283 || ahead.peek(Token![!])
1284 || ahead.peek(Token![-])
1285 {
1286 let attrs = input.call(Attribute::parse_outer)?;
1287 if input.peek(Token![&]) {
1288 Ok(Expr::Reference(ExprReference {
1289 attrs: attrs,
1290 and_token: input.parse()?,
1291 mutability: input.parse()?,
1292 expr: Box::new(unary_expr(input, allow_struct, AllowBlock(true))?),
1293 }))
1294 } else if input.peek(Token![box]) {
1295 Ok(Expr::Box(ExprBox {
1296 attrs: attrs,
1297 box_token: input.parse()?,
1298 expr: Box::new(unary_expr(input, allow_struct, AllowBlock(true))?),
1299 }))
1300 } else {
1301 Ok(Expr::Unary(ExprUnary {
1302 attrs: attrs,
1303 op: input.parse()?,
1304 expr: Box::new(unary_expr(input, allow_struct, AllowBlock(true))?),
1305 }))
1306 }
1307 } else {
1308 trailer_expr(input, allow_struct, allow_block)
1309 }
1310 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001311
Michael Layzell734adb42017-06-07 16:58:31 -04001312 // XXX: This duplication is ugly
1313 #[cfg(not(feature = "full"))]
David Tolnay60291082018-08-28 09:54:49 -07001314 fn unary_expr(
1315 input: ParseStream,
1316 allow_struct: AllowStruct,
1317 allow_block: AllowBlock,
1318 ) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001319 let ahead = input.fork();
1320 ahead.call(Attribute::parse_outer)?;
1321 if ahead.peek(Token![*]) || ahead.peek(Token![!]) || ahead.peek(Token![-]) {
1322 Ok(Expr::Unary(ExprUnary {
1323 attrs: input.call(Attribute::parse_outer)?,
1324 op: input.parse()?,
1325 expr: Box::new(unary_expr(input, allow_struct, AllowBlock(true))?),
1326 }))
1327 } else {
1328 trailer_expr(input, allow_struct, allow_block)
1329 }
1330 }
Michael Layzell734adb42017-06-07 16:58:31 -04001331
David Tolnayd997aef2018-07-21 18:42:31 -07001332 #[cfg(feature = "full")]
David Tolnay5d314dc2018-07-21 16:40:01 -07001333 fn take_outer(attrs: &mut Vec<Attribute>) -> Vec<Attribute> {
1334 let mut outer = Vec::new();
1335 let mut inner = Vec::new();
1336 for attr in mem::replace(attrs, Vec::new()) {
1337 match attr.style {
1338 AttrStyle::Outer => outer.push(attr),
1339 AttrStyle::Inner(_) => inner.push(attr),
1340 }
1341 }
1342 *attrs = inner;
1343 outer
1344 }
1345
David Tolnaybcf26022017-12-25 22:10:52 -05001346 // <atom> (..<args>) ...
1347 // <atom> . <ident> (..<args>) ...
1348 // <atom> . <ident> ...
1349 // <atom> . <lit> ...
1350 // <atom> [ <expr> ] ...
1351 // <atom> ? ...
Michael Layzell734adb42017-06-07 16:58:31 -04001352 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001353 fn trailer_expr(
1354 input: ParseStream,
1355 allow_struct: AllowStruct,
1356 allow_block: AllowBlock,
1357 ) -> Result<Expr> {
David Tolnay1501f7e2018-08-27 14:21:03 -07001358 let mut e = atom_expr(input, allow_struct, allow_block)?;
1359
1360 let mut attrs = e.replace_attrs(Vec::new());
1361 let outer_attrs = take_outer(&mut attrs);
1362 e.replace_attrs(attrs);
1363
David Tolnay01218d12018-08-29 18:13:07 -07001364 e = trailer_helper(input, e)?;
1365
1366 let mut attrs = outer_attrs;
1367 attrs.extend(e.replace_attrs(Vec::new()));
1368 e.replace_attrs(attrs);
1369 Ok(e)
1370 }
1371
1372 #[cfg(feature = "full")]
1373 fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
David Tolnay1501f7e2018-08-27 14:21:03 -07001374 loop {
1375 if input.peek(token::Paren) {
1376 let content;
1377 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001378 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001379 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001380 paren_token: parenthesized!(content in input),
1381 args: content.parse_terminated(<Expr as Parse>::parse)?,
1382 });
1383 } else if input.peek(Token![.]) && !input.peek(Token![..]) {
1384 let dot_token: Token![.] = input.parse()?;
1385 let member: Member = input.parse()?;
1386 let turbofish = if member.is_named() && input.peek(Token![::]) {
1387 Some(MethodTurbofish {
1388 colon2_token: input.parse()?,
1389 lt_token: input.parse()?,
1390 args: {
1391 let mut args = Punctuated::new();
1392 loop {
1393 if input.peek(Token![>]) {
1394 break;
1395 }
1396 let value = input.parse()?;
1397 args.push_value(value);
1398 if input.peek(Token![>]) {
1399 break;
1400 }
1401 let punct = input.parse()?;
1402 args.push_punct(punct);
1403 }
1404 args
1405 },
1406 gt_token: input.parse()?,
1407 })
1408 } else {
1409 None
1410 };
1411
1412 if turbofish.is_some() || input.peek(token::Paren) {
1413 if let Member::Named(method) = member {
1414 let content;
1415 e = Expr::MethodCall(ExprMethodCall {
1416 attrs: Vec::new(),
1417 receiver: Box::new(e),
1418 dot_token: dot_token,
1419 method: method,
1420 turbofish: turbofish,
1421 paren_token: parenthesized!(content in input),
1422 args: content.parse_terminated(<Expr as Parse>::parse)?,
1423 });
1424 continue;
1425 }
1426 }
1427
1428 e = Expr::Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -05001429 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001430 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001431 dot_token: dot_token,
David Tolnay85b69a42017-12-27 20:43:10 -05001432 member: member,
David Tolnay1501f7e2018-08-27 14:21:03 -07001433 });
1434 } else if input.peek(token::Bracket) {
1435 let content;
1436 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001437 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001438 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001439 bracket_token: bracketed!(content in input),
1440 index: content.parse()?,
1441 });
1442 } else if input.peek(Token![?]) {
1443 e = Expr::Try(ExprTry {
David Tolnay8c91b882017-12-28 23:04:32 -05001444 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001445 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001446 question_token: input.parse()?,
1447 });
1448 } else {
1449 break;
1450 }
1451 }
David Tolnay1501f7e2018-08-27 14:21:03 -07001452 Ok(e)
1453 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001454
Michael Layzell734adb42017-06-07 16:58:31 -04001455 // XXX: Duplication == ugly
1456 #[cfg(not(feature = "full"))]
David Tolnay60291082018-08-28 09:54:49 -07001457 fn trailer_expr(
1458 input: ParseStream,
1459 allow_struct: AllowStruct,
1460 allow_block: AllowBlock,
1461 ) -> Result<Expr> {
David Tolnay1501f7e2018-08-27 14:21:03 -07001462 let mut e = atom_expr(input, allow_struct, allow_block)?;
1463
1464 loop {
1465 if input.peek(token::Paren) {
1466 let content;
1467 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001468 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001469 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001470 paren_token: parenthesized!(content in input),
1471 args: content.parse_terminated(<Expr as Parse>::parse)?,
1472 });
1473 } else if input.peek(Token![.]) {
1474 e = Expr::Field(ExprField {
David Tolnayd5147742018-06-30 10:09:52 -07001475 attrs: Vec::new(),
1476 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001477 dot_token: input.parse()?,
1478 member: input.parse()?,
1479 });
1480 } else if input.peek(token::Bracket) {
1481 let content;
1482 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001483 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001484 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001485 bracket_token: bracketed!(content in input),
1486 index: content.parse()?,
1487 });
1488 } else {
1489 break;
1490 }
1491 }
1492
1493 Ok(e)
1494 }
Michael Layzell734adb42017-06-07 16:58:31 -04001495
David Tolnaya454c8f2018-01-07 01:01:10 -08001496 // Parse all atomic expressions which don't have to worry about precedence
David Tolnaybcf26022017-12-25 22:10:52 -05001497 // interactions, as they are fully contained.
Michael Layzell734adb42017-06-07 16:58:31 -04001498 #[cfg(feature = "full")]
David Tolnay6e1e5052018-08-30 10:21:48 -07001499 fn atom_expr(input: ParseStream, allow_struct: AllowStruct, allow_block: AllowBlock) -> Result<Expr> {
1500 if input.peek(token::Group) {
1501 return input.parse().map(Expr::Group);
1502 }
1503
1504 let mut attrs = input.call(Attribute::parse_outer)?;
1505
1506 let mut expr = if input.peek(token::Group) {
1507 Expr::Group(input.parse()?)
1508 } else if input.peek(Lit) {
1509 Expr::Lit(input.parse()?)
1510 } else if input.peek(Token![async])
1511 && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
1512 {
1513 Expr::Async(input.parse()?)
1514 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
1515 Expr::TryBlock(input.parse()?)
1516 } else if input.peek(Token![|])
1517 || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1518 || input.peek(Token![static])
1519 || input.peek(Token![move])
1520 {
1521 Expr::Closure(expr_closure(input, allow_struct)?)
1522 } else if input.peek(Ident)
1523 || input.peek(Token![::])
1524 || input.peek(Token![<])
1525 || input.peek(Token![self])
1526 || input.peek(Token![Self])
1527 || input.peek(Token![super])
1528 || input.peek(Token![extern])
1529 || input.peek(Token![crate])
1530 {
1531 path_or_macro_or_struct(input, allow_struct)?
1532 } else if input.peek(token::Paren) {
1533 paren_or_tuple(input)?
1534 } else if input.peek(Token![break]) {
1535 Expr::Break(expr_break(input, allow_struct)?)
1536 } else if input.peek(Token![continue]) {
1537 Expr::Continue(input.parse()?)
1538 } else if input.peek(Token![return]) {
1539 Expr::Return(expr_ret(input, allow_struct)?)
1540 } else if input.peek(token::Bracket) {
1541 array_or_repeat(input)?
1542 } else if input.peek(Token![if]) {
1543 if input.peek2(Token![let]) {
1544 Expr::IfLet(input.parse()?)
1545 } else {
1546 Expr::If(input.parse()?)
1547 }
1548 } else if input.peek(Token![while]) {
1549 if input.peek2(Token![let]) {
1550 Expr::WhileLet(input.parse()?)
1551 } else {
1552 Expr::While(input.parse()?)
1553 }
1554 } else if input.peek(Token![for]) {
1555 Expr::ForLoop(input.parse()?)
1556 } else if input.peek(Token![loop]) {
1557 Expr::Loop(input.parse()?)
1558 } else if input.peek(Token![match]) {
1559 Expr::Match(input.parse()?)
1560 } else if input.peek(Token![yield]) {
1561 Expr::Yield(input.parse()?)
1562 } else if input.peek(Token![unsafe]) {
1563 Expr::Unsafe(input.parse()?)
1564 } else if allow_block.0 && input.peek(token::Brace) {
1565 Expr::Block(input.parse()?)
1566 } else if input.peek(Token![..]) {
1567 Expr::Range(expr_range(input, allow_struct)?)
1568 } else if input.peek(Lifetime) {
1569 let the_label: Label = input.parse()?;
1570 let mut expr = if input.peek(Token![while]) {
1571 if input.peek2(Token![let]) {
1572 Expr::WhileLet(input.parse()?)
1573 } else {
1574 Expr::While(input.parse()?)
1575 }
1576 } else if input.peek(Token![for]) {
1577 Expr::ForLoop(input.parse()?)
1578 } else if input.peek(Token![loop]) {
1579 Expr::Loop(input.parse()?)
1580 } else if input.peek(token::Brace) {
1581 Expr::Block(input.parse()?)
1582 } else {
1583 return Err(input.error("expected loop or block expression"));
1584 };
1585 match expr {
1586 Expr::WhileLet(ExprWhileLet { ref mut label, .. }) |
1587 Expr::While(ExprWhile { ref mut label, .. }) |
1588 Expr::ForLoop(ExprForLoop { ref mut label, .. }) |
1589 Expr::Loop(ExprLoop { ref mut label, .. }) |
1590 Expr::Block(ExprBlock { ref mut label, .. }) => *label = Some(the_label),
1591 _ => unreachable!(),
1592 }
1593 expr
1594 } else {
1595 return Err(input.error("expected expression"));
1596 };
1597
1598 attrs.extend(expr.replace_attrs(Vec::new()));
1599 expr.replace_attrs(attrs);
1600 Ok(expr)
1601 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001602
Michael Layzell734adb42017-06-07 16:58:31 -04001603 #[cfg(not(feature = "full"))]
David Tolnay3e541292018-08-30 11:42:15 -07001604 fn atom_expr(input: ParseStream, _allow_struct: AllowStruct, _allow_block: AllowBlock) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001605 if input.peek(Lit) {
1606 input.parse().map(Expr::Lit)
1607 } else if input.peek(token::Paren) {
1608 input.parse().map(Expr::Paren)
1609 } else if input.peek(Ident)
1610 || input.peek(Token![::])
1611 || input.peek(Token![<])
1612 || input.peek(Token![self])
1613 || input.peek(Token![Self])
1614 || input.peek(Token![super])
1615 || input.peek(Token![extern])
1616 || input.peek(Token![crate])
1617 {
1618 input.parse().map(Expr::Path)
1619 } else {
1620 Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
1621 }
1622 }
1623
1624 #[cfg(feature = "full")]
1625 fn path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1626 let expr: ExprPath = input.parse()?;
1627 if expr.qself.is_some() {
1628 return Ok(Expr::Path(expr));
1629 }
1630
1631 if input.peek(Token![!]) && !input.peek(Token![!=]) {
1632 let mut contains_arguments = false;
1633 for segment in &expr.path.segments {
1634 match segment.arguments {
1635 PathArguments::None => {}
1636 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
1637 contains_arguments = true;
1638 }
1639 }
1640 }
1641
1642 if !contains_arguments {
1643 let bang_token: Token![!] = input.parse()?;
1644 let (delimiter, tts) = mac::parse_delimiter(input)?;
1645 return Ok(Expr::Macro(ExprMacro {
1646 attrs: Vec::new(),
1647 mac: Macro {
1648 path: expr.path,
1649 bang_token: bang_token,
1650 delimiter: delimiter,
1651 tts: tts,
1652 },
1653 }));
1654 }
1655 }
1656
1657 if allow_struct.0 && input.peek(token::Brace) {
1658 let outer_attrs = Vec::new();
1659 expr_struct_helper(input, outer_attrs, expr.path).map(Expr::Struct)
1660 } else {
1661 Ok(Expr::Path(expr))
1662 }
1663 }
1664
1665 #[cfg(feature = "full")]
1666 fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
1667 let content;
1668 let paren_token = parenthesized!(content in input);
1669 let inner_attrs = content.call(Attribute::parse_inner)?;
1670 if content.is_empty() {
1671 return Ok(Expr::Tuple(ExprTuple {
1672 attrs: inner_attrs,
1673 paren_token: paren_token,
1674 elems: Punctuated::new(),
1675 }));
1676 }
1677
1678 let first: Expr = content.parse()?;
1679 if content.is_empty() {
1680 return Ok(Expr::Paren(ExprParen {
1681 attrs: inner_attrs,
1682 paren_token: paren_token,
1683 expr: Box::new(first),
1684 }));
1685 }
1686
1687 let mut elems = Punctuated::new();
1688 elems.push_value(first);
1689 while !content.is_empty() {
1690 let punct = content.parse()?;
1691 elems.push_punct(punct);
1692 if content.is_empty() {
1693 break;
1694 }
1695 let value = content.parse()?;
1696 elems.push_value(value);
1697 }
1698 Ok(Expr::Tuple(ExprTuple {
1699 attrs: inner_attrs,
1700 paren_token: paren_token,
1701 elems: elems,
1702 }))
1703 }
1704
1705 #[cfg(feature = "full")]
1706 fn array_or_repeat(input: ParseStream) -> Result<Expr> {
1707 let content;
1708 let bracket_token = bracketed!(content in input);
1709 let inner_attrs = content.call(Attribute::parse_inner)?;
1710 if content.is_empty() {
1711 return Ok(Expr::Array(ExprArray {
1712 attrs: inner_attrs,
1713 bracket_token: bracket_token,
1714 elems: Punctuated::new(),
1715 }));
1716 }
1717
1718 let first: Expr = content.parse()?;
1719 if content.is_empty() || content.peek(Token![,]) {
1720 let mut elems = Punctuated::new();
1721 elems.push_value(first);
1722 while !content.is_empty() {
1723 let punct = content.parse()?;
1724 elems.push_punct(punct);
1725 if content.is_empty() {
1726 break;
1727 }
1728 let value = content.parse()?;
1729 elems.push_value(value);
1730 }
1731 Ok(Expr::Array(ExprArray {
1732 attrs: inner_attrs,
1733 bracket_token: bracket_token,
1734 elems: elems,
1735 }))
1736 } else if content.peek(Token![;]) {
1737 let semi_token: Token![;] = content.parse()?;
1738 let len: Expr = content.parse()?;
1739 Ok(Expr::Repeat(ExprRepeat {
1740 attrs: inner_attrs,
1741 bracket_token: bracket_token,
1742 expr: Box::new(first),
1743 semi_token: semi_token,
1744 len: Box::new(len),
1745 }))
1746 } else {
1747 Err(content.error("expected `,` or `;`"))
1748 }
1749 }
Michael Layzell734adb42017-06-07 16:58:31 -04001750
Michael Layzell734adb42017-06-07 16:58:31 -04001751 #[cfg(feature = "full")]
David Tolnay01218d12018-08-29 18:13:07 -07001752 fn expr_early(input: ParseStream) -> Result<Expr> {
1753 let mut attrs = input.call(Attribute::parse_outer)?;
1754 let mut expr = if input.peek(Token![if]) {
1755 if input.peek2(Token![let]) {
1756 Expr::IfLet(input.parse()?)
1757 } else {
1758 Expr::If(input.parse()?)
1759 }
1760 } else if input.peek(Token![while]) {
1761 if input.peek2(Token![let]) {
1762 Expr::WhileLet(input.parse()?)
1763 } else {
1764 Expr::While(input.parse()?)
1765 }
1766 } else if input.peek(Token![for]) {
1767 Expr::ForLoop(input.parse()?)
1768 } else if input.peek(Token![loop]) {
1769 Expr::Loop(input.parse()?)
1770 } else if input.peek(Token![match]) {
1771 Expr::Match(input.parse()?)
1772 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
1773 Expr::TryBlock(input.parse()?)
1774 } else if input.peek(Token![unsafe]) {
1775 Expr::Unsafe(input.parse()?)
1776 } else if input.peek(token::Brace) {
1777 Expr::Block(input.parse()?)
1778 } else {
1779 let allow_struct = AllowStruct(true);
1780 let allow_block = AllowBlock(true);
1781 let mut expr = unary_expr(input, allow_struct, allow_block)?;
1782
1783 attrs.extend(expr.replace_attrs(Vec::new()));
1784 expr.replace_attrs(attrs);
1785
1786 return parse_expr(input, expr, allow_struct, allow_block, Precedence::Any);
1787 };
1788
1789 if input.peek(Token![.]) || input.peek(Token![?]) {
1790 expr = trailer_helper(input, expr)?;
1791
1792 attrs.extend(expr.replace_attrs(Vec::new()));
1793 expr.replace_attrs(attrs);
1794
1795 let allow_struct = AllowStruct(true);
1796 let allow_block = AllowBlock(true);
1797 return parse_expr(input, expr, allow_struct, allow_block, Precedence::Any);
1798 }
1799
1800 attrs.extend(expr.replace_attrs(Vec::new()));
1801 expr.replace_attrs(attrs);
1802 Ok(expr)
1803 }
Michael Layzell35418782017-06-07 09:20:25 -04001804
David Tolnay60291082018-08-28 09:54:49 -07001805 impl Parse for ExprLit {
David Tolnayeb981bb2018-07-21 19:31:38 -07001806 #[cfg(not(feature = "full"))]
David Tolnay60291082018-08-28 09:54:49 -07001807 fn parse(input: ParseStream) -> Result<Self> {
1808 Ok(ExprLit {
David Tolnayeb981bb2018-07-21 19:31:38 -07001809 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07001810 lit: input.parse()?,
David Tolnayeb981bb2018-07-21 19:31:38 -07001811 })
David Tolnay60291082018-08-28 09:54:49 -07001812 }
David Tolnayeb981bb2018-07-21 19:31:38 -07001813
1814 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001815 fn parse(input: ParseStream) -> Result<Self> {
1816 Ok(ExprLit {
1817 attrs: input.call(Attribute::parse_outer)?,
1818 lit: input.parse()?,
David Tolnay8c91b882017-12-28 23:04:32 -05001819 })
David Tolnay60291082018-08-28 09:54:49 -07001820 }
David Tolnay8c91b882017-12-28 23:04:32 -05001821 }
1822
1823 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001824 impl Parse for ExprMacro {
1825 fn parse(input: ParseStream) -> Result<Self> {
1826 Ok(ExprMacro {
1827 attrs: input.call(Attribute::parse_outer)?,
1828 mac: input.parse()?,
David Tolnay8c91b882017-12-28 23:04:32 -05001829 })
David Tolnay60291082018-08-28 09:54:49 -07001830 }
David Tolnay8c91b882017-12-28 23:04:32 -05001831 }
1832
David Tolnaye98775f2017-12-28 23:17:00 -05001833 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001834 impl Parse for ExprGroup {
1835 fn parse(input: ParseStream) -> Result<Self> {
1836 let content;
1837 Ok(ExprGroup {
David Tolnay8c91b882017-12-28 23:04:32 -05001838 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07001839 group_token: grouped!(content in input),
1840 expr: content.parse()?,
David Tolnaybb4ca9f2017-12-26 12:28:58 -05001841 })
David Tolnay60291082018-08-28 09:54:49 -07001842 }
Michael Layzell93c36282017-06-04 20:43:14 -04001843 }
1844
David Tolnay60291082018-08-28 09:54:49 -07001845 impl Parse for ExprParen {
David Tolnayeb981bb2018-07-21 19:31:38 -07001846 #[cfg(not(feature = "full"))]
David Tolnay60291082018-08-28 09:54:49 -07001847 fn parse(input: ParseStream) -> Result<Self> {
1848 let content;
1849 Ok(ExprParen {
David Tolnayeb981bb2018-07-21 19:31:38 -07001850 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07001851 paren_token: parenthesized!(content in input),
1852 expr: content.parse()?,
David Tolnayeb981bb2018-07-21 19:31:38 -07001853 })
David Tolnay60291082018-08-28 09:54:49 -07001854 }
David Tolnayeb981bb2018-07-21 19:31:38 -07001855
1856 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001857 fn parse(input: ParseStream) -> Result<Self> {
1858 let outer_attrs = input.call(Attribute::parse_outer)?;
1859
1860 let content;
1861 let paren_token = parenthesized!(content in input);
1862 let inner_attrs = content.call(Attribute::parse_inner)?;
1863 let expr: Expr = content.parse()?;
1864
1865 Ok(ExprParen {
David Tolnay5d314dc2018-07-21 16:40:01 -07001866 attrs: {
1867 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07001868 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07001869 attrs
1870 },
David Tolnay60291082018-08-28 09:54:49 -07001871 paren_token: paren_token,
1872 expr: Box::new(expr),
David Tolnaybb4ca9f2017-12-26 12:28:58 -05001873 })
David Tolnay60291082018-08-28 09:54:49 -07001874 }
Alex Crichton954046c2017-05-30 21:49:42 -07001875 }
David Tolnay89e05672016-10-02 14:39:42 -07001876
Michael Layzell734adb42017-06-07 16:58:31 -04001877 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001878 impl Parse for ExprArray {
1879 fn parse(input: ParseStream) -> Result<Self> {
1880 let outer_attrs = input.call(Attribute::parse_outer)?;
1881
1882 let content;
1883 let bracket_token = bracketed!(content in input);
1884 let inner_attrs = content.call(Attribute::parse_inner)?;
1885 let elems = content.parse_terminated(<Expr as Parse>::parse)?;
1886
1887 Ok(ExprArray {
David Tolnay5d314dc2018-07-21 16:40:01 -07001888 attrs: {
1889 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07001890 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07001891 attrs
1892 },
David Tolnay60291082018-08-28 09:54:49 -07001893 bracket_token: bracket_token,
1894 elems: elems,
Michael Layzell92639a52017-06-01 00:07:44 -04001895 })
David Tolnay60291082018-08-28 09:54:49 -07001896 }
Alex Crichton954046c2017-05-30 21:49:42 -07001897 }
David Tolnayfa0edf22016-09-23 22:58:24 -07001898
Michael Layzell734adb42017-06-07 16:58:31 -04001899 #[cfg(feature = "full")]
David Tolnay1501f7e2018-08-27 14:21:03 -07001900 impl Parse for GenericMethodArgument {
David Tolnayd60cfec2017-12-29 00:21:38 -05001901 // TODO parse const generics as well
David Tolnay1501f7e2018-08-27 14:21:03 -07001902 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay60291082018-08-28 09:54:49 -07001903 input
1904 .parse_synom(ty_no_eq_after)
1905 .map(GenericMethodArgument::Type)
David Tolnay1501f7e2018-08-27 14:21:03 -07001906 }
David Tolnayd60cfec2017-12-29 00:21:38 -05001907 }
1908
1909 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001910 impl Parse for ExprTuple {
1911 fn parse(input: ParseStream) -> Result<Self> {
1912 let outer_attrs = input.call(Attribute::parse_outer)?;
1913
1914 let content;
1915 let paren_token = parenthesized!(content in input);
1916 let inner_attrs = content.call(Attribute::parse_inner)?;
1917 let elems = content.parse_terminated(<Expr as Parse>::parse)?;
1918
1919 Ok(ExprTuple {
David Tolnay5d314dc2018-07-21 16:40:01 -07001920 attrs: {
1921 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07001922 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07001923 attrs
1924 },
David Tolnay60291082018-08-28 09:54:49 -07001925 paren_token: paren_token,
1926 elems: elems,
Michael Layzell92639a52017-06-01 00:07:44 -04001927 })
David Tolnay60291082018-08-28 09:54:49 -07001928 }
Alex Crichton954046c2017-05-30 21:49:42 -07001929 }
David Tolnayfa0edf22016-09-23 22:58:24 -07001930
Michael Layzell734adb42017-06-07 16:58:31 -04001931 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001932 impl Parse for ExprIfLet {
1933 fn parse(input: ParseStream) -> Result<Self> {
1934 Ok(ExprIfLet {
David Tolnay8c91b882017-12-28 23:04:32 -05001935 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07001936 if_token: input.parse()?,
1937 let_token: input.parse()?,
1938 pats: {
1939 let mut pats = Punctuated::new();
1940 let value: Pat = input.parse()?;
1941 pats.push_value(value);
1942 while input.peek(Token![|])
1943 && !input.peek(Token![||])
1944 && !input.peek(Token![|=])
1945 {
1946 let punct = input.parse()?;
1947 pats.push_punct(punct);
1948 let value: Pat = input.parse()?;
1949 pats.push_value(value);
1950 }
1951 pats
Michael Layzell92639a52017-06-01 00:07:44 -04001952 },
David Tolnay60291082018-08-28 09:54:49 -07001953 eq_token: input.parse()?,
1954 expr: Box::new(input.call(expr_no_struct)?),
1955 then_branch: input.parse()?,
1956 else_branch: {
1957 if input.peek(Token![else]) {
1958 Some(input.call(else_block)?)
1959 } else {
1960 None
1961 }
1962 },
Michael Layzell92639a52017-06-01 00:07:44 -04001963 })
David Tolnay60291082018-08-28 09:54:49 -07001964 }
David Tolnay29f9ce12016-10-02 20:58:40 -07001965 }
1966
Michael Layzell734adb42017-06-07 16:58:31 -04001967 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001968 impl Parse for ExprIf {
1969 fn parse(input: ParseStream) -> Result<Self> {
1970 Ok(ExprIf {
David Tolnay8c91b882017-12-28 23:04:32 -05001971 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07001972 if_token: input.parse()?,
1973 cond: Box::new(input.call(expr_no_struct)?),
1974 then_branch: input.parse()?,
1975 else_branch: {
1976 if input.peek(Token![else]) {
1977 Some(input.call(else_block)?)
1978 } else {
1979 None
1980 }
Michael Layzell92639a52017-06-01 00:07:44 -04001981 },
Michael Layzell92639a52017-06-01 00:07:44 -04001982 })
David Tolnay60291082018-08-28 09:54:49 -07001983 }
Alex Crichton954046c2017-05-30 21:49:42 -07001984 }
David Tolnaybb6feae2016-10-02 21:25:20 -07001985
Michael Layzell734adb42017-06-07 16:58:31 -04001986 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001987 fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
1988 let else_token: Token![else] = input.parse()?;
1989
1990 let lookahead = input.lookahead1();
1991 let else_branch = if input.peek(Token![if]) {
1992 if input.peek2(Token![let]) {
1993 input.parse().map(Expr::IfLet)?
1994 } else {
1995 input.parse().map(Expr::If)?
1996 }
1997 } else if input.peek(token::Brace) {
1998 Expr::Block(ExprBlock {
1999 attrs: Vec::new(),
2000 label: None,
2001 block: input.parse()?,
2002 })
2003 } else {
2004 return Err(lookahead.error());
2005 };
2006
2007 Ok((else_token, Box::new(else_branch)))
2008 }
David Tolnay939766a2016-09-23 23:48:12 -07002009
Michael Layzell734adb42017-06-07 16:58:31 -04002010 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002011 impl Parse for ExprForLoop {
2012 fn parse(input: ParseStream) -> Result<Self> {
2013 let outer_attrs = input.call(Attribute::parse_outer)?;
2014 let label: Option<Label> = input.parse()?;
2015 let for_token: Token![for] = input.parse()?;
2016 let pat: Pat = input.parse()?;
2017 let in_token: Token![in] = input.parse()?;
2018 let expr: Expr = input.call(expr_no_struct)?;
2019
2020 let content;
2021 let brace_token = braced!(content in input);
2022 let inner_attrs = content.call(Attribute::parse_inner)?;
2023 let stmts = content.call(Block::parse_within)?;
2024
2025 Ok(ExprForLoop {
David Tolnay5d314dc2018-07-21 16:40:01 -07002026 attrs: {
2027 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07002028 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07002029 attrs
2030 },
David Tolnaybcd498f2017-12-29 12:02:33 -05002031 label: label,
David Tolnay60291082018-08-28 09:54:49 -07002032 for_token: for_token,
David Tolnay5d314dc2018-07-21 16:40:01 -07002033 pat: Box::new(pat),
David Tolnay60291082018-08-28 09:54:49 -07002034 in_token: in_token,
David Tolnay5d314dc2018-07-21 16:40:01 -07002035 expr: Box::new(expr),
2036 body: Block {
David Tolnay60291082018-08-28 09:54:49 -07002037 brace_token: brace_token,
2038 stmts: stmts,
David Tolnay5d314dc2018-07-21 16:40:01 -07002039 },
Michael Layzell92639a52017-06-01 00:07:44 -04002040 })
David Tolnay60291082018-08-28 09:54:49 -07002041 }
Alex Crichton954046c2017-05-30 21:49:42 -07002042 }
Gregory Katze5f35682016-09-27 14:20:55 -04002043
Michael Layzell734adb42017-06-07 16:58:31 -04002044 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002045 impl Parse for ExprLoop {
2046 fn parse(input: ParseStream) -> Result<Self> {
2047 let outer_attrs = input.call(Attribute::parse_outer)?;
2048 let label: Option<Label> = input.parse()?;
2049 let loop_token: Token![loop] = input.parse()?;
2050
2051 let content;
2052 let brace_token = braced!(content in input);
2053 let inner_attrs = content.call(Attribute::parse_inner)?;
2054 let stmts = content.call(Block::parse_within)?;
2055
2056 Ok(ExprLoop {
David Tolnay5d314dc2018-07-21 16:40:01 -07002057 attrs: {
2058 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07002059 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07002060 attrs
2061 },
David Tolnaybcd498f2017-12-29 12:02:33 -05002062 label: label,
David Tolnay60291082018-08-28 09:54:49 -07002063 loop_token: loop_token,
David Tolnay5d314dc2018-07-21 16:40:01 -07002064 body: Block {
David Tolnay60291082018-08-28 09:54:49 -07002065 brace_token: brace_token,
2066 stmts: stmts,
David Tolnay5d314dc2018-07-21 16:40:01 -07002067 },
Michael Layzell92639a52017-06-01 00:07:44 -04002068 })
David Tolnay60291082018-08-28 09:54:49 -07002069 }
Alex Crichton954046c2017-05-30 21:49:42 -07002070 }
2071
Michael Layzell734adb42017-06-07 16:58:31 -04002072 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002073 impl Parse for ExprMatch {
2074 fn parse(input: ParseStream) -> Result<Self> {
2075 let outer_attrs = input.call(Attribute::parse_outer)?;
2076 let match_token: Token![match] = input.parse()?;
2077 let expr = expr_no_struct(input)?;
2078
2079 let content;
2080 let brace_token = braced!(content in input);
2081 let inner_attrs = content.call(Attribute::parse_inner)?;
2082
2083 let mut arms = Vec::new();
2084 while !content.is_empty() {
2085 arms.push(content.parse()?);
2086 }
2087
2088 Ok(ExprMatch {
David Tolnay5d314dc2018-07-21 16:40:01 -07002089 attrs: {
2090 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07002091 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07002092 attrs
2093 },
David Tolnay60291082018-08-28 09:54:49 -07002094 match_token: match_token,
2095 expr: Box::new(expr),
2096 brace_token: brace_token,
2097 arms: arms,
Michael Layzell92639a52017-06-01 00:07:44 -04002098 })
David Tolnay60291082018-08-28 09:54:49 -07002099 }
Alex Crichton954046c2017-05-30 21:49:42 -07002100 }
David Tolnay1978c672016-10-27 22:05:52 -07002101
Michael Layzell734adb42017-06-07 16:58:31 -04002102 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002103 impl Parse for ExprTryBlock {
2104 fn parse(input: ParseStream) -> Result<Self> {
2105 Ok(ExprTryBlock {
David Tolnay8c91b882017-12-28 23:04:32 -05002106 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002107 try_token: input.parse()?,
2108 block: input.parse()?,
David Tolnaybb4ca9f2017-12-26 12:28:58 -05002109 })
David Tolnay60291082018-08-28 09:54:49 -07002110 }
Alex Crichton954046c2017-05-30 21:49:42 -07002111 }
Arnavion02ef13f2017-04-25 00:54:31 -07002112
Michael Layzell734adb42017-06-07 16:58:31 -04002113 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002114 impl Parse for ExprYield {
2115 fn parse(input: ParseStream) -> Result<Self> {
2116 Ok(ExprYield {
David Tolnay8c91b882017-12-28 23:04:32 -05002117 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002118 yield_token: input.parse()?,
2119 expr: {
2120 if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
2121 Some(input.parse()?)
2122 } else {
2123 None
2124 }
2125 },
Alex Crichtonfe110462017-06-01 12:49:27 -07002126 })
David Tolnay60291082018-08-28 09:54:49 -07002127 }
Alex Crichtonfe110462017-06-01 12:49:27 -07002128 }
2129
2130 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002131 impl Parse for Arm {
2132 fn parse(input: ParseStream) -> Result<Self> {
2133 let requires_comma;
2134 Ok(Arm {
2135 attrs: input.call(Attribute::parse_outer)?,
2136 leading_vert: input.parse()?,
2137 pats: {
2138 let mut pats = Punctuated::new();
2139 let value: Pat = input.parse()?;
2140 pats.push_value(value);
2141 loop {
2142 if !input.peek(Token![|]) {
2143 break;
2144 }
2145 let punct = input.parse()?;
2146 pats.push_punct(punct);
2147 let value: Pat = input.parse()?;
2148 pats.push_value(value);
2149 }
2150 pats
2151 },
2152 guard: {
2153 if input.peek(Token![if]) {
2154 let if_token: Token![if] = input.parse()?;
2155 let guard: Expr = input.parse()?;
2156 Some((if_token, Box::new(guard)))
2157 } else {
2158 None
2159 }
2160 },
2161 fat_arrow_token: input.parse()?,
2162 body: {
David Tolnay01218d12018-08-29 18:13:07 -07002163 let body = input.call(expr_early)?;
David Tolnay60291082018-08-28 09:54:49 -07002164 requires_comma = arm_expr_requires_comma(&body);
2165 Box::new(body)
2166 },
2167 comma: {
2168 if requires_comma && !input.is_empty() {
2169 Some(input.parse()?)
2170 } else {
2171 input.parse()?
2172 }
2173 },
Michael Layzell92639a52017-06-01 00:07:44 -04002174 })
David Tolnay60291082018-08-28 09:54:49 -07002175 }
Alex Crichton954046c2017-05-30 21:49:42 -07002176 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07002177
Michael Layzell734adb42017-06-07 16:58:31 -04002178 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002179 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
2180 let attrs = input.call(Attribute::parse_outer)?;
2181 let asyncness: Option<Token![async]> = input.parse()?;
2182 let movability: Option<Token![static]> = if asyncness.is_none() {
2183 input.parse()?
2184 } else {
2185 None
2186 };
2187 let capture: Option<Token![move]> = input.parse()?;
2188 let or1_token: Token![|] = input.parse()?;
2189
2190 let mut inputs = Punctuated::new();
2191 loop {
2192 if input.peek(Token![|]) {
2193 break;
2194 }
2195 let value = fn_arg(input)?;
2196 inputs.push_value(value);
2197 if input.peek(Token![|]) {
2198 break;
2199 }
2200 let punct: Token![,] = input.parse()?;
2201 inputs.push_punct(punct);
2202 }
2203
2204 let or2_token: Token![|] = input.parse()?;
2205
2206 let (output, body) = if input.peek(Token![->]) {
2207 let arrow_token: Token![->] = input.parse()?;
2208 let ty: Type = input.parse()?;
2209 let body: Block = input.parse()?;
2210 let output = ReturnType::Type(arrow_token, Box::new(ty));
2211 let block = Expr::Block(ExprBlock {
2212 attrs: Vec::new(),
2213 label: None,
2214 block: body,
2215 });
2216 (output, block)
2217 } else {
2218 let body = ambiguous_expr(input, allow_struct, AllowBlock(true))?;
2219 (ReturnType::Default, body)
2220 };
2221
2222 Ok(ExprClosure {
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002223 attrs: attrs,
2224 asyncness: asyncness,
2225 movability: movability,
2226 capture: capture,
David Tolnay60291082018-08-28 09:54:49 -07002227 or1_token: or1_token,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002228 inputs: inputs,
David Tolnay60291082018-08-28 09:54:49 -07002229 or2_token: or2_token,
2230 output: output,
2231 body: Box::new(body),
2232 })
David Tolnay02a9c6f2018-08-24 18:58:45 -04002233 }
Yusuke Sasaki851062f2018-08-01 06:28:28 +09002234
2235 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002236 impl Parse for ExprAsync {
2237 fn parse(input: ParseStream) -> Result<Self> {
2238 Ok(ExprAsync {
2239 attrs: input.call(Attribute::parse_outer)?,
2240 async_token: input.parse()?,
2241 capture: input.parse()?,
2242 block: input.parse()?,
2243 })
2244 }
2245 }
Gregory Katz3e562cc2016-09-28 18:33:02 -04002246
Michael Layzell734adb42017-06-07 16:58:31 -04002247 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002248 fn fn_arg(input: ParseStream) -> Result<FnArg> {
2249 let pat: Pat = input.parse()?;
2250
2251 if input.peek(Token![:]) {
2252 Ok(FnArg::Captured(ArgCaptured {
2253 pat: pat,
2254 colon_token: input.parse()?,
2255 ty: input.parse()?,
2256 }))
2257 } else {
2258 Ok(FnArg::Inferred(pat))
2259 }
2260 }
2261
2262 #[cfg(feature = "full")]
2263 impl Parse for ExprWhile {
2264 fn parse(input: ParseStream) -> Result<Self> {
2265 let outer_attrs = input.call(Attribute::parse_outer)?;
2266 let label: Option<Label> = input.parse()?;
2267 let while_token: Token![while] = input.parse()?;
2268 let cond = expr_no_struct(input)?;
2269
2270 let content;
2271 let brace_token = braced!(content in input);
2272 let inner_attrs = content.call(Attribute::parse_inner)?;
2273 let stmts = content.call(Block::parse_within)?;
2274
2275 Ok(ExprWhile {
David Tolnay5d314dc2018-07-21 16:40:01 -07002276 attrs: {
2277 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07002278 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07002279 attrs
2280 },
2281 label: label,
David Tolnay60291082018-08-28 09:54:49 -07002282 while_token: while_token,
Michael Layzell92639a52017-06-01 00:07:44 -04002283 cond: Box::new(cond),
David Tolnay5d314dc2018-07-21 16:40:01 -07002284 body: Block {
David Tolnay60291082018-08-28 09:54:49 -07002285 brace_token: brace_token,
2286 stmts: stmts,
David Tolnay5d314dc2018-07-21 16:40:01 -07002287 },
Michael Layzell92639a52017-06-01 00:07:44 -04002288 })
David Tolnay60291082018-08-28 09:54:49 -07002289 }
Alex Crichton954046c2017-05-30 21:49:42 -07002290 }
2291
Michael Layzell734adb42017-06-07 16:58:31 -04002292 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002293 impl Parse for ExprWhileLet {
2294 fn parse(input: ParseStream) -> Result<Self> {
2295 let outer_attrs = input.call(Attribute::parse_outer)?;
2296 let label: Option<Label> = input.parse()?;
2297 let while_token: Token![while] = input.parse()?;
2298 let let_token: Token![let] = input.parse()?;
2299
2300 let mut pats = Punctuated::new();
2301 let value: Pat = input.parse()?;
2302 pats.push_value(value);
2303 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2304 let punct = input.parse()?;
2305 pats.push_punct(punct);
2306 let value: Pat = input.parse()?;
2307 pats.push_value(value);
2308 }
2309
2310 let eq_token: Token![=] = input.parse()?;
2311 let expr = expr_no_struct(input)?;
2312
2313 let content;
2314 let brace_token = braced!(content in input);
2315 let inner_attrs = content.call(Attribute::parse_inner)?;
2316 let stmts = content.call(Block::parse_within)?;
2317
2318 Ok(ExprWhileLet {
David Tolnay5d314dc2018-07-21 16:40:01 -07002319 attrs: {
2320 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07002321 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07002322 attrs
2323 },
David Tolnaybcd498f2017-12-29 12:02:33 -05002324 label: label,
David Tolnay60291082018-08-28 09:54:49 -07002325 while_token: while_token,
2326 let_token: let_token,
David Tolnay5d314dc2018-07-21 16:40:01 -07002327 pats: pats,
David Tolnay60291082018-08-28 09:54:49 -07002328 eq_token: eq_token,
2329 expr: Box::new(expr),
David Tolnay5d314dc2018-07-21 16:40:01 -07002330 body: Block {
David Tolnay60291082018-08-28 09:54:49 -07002331 brace_token: brace_token,
2332 stmts: stmts,
David Tolnay5d314dc2018-07-21 16:40:01 -07002333 },
David Tolnaybcd498f2017-12-29 12:02:33 -05002334 })
David Tolnay60291082018-08-28 09:54:49 -07002335 }
David Tolnaybcd498f2017-12-29 12:02:33 -05002336 }
2337
2338 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002339 impl Parse for Label {
2340 fn parse(input: ParseStream) -> Result<Self> {
2341 Ok(Label {
2342 name: input.parse()?,
2343 colon_token: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04002344 })
David Tolnay60291082018-08-28 09:54:49 -07002345 }
Alex Crichton954046c2017-05-30 21:49:42 -07002346 }
2347
Michael Layzell734adb42017-06-07 16:58:31 -04002348 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002349 impl Parse for Option<Label> {
2350 fn parse(input: ParseStream) -> Result<Self> {
2351 if input.peek(Lifetime) {
2352 input.parse().map(Some)
2353 } else {
2354 Ok(None)
2355 }
2356 }
2357 }
2358
2359 #[cfg(feature = "full")]
2360 impl Parse for ExprContinue {
2361 fn parse(input: ParseStream) -> Result<Self> {
2362 Ok(ExprContinue {
2363 attrs: input.call(Attribute::parse_outer)?,
2364 continue_token: input.parse()?,
2365 label: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04002366 })
David Tolnay60291082018-08-28 09:54:49 -07002367 }
Alex Crichton954046c2017-05-30 21:49:42 -07002368 }
Gregory Katzfd6935d2016-09-30 22:51:25 -04002369
Michael Layzell734adb42017-06-07 16:58:31 -04002370 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002371 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2372 Ok(ExprBreak {
2373 attrs: input.call(Attribute::parse_outer)?,
2374 break_token: input.parse()?,
2375 label: input.parse()?,
2376 expr: {
2377 if input.is_empty()
2378 || input.peek(Token![,])
2379 || input.peek(Token![;])
2380 || !allow_struct.0 && input.peek(token::Brace)
2381 {
2382 None
2383 } else {
2384 // We can't allow blocks after a `break` expression when we
2385 // wouldn't allow structs, as this expression is ambiguous.
2386 let allow_block = AllowBlock(allow_struct.0);
2387 let expr = ambiguous_expr(input, allow_struct, allow_block)?;
2388 Some(Box::new(expr))
Michael Layzell92639a52017-06-01 00:07:44 -04002389 }
David Tolnay60291082018-08-28 09:54:49 -07002390 },
2391 })
Alex Crichton954046c2017-05-30 21:49:42 -07002392 }
2393
Michael Layzell734adb42017-06-07 16:58:31 -04002394 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002395 fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
2396 Ok(ExprReturn {
2397 attrs: input.call(Attribute::parse_outer)?,
2398 return_token: input.parse()?,
2399 expr: {
2400 if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
2401 None
2402 } else {
2403 // NOTE: return is greedy and eats blocks after it even when in a
2404 // position where structs are not allowed, such as in if statement
2405 // conditions. For example:
2406 //
2407 // if return { println!("A") } {} // Prints "A"
2408 let expr = ambiguous_expr(input, allow_struct, AllowBlock(true))?;
2409 Some(Box::new(expr))
2410 }
2411 },
2412 })
2413 }
2414
2415 #[cfg(feature = "full")]
2416 impl Parse for ExprStruct {
2417 fn parse(input: ParseStream) -> Result<Self> {
2418 let outer_attrs = input.call(Attribute::parse_outer)?;
2419 let path: Path = input.parse()?;
2420
David Tolnay6e1e5052018-08-30 10:21:48 -07002421 expr_struct_helper(input, outer_attrs, path)
2422 }
2423 }
David Tolnay60291082018-08-28 09:54:49 -07002424
David Tolnay6e1e5052018-08-30 10:21:48 -07002425 #[cfg(feature = "full")]
2426 fn expr_struct_helper(input: ParseStream, outer_attrs: Vec<Attribute>, path: Path) -> Result<ExprStruct> {
2427 let content;
2428 let brace_token = braced!(content in input);
2429 let inner_attrs = content.call(Attribute::parse_inner)?;
David Tolnay60291082018-08-28 09:54:49 -07002430
David Tolnay6e1e5052018-08-30 10:21:48 -07002431 let mut fields = Punctuated::new();
2432 loop {
2433 let attrs = content.call(Attribute::parse_outer)?;
2434 if content.fork().parse::<Member>().is_err() {
2435 if attrs.is_empty() {
David Tolnay60291082018-08-28 09:54:49 -07002436 break;
David Tolnay6e1e5052018-08-30 10:21:48 -07002437 } else {
2438 return Err(content.error("expected struct field"));
David Tolnay60291082018-08-28 09:54:49 -07002439 }
David Tolnay60291082018-08-28 09:54:49 -07002440 }
2441
David Tolnay6e1e5052018-08-30 10:21:48 -07002442 let member: Member = content.parse()?;
2443 let (colon_token, value) = if content.peek(Token![:]) || !member.is_named() {
2444 let colon_token: Token![:] = content.parse()?;
2445 let value: Expr = content.parse()?;
2446 (Some(colon_token), value)
2447 } else if let Member::Named(ref ident) = member {
2448 let value = Expr::Path(ExprPath {
2449 attrs: Vec::new(),
2450 qself: None,
2451 path: Path::from(ident.clone()),
2452 });
2453 (None, value)
David Tolnay60291082018-08-28 09:54:49 -07002454 } else {
David Tolnay6e1e5052018-08-30 10:21:48 -07002455 unreachable!()
David Tolnay60291082018-08-28 09:54:49 -07002456 };
2457
David Tolnay6e1e5052018-08-30 10:21:48 -07002458 fields.push(FieldValue {
2459 attrs: attrs,
2460 member: member,
2461 colon_token: colon_token,
2462 expr: value,
2463 });
2464
2465 if !content.peek(Token![,]) {
2466 break;
2467 }
2468 let punct: Token![,] = content.parse()?;
2469 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002470 }
David Tolnay6e1e5052018-08-30 10:21:48 -07002471
2472 let (dot2_token, rest) = if fields.empty_or_trailing() && content.peek(Token![..]) {
2473 let dot2_token: Token![..] = content.parse()?;
2474 let rest: Expr = content.parse()?;
2475 (Some(dot2_token), Some(Box::new(rest)))
2476 } else {
2477 (None, None)
2478 };
2479
2480 Ok(ExprStruct {
2481 attrs: {
2482 let mut attrs = outer_attrs;
2483 attrs.extend(inner_attrs);
2484 attrs
2485 },
2486 brace_token: brace_token,
2487 path: path,
2488 fields: fields,
2489 dot2_token: dot2_token,
2490 rest: rest,
2491 })
Alex Crichton954046c2017-05-30 21:49:42 -07002492 }
David Tolnay055a7042016-10-02 19:23:54 -07002493
Michael Layzell734adb42017-06-07 16:58:31 -04002494 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002495 impl Parse for ExprRepeat {
2496 fn parse(input: ParseStream) -> Result<Self> {
2497 let outer_attrs = input.call(Attribute::parse_outer)?;
2498
2499 let content;
2500 let bracket_token = bracketed!(content in input);
2501 let inner_attrs = content.call(Attribute::parse_inner)?;
2502 let expr: Expr = content.parse()?;
2503 let semi_token: Token![;] = content.parse()?;
2504 let len: Expr = content.parse()?;
2505
2506 Ok(ExprRepeat {
David Tolnay5d314dc2018-07-21 16:40:01 -07002507 attrs: {
2508 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07002509 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07002510 attrs
2511 },
David Tolnay60291082018-08-28 09:54:49 -07002512 bracket_token: bracket_token,
2513 expr: Box::new(expr),
2514 semi_token: semi_token,
2515 len: Box::new(len),
Michael Layzell92639a52017-06-01 00:07:44 -04002516 })
David Tolnay60291082018-08-28 09:54:49 -07002517 }
Alex Crichton954046c2017-05-30 21:49:42 -07002518 }
David Tolnay055a7042016-10-02 19:23:54 -07002519
Michael Layzell734adb42017-06-07 16:58:31 -04002520 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002521 impl Parse for ExprUnsafe {
2522 fn parse(input: ParseStream) -> Result<Self> {
2523 let outer_attrs = input.call(Attribute::parse_outer)?;
2524 let unsafe_token: Token![unsafe] = input.parse()?;
2525
2526 let content;
2527 let brace_token = braced!(content in input);
2528 let inner_attrs = content.call(Attribute::parse_inner)?;
2529 let stmts = content.call(Block::parse_within)?;
2530
2531 Ok(ExprUnsafe {
David Tolnayc4be3512018-08-27 06:25:44 -07002532 attrs: {
2533 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07002534 attrs.extend(inner_attrs);
David Tolnayc4be3512018-08-27 06:25:44 -07002535 attrs
2536 },
David Tolnay60291082018-08-28 09:54:49 -07002537 unsafe_token: unsafe_token,
David Tolnayc4be3512018-08-27 06:25:44 -07002538 block: Block {
David Tolnay60291082018-08-28 09:54:49 -07002539 brace_token: brace_token,
2540 stmts: stmts,
David Tolnayc4be3512018-08-27 06:25:44 -07002541 },
Nika Layzell640832a2017-12-04 13:37:09 -05002542 })
David Tolnay60291082018-08-28 09:54:49 -07002543 }
Nika Layzell640832a2017-12-04 13:37:09 -05002544 }
2545
2546 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002547 impl Parse for ExprBlock {
2548 fn parse(input: ParseStream) -> Result<Self> {
2549 let outer_attrs = input.call(Attribute::parse_outer)?;
2550 let label: Option<Label> = input.parse()?;
2551
2552 let content;
2553 let brace_token = braced!(content in input);
2554 let inner_attrs = content.call(Attribute::parse_inner)?;
2555 let stmts = content.call(Block::parse_within)?;
2556
2557 Ok(ExprBlock {
David Tolnay5d314dc2018-07-21 16:40:01 -07002558 attrs: {
2559 let mut attrs = outer_attrs;
David Tolnay60291082018-08-28 09:54:49 -07002560 attrs.extend(inner_attrs);
David Tolnay5d314dc2018-07-21 16:40:01 -07002561 attrs
2562 },
David Tolnay1d8e9962018-08-24 19:04:20 -04002563 label: label,
David Tolnay5d314dc2018-07-21 16:40:01 -07002564 block: Block {
David Tolnay60291082018-08-28 09:54:49 -07002565 brace_token: brace_token,
2566 stmts: stmts,
David Tolnay5d314dc2018-07-21 16:40:01 -07002567 },
Michael Layzell92639a52017-06-01 00:07:44 -04002568 })
David Tolnay60291082018-08-28 09:54:49 -07002569 }
Alex Crichton954046c2017-05-30 21:49:42 -07002570 }
David Tolnay89e05672016-10-02 14:39:42 -07002571
Michael Layzell734adb42017-06-07 16:58:31 -04002572 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002573 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2574 Ok(ExprRange {
David Tolnay8c91b882017-12-28 23:04:32 -05002575 attrs: Vec::new(),
2576 from: None,
David Tolnay60291082018-08-28 09:54:49 -07002577 limits: input.parse()?,
2578 to: {
2579 if input.is_empty()
2580 || input.peek(Token![,])
2581 || input.peek(Token![;])
2582 || !allow_struct.0 && input.peek(token::Brace)
2583 {
2584 None
2585 } else {
2586 let to = ambiguous_expr(input, allow_struct, AllowBlock(allow_struct.0))?;
2587 Some(Box::new(to))
2588 }
2589 },
2590 })
2591 }
David Tolnay438c9052016-10-07 23:24:48 -07002592
Michael Layzell734adb42017-06-07 16:58:31 -04002593 #[cfg(feature = "full")]
David Tolnayc4c631e2018-08-27 10:44:37 -07002594 impl Parse for RangeLimits {
2595 fn parse(input: ParseStream) -> Result<Self> {
2596 let lookahead = input.lookahead1();
2597 if lookahead.peek(Token![..=]) {
2598 input.parse().map(RangeLimits::Closed)
2599 } else if lookahead.peek(Token![...]) {
2600 let dot3: Token![...] = input.parse()?;
2601 Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2602 } else if lookahead.peek(Token![..]) {
2603 input.parse().map(RangeLimits::HalfOpen)
2604 } else {
2605 Err(lookahead.error())
2606 }
2607 }
Alex Crichton954046c2017-05-30 21:49:42 -07002608 }
David Tolnay438c9052016-10-07 23:24:48 -07002609
David Tolnay60291082018-08-28 09:54:49 -07002610 impl Parse for ExprPath {
2611 fn parse(input: ParseStream) -> Result<Self> {
2612 #[cfg(not(feature = "full"))]
2613 let attrs = Vec::new();
2614 #[cfg(feature = "full")]
2615 let attrs = input.call(Attribute::parse_outer)?;
David Tolnayeb981bb2018-07-21 19:31:38 -07002616
David Tolnay60291082018-08-28 09:54:49 -07002617 let (qself, path) = path::parsing::qpath(input, true)?;
2618
2619 Ok(ExprPath {
David Tolnay73c9b522018-07-21 15:58:40 -07002620 attrs: attrs,
David Tolnay60291082018-08-28 09:54:49 -07002621 qself: qself,
2622 path: path,
Michael Layzell92639a52017-06-01 00:07:44 -04002623 })
David Tolnay60291082018-08-28 09:54:49 -07002624 }
Alex Crichton954046c2017-05-30 21:49:42 -07002625 }
David Tolnay42602292016-10-01 22:25:45 -07002626
Michael Layzell734adb42017-06-07 16:58:31 -04002627 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002628 impl Parse for Block {
2629 fn parse(input: ParseStream) -> Result<Self> {
2630 let content;
2631 Ok(Block {
2632 brace_token: braced!(content in input),
2633 stmts: content.call(Block::parse_within)?,
Michael Layzell92639a52017-06-01 00:07:44 -04002634 })
David Tolnay60291082018-08-28 09:54:49 -07002635 }
Alex Crichton954046c2017-05-30 21:49:42 -07002636 }
David Tolnay939766a2016-09-23 23:48:12 -07002637
Michael Layzell734adb42017-06-07 16:58:31 -04002638 #[cfg(feature = "full")]
Alex Crichton954046c2017-05-30 21:49:42 -07002639 impl Block {
David Tolnay9389c382018-08-27 09:13:37 -07002640 pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> {
2641 input.step_cursor(|cursor| Self::old_parse_within(*cursor))
2642 }
2643
2644 named!(old_parse_within -> Vec<Stmt>, do_parse!(
David Tolnay4699a312017-12-27 14:39:22 -05002645 many0!(punct!(;)) >>
David Tolnaydc03aec2017-12-30 01:54:18 -05002646 mut standalone: many0!(do_parse!(
2647 stmt: syn!(Stmt) >>
2648 many0!(punct!(;)) >>
2649 (stmt)
2650 )) >>
Alex Crichton70bbd592017-08-27 10:40:03 -07002651 last: option!(do_parse!(
David Tolnayf8106f82018-08-25 21:17:45 -04002652 attrs: many0!(Attribute::old_parse_outer) >>
Alex Crichton70bbd592017-08-27 10:40:03 -07002653 mut e: syn!(Expr) >>
2654 ({
David Tolnay2ae520a2017-12-29 11:19:50 -05002655 e.replace_attrs(attrs);
David Tolnay1f0b7b82018-01-06 16:07:14 -08002656 Stmt::Expr(e)
Alex Crichton70bbd592017-08-27 10:40:03 -07002657 })
2658 )) >>
Michael Layzell92639a52017-06-01 00:07:44 -04002659 (match last {
2660 None => standalone,
2661 Some(last) => {
Alex Crichton70bbd592017-08-27 10:40:03 -07002662 standalone.push(last);
Michael Layzell92639a52017-06-01 00:07:44 -04002663 standalone
2664 }
2665 })
2666 ));
Alex Crichton954046c2017-05-30 21:49:42 -07002667 }
2668
Michael Layzell734adb42017-06-07 16:58:31 -04002669 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002670 impl Parse for Stmt {
2671 fn parse(input: ParseStream) -> Result<Self> {
2672 let ahead = input.fork();
2673 ahead.call(Attribute::parse_outer)?;
David Tolnay939766a2016-09-23 23:48:12 -07002674
David Tolnay60291082018-08-28 09:54:49 -07002675 // TODO: better error messages
2676 if {
2677 let ahead = ahead.fork();
2678 // Only parse braces here; paren and bracket will get parsed as
2679 // expression statements
2680 ahead.call(Path::parse_mod_style).is_ok()
2681 && ahead.parse::<Token![!]>().is_ok()
2682 && (ahead.peek(token::Brace) || ahead.peek(Ident))
2683 } {
2684 stmt_mac(input)
2685 } else if ahead.peek(Token![let]) {
2686 stmt_local(input).map(Stmt::Local)
2687 } else if ahead.peek(Token![pub])
2688 || ahead.peek(Token![crate]) && !ahead.peek2(Token![::])
2689 || ahead.peek(Token![extern]) && !ahead.peek2(Token![::])
2690 || ahead.peek(Token![use])
2691 || ahead.peek(Token![static]) && (ahead.peek2(Token![mut]) || ahead.peek2(Ident))
2692 || ahead.peek(Token![const])
2693 || ahead.peek(Token![unsafe]) && !ahead.peek2(token::Brace)
2694 || ahead.peek(Token![async]) && (ahead.peek2(Token![extern]) || ahead.peek2(Token![fn]))
2695 || ahead.peek(Token![fn])
2696 || ahead.peek(Token![mod])
2697 || ahead.peek(Token![type])
2698 || ahead.peek(Token![existential]) && ahead.peek2(Token![type])
2699 || ahead.peek(Token![struct])
2700 || ahead.peek(Token![enum])
2701 || ahead.peek(Token![union]) && ahead.peek2(Ident)
2702 || ahead.peek(Token![auto]) && ahead.peek2(Token![trait])
2703 || ahead.peek(Token![trait])
2704 || ahead.peek(Token![default]) && (ahead.peek2(Token![unsafe]) || ahead.peek2(Token![impl]))
2705 || ahead.peek(Token![impl])
2706 || ahead.peek(Token![macro])
2707 {
2708 input.parse().map(Stmt::Item)
Michael Layzell35418782017-06-07 09:20:25 -04002709 } else {
David Tolnay01218d12018-08-29 18:13:07 -07002710 input.call(stmt_expr)
Michael Layzell35418782017-06-07 09:20:25 -04002711 }
David Tolnay60291082018-08-28 09:54:49 -07002712 }
Alex Crichton954046c2017-05-30 21:49:42 -07002713 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07002714
Michael Layzell734adb42017-06-07 16:58:31 -04002715 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002716 fn stmt_mac(input: ParseStream) -> Result<Stmt> {
2717 let attrs = input.call(Attribute::parse_outer)?;
2718 let path = input.call(Path::parse_mod_style)?;
2719 let bang_token: Token![!] = input.parse()?;
2720 let ident: Option<Ident> = input.parse()?;
2721 let (delimiter, tts) = mac::parse_delimiter(input)?;
2722 let semi_token: Option<Token![;]> = input.parse()?;
2723
2724 Ok(Stmt::Item(Item::Macro(ItemMacro {
2725 attrs: attrs,
2726 ident: ident,
2727 mac: Macro {
2728 path: path,
2729 bang_token: bang_token,
2730 delimiter: delimiter,
2731 tts: tts,
2732 },
2733 semi_token: semi_token,
2734 })))
Alex Crichton954046c2017-05-30 21:49:42 -07002735 }
David Tolnay84aa0752016-10-02 23:01:13 -07002736
Michael Layzell734adb42017-06-07 16:58:31 -04002737 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002738 fn stmt_local(input: ParseStream) -> Result<Local> {
2739 Ok(Local {
2740 attrs: input.call(Attribute::parse_outer)?,
2741 let_token: input.parse()?,
2742 pats: {
2743 let mut pats = Punctuated::new();
2744 let value: Pat = input.parse()?;
2745 pats.push_value(value);
2746 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2747 let punct = input.parse()?;
2748 pats.push_punct(punct);
2749 let value: Pat = input.parse()?;
2750 pats.push_value(value);
2751 }
2752 pats
2753 },
2754 ty: {
2755 if input.peek(Token![:]) {
2756 let colon_token: Token![:] = input.parse()?;
2757 let ty: Type = input.parse()?;
2758 Some((colon_token, Box::new(ty)))
2759 } else {
2760 None
2761 }
2762 },
2763 init: {
2764 if input.peek(Token![=]) {
2765 let eq_token: Token![=] = input.parse()?;
2766 let init: Expr = input.parse()?;
2767 Some((eq_token, Box::new(init)))
2768 } else {
2769 None
2770 }
2771 },
2772 semi_token: input.parse()?,
2773 })
2774 }
2775
2776 #[cfg(feature = "full")]
David Tolnay01218d12018-08-29 18:13:07 -07002777 fn stmt_expr(input: ParseStream) -> Result<Stmt> {
David Tolnay60291082018-08-28 09:54:49 -07002778 let mut attrs = input.call(Attribute::parse_outer)?;
David Tolnay01218d12018-08-29 18:13:07 -07002779 let mut e = expr_early(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002780
2781 attrs.extend(e.replace_attrs(Vec::new()));
2782 e.replace_attrs(attrs);
2783
2784 if input.peek(Token![;]) {
David Tolnay01218d12018-08-29 18:13:07 -07002785 return Ok(Stmt::Semi(e, input.parse()?));
David Tolnay60291082018-08-28 09:54:49 -07002786 }
David Tolnay60291082018-08-28 09:54:49 -07002787
David Tolnay01218d12018-08-29 18:13:07 -07002788 match e {
2789 Expr::IfLet(_) |
2790 Expr::If(_) |
2791 Expr::WhileLet(_) |
2792 Expr::While(_) |
2793 Expr::ForLoop(_) |
2794 Expr::Loop(_) |
2795 Expr::Match(_) |
2796 Expr::TryBlock(_) |
2797 Expr::Yield(_) |
2798 Expr::Unsafe(_) |
2799 Expr::Block(_) => Ok(Stmt::Expr(e)),
2800 _ => {
2801 Err(input.error("expected semicolon"))
2802 }
2803 }
David Tolnay60291082018-08-28 09:54:49 -07002804 }
2805
2806 #[cfg(feature = "full")]
2807 impl Parse for Pat {
2808 fn parse(input: ParseStream) -> Result<Self> {
2809 // TODO: better error messages
2810 let lookahead = input.lookahead1();
2811 if lookahead.peek(Token![_]) {
2812 input.parse().map(Pat::Wild)
2813 } else if lookahead.peek(Token![box]) {
2814 input.parse().map(Pat::Box)
2815 } else if input.fork().parse::<PatRange>().is_ok() {
2816 // must be before Pat::Lit
2817 input.parse().map(Pat::Range)
2818 } else if input.fork().parse::<PatTupleStruct>().is_ok() {
2819 // must be before Pat::Ident
2820 input.parse().map(Pat::TupleStruct)
2821 } else if input.fork().parse::<PatStruct>().is_ok() {
2822 // must be before Pat::Ident
2823 input.parse().map(Pat::Struct)
2824 } else if input.fork().parse::<PatMacro>().is_ok() {
2825 // must be before Pat::Ident
2826 input.parse().map(Pat::Macro)
2827 } else if input.fork().parse::<PatLit>().is_ok() {
2828 // must be before Pat::Ident
2829 input.parse().map(Pat::Lit)
2830 } else if input.fork().parse::<PatIdent>().is_ok() {
2831 input.parse().map(Pat::Ident)
2832 } else if input.fork().parse::<PatPath>().is_ok() {
2833 input.parse().map(Pat::Path)
2834 } else if lookahead.peek(token::Paren) {
2835 input.parse().map(Pat::Tuple)
2836 } else if lookahead.peek(Token![&]) {
2837 input.parse().map(Pat::Ref)
2838 } else if lookahead.peek(token::Bracket) {
2839 input.parse().map(Pat::Slice)
2840 } else {
2841 Err(lookahead.error())
2842 }
2843 }
2844 }
2845
2846 #[cfg(feature = "full")]
2847 impl Parse for PatWild {
2848 fn parse(input: ParseStream) -> Result<Self> {
2849 Ok(PatWild {
2850 underscore_token: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04002851 })
David Tolnay60291082018-08-28 09:54:49 -07002852 }
Alex Crichton954046c2017-05-30 21:49:42 -07002853 }
2854
Michael Layzell734adb42017-06-07 16:58:31 -04002855 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002856 impl Parse for PatBox {
2857 fn parse(input: ParseStream) -> Result<Self> {
2858 Ok(PatBox {
2859 box_token: input.parse()?,
2860 pat: input.parse()?,
2861 })
2862 }
2863 }
2864
2865 #[cfg(feature = "full")]
2866 impl Parse for PatIdent {
2867 fn parse(input: ParseStream) -> Result<Self> {
2868 Ok(PatIdent {
2869 by_ref: input.parse()?,
2870 mutability: input.parse()?,
2871 ident: {
2872 let ident = if input.peek(Ident) || input.peek(Token![self]) {
2873 input.call(Ident::parse_any2)?
2874 } else {
2875 return Err(input.error("expected identifier or `self`"));
2876 };
2877 if input.peek(Token![<]) || input.peek(Token![::]) {
2878 return Err(input.error("unexpected token"));
2879 }
2880 ident
2881 },
2882 subpat: {
2883 if input.peek(Token![@]) {
2884 let at_token: Token![@] = input.parse()?;
2885 let subpat: Pat = input.parse()?;
2886 Some((at_token, Box::new(subpat)))
2887 } else {
2888 None
2889 }
2890 },
2891 })
2892 }
2893 }
2894
2895 #[cfg(feature = "full")]
2896 impl Parse for PatTupleStruct {
2897 fn parse(input: ParseStream) -> Result<Self> {
2898 Ok(PatTupleStruct {
2899 path: input.parse()?,
2900 pat: input.parse()?,
2901 })
2902 }
2903 }
2904
2905 #[cfg(feature = "full")]
2906 impl Parse for PatStruct {
2907 fn parse(input: ParseStream) -> Result<Self> {
2908 let path: Path = input.parse()?;
2909
2910 let content;
2911 let brace_token = braced!(content in input);
2912
2913 let mut fields = Punctuated::new();
2914 while !content.is_empty() && !content.peek(Token![..]) {
2915 let value: FieldPat = content.parse()?;
2916 fields.push_value(value);
2917 if !content.peek(Token![,]) {
2918 break;
2919 }
2920 let punct: Token![,] = content.parse()?;
2921 fields.push_punct(punct);
2922 }
2923
2924 let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) {
2925 Some(content.parse()?)
2926 } else {
2927 None
2928 };
2929
2930 Ok(PatStruct {
2931 path: path,
2932 brace_token: brace_token,
2933 fields: fields,
2934 dot2_token: dot2_token,
2935 })
2936 }
2937 }
2938
2939 #[cfg(feature = "full")]
2940 impl Parse for FieldPat {
2941 fn parse(input: ParseStream) -> Result<Self> {
2942 let boxed: Option<Token![box]> = input.parse()?;
2943 let by_ref: Option<Token![ref]> = input.parse()?;
2944 let mutability: Option<Token![mut]> = input.parse()?;
2945 let member: Member = input.parse()?;
2946
2947 if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
2948 || member.is_unnamed()
2949 {
2950 return Ok(FieldPat {
2951 attrs: Vec::new(),
2952 member: member,
2953 colon_token: input.parse()?,
2954 pat: input.parse()?,
2955 });
2956 }
2957
2958 let ident = match member {
2959 Member::Named(ident) => ident,
2960 Member::Unnamed(_) => unreachable!(),
2961 };
2962
2963 let mut pat = Pat::Ident(PatIdent {
David Tolnay24237fb2017-12-29 02:15:26 -05002964 by_ref: by_ref,
David Tolnayefc96fb2017-12-29 02:03:15 -05002965 mutability: mutability,
David Tolnay60291082018-08-28 09:54:49 -07002966 ident: ident.clone(),
2967 subpat: None,
2968 });
Alex Crichton954046c2017-05-30 21:49:42 -07002969
David Tolnay60291082018-08-28 09:54:49 -07002970 if let Some(boxed) = boxed {
2971 pat = Pat::Box(PatBox {
Michael Layzell92639a52017-06-01 00:07:44 -04002972 pat: Box::new(pat),
David Tolnay60291082018-08-28 09:54:49 -07002973 box_token: boxed,
2974 });
2975 }
2976
2977 Ok(FieldPat {
2978 member: Member::Named(ident),
2979 pat: Box::new(pat),
2980 attrs: Vec::new(),
2981 colon_token: None,
2982 })
2983 }
Alex Crichton954046c2017-05-30 21:49:42 -07002984 }
2985
David Tolnay1501f7e2018-08-27 14:21:03 -07002986 impl Parse for Member {
2987 fn parse(input: ParseStream) -> Result<Self> {
2988 if input.peek(Ident) {
2989 input.parse().map(Member::Named)
2990 } else if input.peek(LitInt) {
2991 input.parse().map(Member::Unnamed)
2992 } else {
2993 Err(input.error("expected identifier or integer"))
2994 }
2995 }
David Tolnay85b69a42017-12-27 20:43:10 -05002996 }
2997
David Tolnay1501f7e2018-08-27 14:21:03 -07002998 impl Parse for Index {
2999 fn parse(input: ParseStream) -> Result<Self> {
3000 let lit: LitInt = input.parse()?;
3001 if let IntSuffix::None = lit.suffix() {
3002 Ok(Index {
3003 index: lit.value() as u32,
3004 span: lit.span(),
3005 })
3006 } else {
3007 Err(input.error("expected unsuffixed integer"))
3008 }
3009 }
David Tolnay85b69a42017-12-27 20:43:10 -05003010 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07003011
Michael Layzell734adb42017-06-07 16:58:31 -04003012 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07003013 impl Parse for PatPath {
3014 fn parse(input: ParseStream) -> Result<Self> {
3015 let p: ExprPath = input.parse()?;
3016 Ok(PatPath {
3017 qself: p.qself,
3018 path: p.path,
3019 })
3020 }
Alex Crichton954046c2017-05-30 21:49:42 -07003021 }
David Tolnay9636c052016-10-02 17:11:17 -07003022
Michael Layzell734adb42017-06-07 16:58:31 -04003023 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07003024 impl Parse for PatTuple {
3025 fn parse(input: ParseStream) -> Result<Self> {
3026 let content;
3027 let paren_token = parenthesized!(content in input);
3028
3029 let mut front = Punctuated::new();
3030 let mut dot2_token = None::<Token![..]>;
3031 let mut comma_token = None::<Token![,]>;
3032 loop {
3033 if content.is_empty() {
3034 break;
Michael Layzell92639a52017-06-01 00:07:44 -04003035 }
David Tolnay60291082018-08-28 09:54:49 -07003036 if content.peek(Token![..]) {
3037 dot2_token = Some(content.parse()?);
3038 comma_token = content.parse()?;
3039 break;
3040 }
3041 let value: Pat = content.parse()?;
3042 front.push_value(value);
3043 if content.is_empty() {
3044 break;
3045 }
3046 let punct = content.parse()?;
3047 front.push_punct(punct);
3048 }
David Tolnayfbb73232016-10-03 01:00:06 -07003049
David Tolnay60291082018-08-28 09:54:49 -07003050 let back = if comma_token.is_some() {
3051 content.parse_synom(Punctuated::parse_terminated)?
Michael Layzell92639a52017-06-01 00:07:44 -04003052 } else {
David Tolnay60291082018-08-28 09:54:49 -07003053 Punctuated::new()
3054 };
3055
3056 Ok(PatTuple {
3057 paren_token: paren_token,
3058 front: front,
3059 dot2_token: dot2_token,
3060 comma_token: comma_token,
3061 back: back,
Michael Layzell92639a52017-06-01 00:07:44 -04003062 })
David Tolnay60291082018-08-28 09:54:49 -07003063 }
Alex Crichton954046c2017-05-30 21:49:42 -07003064 }
David Tolnaye1310902016-10-29 23:40:00 -07003065
Michael Layzell734adb42017-06-07 16:58:31 -04003066 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07003067 impl Parse for PatRef {
3068 fn parse(input: ParseStream) -> Result<Self> {
3069 Ok(PatRef {
3070 and_token: input.parse()?,
3071 mutability: input.parse()?,
3072 pat: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04003073 })
David Tolnay60291082018-08-28 09:54:49 -07003074 }
Alex Crichton954046c2017-05-30 21:49:42 -07003075 }
David Tolnaye1310902016-10-29 23:40:00 -07003076
Michael Layzell734adb42017-06-07 16:58:31 -04003077 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07003078 impl Parse for PatLit {
3079 fn parse(input: ParseStream) -> Result<Self> {
3080 if input.peek(Lit) || input.peek(Token![-]) && input.peek2(Lit) {
3081 Ok(PatLit {
3082 expr: input.call(pat_lit_expr)?,
3083 })
3084 } else {
3085 Err(input.error("expected literal pattern"))
3086 }
3087 }
3088 }
3089
3090 #[cfg(feature = "full")]
3091 impl Parse for PatRange {
3092 fn parse(input: ParseStream) -> Result<Self> {
3093 Ok(PatRange {
3094 lo: input.call(pat_lit_expr)?,
3095 limits: input.parse()?,
3096 hi: input.call(pat_lit_expr)?,
3097 })
3098 }
3099 }
3100
3101 #[cfg(feature = "full")]
3102 fn pat_lit_expr(input: ParseStream) -> Result<Box<Expr>> {
3103 let neg: Option<Token![-]> = input.parse()?;
3104
3105 let lookahead = input.lookahead1();
3106 let expr = if lookahead.peek(Lit) {
3107 Expr::Lit(input.parse()?)
3108 } else if lookahead.peek(Ident)
3109 || lookahead.peek(Token![::])
3110 || lookahead.peek(Token![<])
3111 || lookahead.peek(Token![self])
3112 || lookahead.peek(Token![Self])
3113 || lookahead.peek(Token![super])
3114 || lookahead.peek(Token![extern])
3115 || lookahead.peek(Token![crate])
3116 {
3117 Expr::Path(input.parse()?)
3118 } else {
3119 return Err(lookahead.error());
3120 };
3121
3122 Ok(Box::new(if let Some(neg) = neg {
David Tolnay8c91b882017-12-28 23:04:32 -05003123 Expr::Unary(ExprUnary {
3124 attrs: Vec::new(),
David Tolnayc29b9892017-12-27 22:58:14 -05003125 op: UnOp::Neg(neg),
David Tolnay60291082018-08-28 09:54:49 -07003126 expr: Box::new(expr),
David Tolnay3bc597f2017-12-31 02:31:11 -05003127 })
David Tolnay0ad9e9f2016-10-29 22:20:02 -07003128 } else {
David Tolnay60291082018-08-28 09:54:49 -07003129 expr
3130 }))
Alex Crichton954046c2017-05-30 21:49:42 -07003131 }
David Tolnay323279a2017-12-29 11:26:32 -05003132
3133 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07003134 impl Parse for PatSlice {
3135 fn parse(input: ParseStream) -> Result<Self> {
3136 let content;
3137 let bracket_token = bracketed!(content in input);
3138
3139 let mut front = Punctuated::new();
3140 let mut middle = None;
3141 loop {
3142 if content.is_empty() || content.peek(Token![..]) {
3143 break;
3144 }
3145 let value: Pat = content.parse()?;
3146 if content.peek(Token![..]) {
3147 middle = Some(Box::new(value));
3148 break;
3149 }
3150 front.push_value(value);
3151 if content.is_empty() {
3152 break;
3153 }
3154 let punct = content.parse()?;
3155 front.push_punct(punct);
3156 }
3157
3158 let dot2_token: Option<Token![..]> = content.parse()?;
3159 let mut comma_token = None::<Token![,]>;
3160 let mut back = Punctuated::new();
3161 if dot2_token.is_some() {
3162 comma_token = content.parse()?;
3163 if comma_token.is_some() {
3164 loop {
3165 if content.is_empty() {
3166 break;
3167 }
3168 let value: Pat = content.parse()?;
3169 back.push_value(value);
3170 if content.is_empty() {
3171 break;
3172 }
3173 let punct = content.parse()?;
3174 back.push_punct(punct);
3175 }
3176 }
3177 }
3178
3179 Ok(PatSlice {
3180 bracket_token: bracket_token,
3181 front: front,
3182 middle: middle,
3183 dot2_token: dot2_token,
3184 comma_token: comma_token,
3185 back: back,
3186 })
3187 }
3188 }
3189
3190 #[cfg(feature = "full")]
3191 impl Parse for PatMacro {
3192 fn parse(input: ParseStream) -> Result<Self> {
3193 Ok(PatMacro {
3194 mac: input.parse()?,
3195 })
3196 }
David Tolnay323279a2017-12-29 11:26:32 -05003197 }
David Tolnay1501f7e2018-08-27 14:21:03 -07003198
3199 #[cfg(feature = "full")]
3200 impl Member {
3201 fn is_named(&self) -> bool {
3202 match *self {
3203 Member::Named(_) => true,
3204 Member::Unnamed(_) => false,
3205 }
3206 }
David Tolnay60291082018-08-28 09:54:49 -07003207
3208 fn is_unnamed(&self) -> bool {
3209 match *self {
3210 Member::Named(_) => false,
3211 Member::Unnamed(_) => true,
3212 }
3213 }
David Tolnay1501f7e2018-08-27 14:21:03 -07003214 }
David Tolnayb9c8e322016-09-23 20:48:37 -07003215}
3216
David Tolnayf4bbbd92016-09-23 14:41:55 -07003217#[cfg(feature = "printing")]
3218mod printing {
3219 use super::*;
Michael Layzell734adb42017-06-07 16:58:31 -04003220 #[cfg(feature = "full")]
David Tolnay13b3d352016-10-03 00:31:15 -07003221 use attr::FilterAttrs;
Alex Crichtona74a1c82018-05-16 10:20:44 -07003222 use proc_macro2::{Literal, TokenStream};
3223 use quote::{ToTokens, TokenStreamExt};
David Tolnayf4bbbd92016-09-23 14:41:55 -07003224
David Tolnaybcf26022017-12-25 22:10:52 -05003225 // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
David Tolnayb6a0e7d2018-05-20 22:06:47 -07003226 // before appending it to `TokenStream`.
Michael Layzell3936ceb2017-07-08 00:28:36 -04003227 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003228 fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) {
David Tolnay8c91b882017-12-28 23:04:32 -05003229 if let Expr::Struct(_) = *e {
David Tolnay32954ef2017-12-26 22:43:16 -05003230 token::Paren::default().surround(tokens, |tokens| {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003231 e.to_tokens(tokens);
3232 });
3233 } else {
3234 e.to_tokens(tokens);
3235 }
3236 }
3237
David Tolnay8c91b882017-12-28 23:04:32 -05003238 #[cfg(feature = "full")]
David Tolnayd997aef2018-07-21 18:42:31 -07003239 fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
David Tolnay8c91b882017-12-28 23:04:32 -05003240 tokens.append_all(attrs.outer());
3241 }
Michael Layzell734adb42017-06-07 16:58:31 -04003242
David Tolnayd997aef2018-07-21 18:42:31 -07003243 #[cfg(feature = "full")]
3244 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3245 tokens.append_all(attrs.inner());
3246 }
3247
David Tolnay8c91b882017-12-28 23:04:32 -05003248 #[cfg(not(feature = "full"))]
David Tolnayd997aef2018-07-21 18:42:31 -07003249 fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3250
3251 #[cfg(not(feature = "full"))]
3252 fn inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
Alex Crichton62a0a592017-05-22 13:58:53 -07003253
Michael Layzell734adb42017-06-07 16:58:31 -04003254 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003255 impl ToTokens for ExprBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003256 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003257 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003258 self.box_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003259 self.expr.to_tokens(tokens);
3260 }
3261 }
3262
Michael Layzell734adb42017-06-07 16:58:31 -04003263 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003264 impl ToTokens for ExprInPlace {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003265 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003266 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8701a5c2017-12-28 23:31:10 -05003267 self.place.to_tokens(tokens);
3268 self.arrow_token.to_tokens(tokens);
3269 self.value.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003270 }
3271 }
3272
Michael Layzell734adb42017-06-07 16:58:31 -04003273 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003274 impl ToTokens for ExprArray {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003275 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003276 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003277 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003278 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003279 self.elems.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003280 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003281 }
3282 }
3283
3284 impl ToTokens for ExprCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003285 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003286 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003287 self.func.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003288 self.paren_token.surround(tokens, |tokens| {
3289 self.args.to_tokens(tokens);
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 ExprMethodCall {
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);
David Tolnay76418512017-12-28 23:47:47 -05003298 self.receiver.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003299 self.dot_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003300 self.method.to_tokens(tokens);
David Tolnayd60cfec2017-12-29 00:21:38 -05003301 self.turbofish.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003302 self.paren_token.surround(tokens, |tokens| {
3303 self.args.to_tokens(tokens);
3304 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003305 }
3306 }
3307
Michael Layzell734adb42017-06-07 16:58:31 -04003308 #[cfg(feature = "full")]
David Tolnayd60cfec2017-12-29 00:21:38 -05003309 impl ToTokens for MethodTurbofish {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003310 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003311 self.colon2_token.to_tokens(tokens);
3312 self.lt_token.to_tokens(tokens);
3313 self.args.to_tokens(tokens);
3314 self.gt_token.to_tokens(tokens);
3315 }
3316 }
3317
3318 #[cfg(feature = "full")]
3319 impl ToTokens for GenericMethodArgument {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003320 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003321 match *self {
3322 GenericMethodArgument::Type(ref t) => t.to_tokens(tokens),
3323 GenericMethodArgument::Const(ref c) => c.to_tokens(tokens),
3324 }
3325 }
3326 }
3327
3328 #[cfg(feature = "full")]
David Tolnay05362582017-12-26 01:33:57 -05003329 impl ToTokens for ExprTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003330 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003331 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003332 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003333 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003334 self.elems.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003335 // If we only have one argument, we need a trailing comma to
David Tolnay05362582017-12-26 01:33:57 -05003336 // distinguish ExprTuple from ExprParen.
David Tolnaya0834b42018-01-01 21:30:02 -08003337 if self.elems.len() == 1 && !self.elems.trailing_punct() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003338 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003339 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003340 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003341 }
3342 }
3343
3344 impl ToTokens for ExprBinary {
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);
Alex Crichton62a0a592017-05-22 13:58:53 -07003347 self.left.to_tokens(tokens);
3348 self.op.to_tokens(tokens);
3349 self.right.to_tokens(tokens);
3350 }
3351 }
3352
3353 impl ToTokens for ExprUnary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003354 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003355 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003356 self.op.to_tokens(tokens);
3357 self.expr.to_tokens(tokens);
3358 }
3359 }
3360
David Tolnay8c91b882017-12-28 23:04:32 -05003361 impl ToTokens for ExprLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003362 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003363 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003364 self.lit.to_tokens(tokens);
3365 }
3366 }
3367
Alex Crichton62a0a592017-05-22 13:58:53 -07003368 impl ToTokens for ExprCast {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003369 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003370 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003371 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003372 self.as_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003373 self.ty.to_tokens(tokens);
3374 }
3375 }
3376
David Tolnay0cf94f22017-12-28 23:46:26 -05003377 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003378 impl ToTokens for ExprType {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003379 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003380 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003381 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003382 self.colon_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003383 self.ty.to_tokens(tokens);
3384 }
3385 }
3386
Michael Layzell734adb42017-06-07 16:58:31 -04003387 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003388 fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>) {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003389 if let Some((ref else_token, ref else_)) = *else_ {
3390 else_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003391
3392 // If we are not one of the valid expressions to exist in an else
3393 // clause, wrap ourselves in a block.
David Tolnay2ccf32a2017-12-29 00:34:26 -05003394 match **else_ {
David Tolnay8c91b882017-12-28 23:04:32 -05003395 Expr::If(_) | Expr::IfLet(_) | Expr::Block(_) => {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003396 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003397 }
3398 _ => {
David Tolnay32954ef2017-12-26 22:43:16 -05003399 token::Brace::default().surround(tokens, |tokens| {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003400 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003401 });
3402 }
3403 }
3404 }
3405 }
3406
3407 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003408 impl ToTokens for ExprIf {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003409 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003410 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003411 self.if_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003412 wrap_bare_struct(tokens, &self.cond);
David Tolnay2ccf32a2017-12-29 00:34:26 -05003413 self.then_branch.to_tokens(tokens);
3414 maybe_wrap_else(tokens, &self.else_branch);
Alex Crichton62a0a592017-05-22 13:58:53 -07003415 }
3416 }
3417
Michael Layzell734adb42017-06-07 16:58:31 -04003418 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003419 impl ToTokens for ExprIfLet {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003420 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003421 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003422 self.if_token.to_tokens(tokens);
3423 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003424 self.pats.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003425 self.eq_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003426 wrap_bare_struct(tokens, &self.expr);
David Tolnay2ccf32a2017-12-29 00:34:26 -05003427 self.then_branch.to_tokens(tokens);
3428 maybe_wrap_else(tokens, &self.else_branch);
Alex Crichton62a0a592017-05-22 13:58:53 -07003429 }
3430 }
3431
Michael Layzell734adb42017-06-07 16:58:31 -04003432 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003433 impl ToTokens for ExprWhile {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003434 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003435 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003436 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003437 self.while_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003438 wrap_bare_struct(tokens, &self.cond);
David Tolnay5d314dc2018-07-21 16:40:01 -07003439 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003440 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003441 tokens.append_all(&self.body.stmts);
3442 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003443 }
3444 }
3445
Michael Layzell734adb42017-06-07 16:58:31 -04003446 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003447 impl ToTokens for ExprWhileLet {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003448 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003449 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003450 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003451 self.while_token.to_tokens(tokens);
3452 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003453 self.pats.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003454 self.eq_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003455 wrap_bare_struct(tokens, &self.expr);
David Tolnay5d314dc2018-07-21 16:40:01 -07003456 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003457 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003458 tokens.append_all(&self.body.stmts);
3459 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003460 }
3461 }
3462
Michael Layzell734adb42017-06-07 16:58:31 -04003463 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003464 impl ToTokens for ExprForLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003465 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003466 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003467 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003468 self.for_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003469 self.pat.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003470 self.in_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003471 wrap_bare_struct(tokens, &self.expr);
David Tolnay5d314dc2018-07-21 16:40:01 -07003472 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003473 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003474 tokens.append_all(&self.body.stmts);
3475 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003476 }
3477 }
3478
Michael Layzell734adb42017-06-07 16:58:31 -04003479 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003480 impl ToTokens for ExprLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003481 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003482 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003483 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003484 self.loop_token.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003485 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003486 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003487 tokens.append_all(&self.body.stmts);
3488 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003489 }
3490 }
3491
Michael Layzell734adb42017-06-07 16:58:31 -04003492 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003493 impl ToTokens for ExprMatch {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003494 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003495 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003496 self.match_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003497 wrap_bare_struct(tokens, &self.expr);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003498 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003499 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay51382052017-12-27 13:46:21 -05003500 for (i, arm) in self.arms.iter().enumerate() {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003501 arm.to_tokens(tokens);
3502 // Ensure that we have a comma after a non-block arm, except
3503 // for the last one.
3504 let is_last = i == self.arms.len() - 1;
Alex Crichton03b30272017-08-28 09:35:24 -07003505 if !is_last && arm_expr_requires_comma(&arm.body) && arm.comma.is_none() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003506 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003507 }
3508 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003509 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003510 }
3511 }
3512
Michael Layzell734adb42017-06-07 16:58:31 -04003513 #[cfg(feature = "full")]
David Tolnay02a9c6f2018-08-24 18:58:45 -04003514 impl ToTokens for ExprAsync {
3515 fn to_tokens(&self, tokens: &mut TokenStream) {
3516 outer_attrs_to_tokens(&self.attrs, tokens);
3517 self.async_token.to_tokens(tokens);
3518 self.capture.to_tokens(tokens);
3519 self.block.to_tokens(tokens);
3520 }
3521 }
3522
3523 #[cfg(feature = "full")]
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003524 impl ToTokens for ExprTryBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003525 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003526 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003527 self.try_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003528 self.block.to_tokens(tokens);
3529 }
3530 }
3531
Michael Layzell734adb42017-06-07 16:58:31 -04003532 #[cfg(feature = "full")]
Alex Crichtonfe110462017-06-01 12:49:27 -07003533 impl ToTokens for ExprYield {
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 Crichtonfe110462017-06-01 12:49:27 -07003536 self.yield_token.to_tokens(tokens);
3537 self.expr.to_tokens(tokens);
3538 }
3539 }
3540
3541 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003542 impl ToTokens for ExprClosure {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003543 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003544 outer_attrs_to_tokens(&self.attrs, tokens);
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09003545 self.asyncness.to_tokens(tokens);
David Tolnay13d4c0e2018-03-31 20:53:59 +02003546 self.movability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003547 self.capture.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003548 self.or1_token.to_tokens(tokens);
David Tolnay56080682018-01-06 14:01:52 -08003549 for input in self.inputs.pairs() {
3550 match **input.value() {
David Tolnay51382052017-12-27 13:46:21 -05003551 FnArg::Captured(ArgCaptured {
3552 ref pat,
3553 ty: Type::Infer(_),
3554 ..
3555 }) => {
Alex Crichton62a0a592017-05-22 13:58:53 -07003556 pat.to_tokens(tokens);
David Tolnay9636c052016-10-02 17:11:17 -07003557 }
David Tolnay56080682018-01-06 14:01:52 -08003558 _ => input.value().to_tokens(tokens),
David Tolnay3c2467c2016-10-02 17:55:08 -07003559 }
David Tolnayf2cfd722017-12-31 18:02:51 -05003560 input.punct().to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003561 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003562 self.or2_token.to_tokens(tokens);
David Tolnay7f675742017-12-27 22:43:21 -05003563 self.output.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003564 self.body.to_tokens(tokens);
3565 }
3566 }
3567
Michael Layzell734adb42017-06-07 16:58:31 -04003568 #[cfg(feature = "full")]
Nika Layzell640832a2017-12-04 13:37:09 -05003569 impl ToTokens for ExprUnsafe {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003570 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003571 outer_attrs_to_tokens(&self.attrs, tokens);
Nika Layzell640832a2017-12-04 13:37:09 -05003572 self.unsafe_token.to_tokens(tokens);
David Tolnayc4be3512018-08-27 06:25:44 -07003573 self.block.brace_token.surround(tokens, |tokens| {
3574 inner_attrs_to_tokens(&self.attrs, tokens);
3575 tokens.append_all(&self.block.stmts);
3576 });
Nika Layzell640832a2017-12-04 13:37:09 -05003577 }
3578 }
3579
3580 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003581 impl ToTokens for ExprBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003582 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003583 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay1d8e9962018-08-24 19:04:20 -04003584 self.label.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003585 self.block.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003586 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003587 tokens.append_all(&self.block.stmts);
3588 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003589 }
3590 }
3591
Michael Layzell734adb42017-06-07 16:58:31 -04003592 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003593 impl ToTokens for ExprAssign {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003594 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003595 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003596 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003597 self.eq_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003598 self.right.to_tokens(tokens);
3599 }
3600 }
3601
Michael Layzell734adb42017-06-07 16:58:31 -04003602 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003603 impl ToTokens for ExprAssignOp {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003604 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003605 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003606 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003607 self.op.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003608 self.right.to_tokens(tokens);
3609 }
3610 }
3611
3612 impl ToTokens for ExprField {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003613 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003614 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003615 self.base.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003616 self.dot_token.to_tokens(tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003617 self.member.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003618 }
3619 }
3620
David Tolnay85b69a42017-12-27 20:43:10 -05003621 impl ToTokens for Member {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003622 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay85b69a42017-12-27 20:43:10 -05003623 match *self {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003624 Member::Named(ref ident) => ident.to_tokens(tokens),
David Tolnay85b69a42017-12-27 20:43:10 -05003625 Member::Unnamed(ref index) => index.to_tokens(tokens),
3626 }
3627 }
3628 }
3629
David Tolnay85b69a42017-12-27 20:43:10 -05003630 impl ToTokens for Index {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003631 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichton9a4dca22018-03-28 06:32:19 -07003632 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
3633 lit.set_span(self.span);
3634 tokens.append(lit);
Alex Crichton62a0a592017-05-22 13:58:53 -07003635 }
3636 }
3637
3638 impl ToTokens for ExprIndex {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003639 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003640 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003641 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003642 self.bracket_token.surround(tokens, |tokens| {
3643 self.index.to_tokens(tokens);
3644 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003645 }
3646 }
3647
Michael Layzell734adb42017-06-07 16:58:31 -04003648 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003649 impl ToTokens for ExprRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003650 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003651 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003652 self.from.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003653 match self.limits {
3654 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
3655 RangeLimits::Closed(ref t) => t.to_tokens(tokens),
3656 }
Alex Crichton62a0a592017-05-22 13:58:53 -07003657 self.to.to_tokens(tokens);
3658 }
3659 }
3660
3661 impl ToTokens for ExprPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003662 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003663 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003664 ::PathTokens(&self.qself, &self.path).to_tokens(tokens)
Alex Crichton62a0a592017-05-22 13:58:53 -07003665 }
3666 }
3667
Michael Layzell734adb42017-06-07 16:58:31 -04003668 #[cfg(feature = "full")]
David Tolnay00674ba2018-03-31 18:14:11 +02003669 impl ToTokens for ExprReference {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003670 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003671 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003672 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003673 self.mutability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003674 self.expr.to_tokens(tokens);
3675 }
3676 }
3677
Michael Layzell734adb42017-06-07 16:58:31 -04003678 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003679 impl ToTokens for ExprBreak {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003680 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003681 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003682 self.break_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003683 self.label.to_tokens(tokens);
3684 self.expr.to_tokens(tokens);
3685 }
3686 }
3687
Michael Layzell734adb42017-06-07 16:58:31 -04003688 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003689 impl ToTokens for ExprContinue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003690 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003691 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003692 self.continue_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003693 self.label.to_tokens(tokens);
3694 }
3695 }
3696
Michael Layzell734adb42017-06-07 16:58:31 -04003697 #[cfg(feature = "full")]
David Tolnayc246cd32017-12-28 23:14:32 -05003698 impl ToTokens for ExprReturn {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003699 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003700 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003701 self.return_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003702 self.expr.to_tokens(tokens);
3703 }
3704 }
3705
Michael Layzell734adb42017-06-07 16:58:31 -04003706 #[cfg(feature = "full")]
David Tolnay8c91b882017-12-28 23:04:32 -05003707 impl ToTokens for ExprMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003708 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003709 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003710 self.mac.to_tokens(tokens);
3711 }
3712 }
3713
3714 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003715 impl ToTokens for ExprStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003716 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003717 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003718 self.path.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003719 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003720 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003721 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003722 if self.rest.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -07003723 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003724 self.rest.to_tokens(tokens);
3725 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003726 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003727 }
3728 }
3729
Michael Layzell734adb42017-06-07 16:58:31 -04003730 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003731 impl ToTokens for ExprRepeat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003732 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003733 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003734 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003735 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003736 self.expr.to_tokens(tokens);
3737 self.semi_token.to_tokens(tokens);
David Tolnay84d80442018-01-07 01:03:20 -08003738 self.len.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003739 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003740 }
3741 }
3742
David Tolnaye98775f2017-12-28 23:17:00 -05003743 #[cfg(feature = "full")]
Michael Layzell93c36282017-06-04 20:43:14 -04003744 impl ToTokens for ExprGroup {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003745 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003746 outer_attrs_to_tokens(&self.attrs, tokens);
Michael Layzell93c36282017-06-04 20:43:14 -04003747 self.group_token.surround(tokens, |tokens| {
3748 self.expr.to_tokens(tokens);
3749 });
3750 }
3751 }
3752
Alex Crichton62a0a592017-05-22 13:58:53 -07003753 impl ToTokens for ExprParen {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003754 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003755 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003756 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003757 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003758 self.expr.to_tokens(tokens);
3759 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003760 }
3761 }
3762
Michael Layzell734adb42017-06-07 16:58:31 -04003763 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003764 impl ToTokens for ExprTry {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003765 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003766 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003767 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003768 self.question_token.to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003769 }
3770 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07003771
David Tolnay2ae520a2017-12-29 11:19:50 -05003772 impl ToTokens for ExprVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003773 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003774 self.tts.to_tokens(tokens);
3775 }
3776 }
3777
Michael Layzell734adb42017-06-07 16:58:31 -04003778 #[cfg(feature = "full")]
David Tolnaybcd498f2017-12-29 12:02:33 -05003779 impl ToTokens for Label {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003780 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaybcd498f2017-12-29 12:02:33 -05003781 self.name.to_tokens(tokens);
3782 self.colon_token.to_tokens(tokens);
3783 }
3784 }
3785
3786 #[cfg(feature = "full")]
David Tolnay055a7042016-10-02 19:23:54 -07003787 impl ToTokens for FieldValue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003788 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003789 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003790 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003791 if let Some(ref colon_token) = self.colon_token {
3792 colon_token.to_tokens(tokens);
David Tolnay276690f2016-10-30 12:06:59 -07003793 self.expr.to_tokens(tokens);
3794 }
David Tolnay055a7042016-10-02 19:23:54 -07003795 }
3796 }
3797
Michael Layzell734adb42017-06-07 16:58:31 -04003798 #[cfg(feature = "full")]
David Tolnayb4ad3b52016-10-01 21:58:13 -07003799 impl ToTokens for Arm {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003800 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003801 tokens.append_all(&self.attrs);
David Tolnay18cc4d42018-03-31 18:47:20 +02003802 self.leading_vert.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003803 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003804 if let Some((ref if_token, ref guard)) = self.guard {
3805 if_token.to_tokens(tokens);
3806 guard.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003807 }
David Tolnaydfb91432018-03-31 19:19:44 +02003808 self.fat_arrow_token.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003809 self.body.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003810 self.comma.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003811 }
3812 }
3813
Michael Layzell734adb42017-06-07 16:58:31 -04003814 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003815 impl ToTokens for PatWild {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003816 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003817 self.underscore_token.to_tokens(tokens);
3818 }
3819 }
3820
Michael Layzell734adb42017-06-07 16:58:31 -04003821 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003822 impl ToTokens for PatIdent {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003823 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay24237fb2017-12-29 02:15:26 -05003824 self.by_ref.to_tokens(tokens);
David Tolnayefc96fb2017-12-29 02:03:15 -05003825 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003826 self.ident.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003827 if let Some((ref at_token, ref subpat)) = self.subpat {
3828 at_token.to_tokens(tokens);
3829 subpat.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003830 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003831 }
3832 }
3833
Michael Layzell734adb42017-06-07 16:58:31 -04003834 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003835 impl ToTokens for PatStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003836 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003837 self.path.to_tokens(tokens);
3838 self.brace_token.surround(tokens, |tokens| {
3839 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003840 // NOTE: We need a comma before the dot2 token if it is present.
3841 if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003842 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003843 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003844 self.dot2_token.to_tokens(tokens);
3845 });
3846 }
3847 }
3848
Michael Layzell734adb42017-06-07 16:58:31 -04003849 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003850 impl ToTokens for PatTupleStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003851 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003852 self.path.to_tokens(tokens);
3853 self.pat.to_tokens(tokens);
3854 }
3855 }
3856
Michael Layzell734adb42017-06-07 16:58:31 -04003857 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003858 impl ToTokens for PatPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003859 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003860 ::PathTokens(&self.qself, &self.path).to_tokens(tokens);
3861 }
3862 }
3863
Michael Layzell734adb42017-06-07 16:58:31 -04003864 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003865 impl ToTokens for PatTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003866 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003867 self.paren_token.surround(tokens, |tokens| {
David Tolnay41871922017-12-29 01:53:45 -05003868 self.front.to_tokens(tokens);
3869 if let Some(ref dot2_token) = self.dot2_token {
3870 if !self.front.empty_or_trailing() {
3871 // Ensure there is a comma before the .. token.
David Tolnayf8db7ba2017-11-11 22:52:16 -08003872 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003873 }
David Tolnay41871922017-12-29 01:53:45 -05003874 dot2_token.to_tokens(tokens);
3875 self.comma_token.to_tokens(tokens);
3876 if self.comma_token.is_none() && !self.back.is_empty() {
3877 // Ensure there is a comma after the .. token.
3878 <Token![,]>::default().to_tokens(tokens);
3879 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07003880 }
David Tolnay41871922017-12-29 01:53:45 -05003881 self.back.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003882 });
3883 }
3884 }
3885
Michael Layzell734adb42017-06-07 16:58:31 -04003886 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003887 impl ToTokens for PatBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003888 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003889 self.box_token.to_tokens(tokens);
3890 self.pat.to_tokens(tokens);
3891 }
3892 }
3893
Michael Layzell734adb42017-06-07 16:58:31 -04003894 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003895 impl ToTokens for PatRef {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003896 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003897 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003898 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003899 self.pat.to_tokens(tokens);
3900 }
3901 }
3902
Michael Layzell734adb42017-06-07 16:58:31 -04003903 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003904 impl ToTokens for PatLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003905 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003906 self.expr.to_tokens(tokens);
3907 }
3908 }
3909
Michael Layzell734adb42017-06-07 16:58:31 -04003910 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003911 impl ToTokens for PatRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003912 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003913 self.lo.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003914 match self.limits {
3915 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
David Tolnay7ac699c2018-08-24 14:00:58 -04003916 RangeLimits::Closed(ref t) => Token![...](t.spans).to_tokens(tokens),
David Tolnay475288a2017-12-19 22:59:44 -08003917 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003918 self.hi.to_tokens(tokens);
3919 }
3920 }
3921
Michael Layzell734adb42017-06-07 16:58:31 -04003922 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003923 impl ToTokens for PatSlice {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003924 fn to_tokens(&self, tokens: &mut TokenStream) {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003925 // XXX: This is a mess, and it will be so easy to screw it up. How
3926 // do we make this correct itself better?
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003927 self.bracket_token.surround(tokens, |tokens| {
3928 self.front.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003929
3930 // If we need a comma before the middle or standalone .. token,
3931 // then make sure it's present.
David Tolnay51382052017-12-27 13:46:21 -05003932 if !self.front.empty_or_trailing()
3933 && (self.middle.is_some() || self.dot2_token.is_some())
Michael Layzell3936ceb2017-07-08 00:28:36 -04003934 {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003935 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003936 }
3937
3938 // If we have an identifier, we always need a .. token.
3939 if self.middle.is_some() {
3940 self.middle.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -07003941 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003942 } else if self.dot2_token.is_some() {
3943 self.dot2_token.to_tokens(tokens);
3944 }
3945
3946 // Make sure we have a comma before the back half.
3947 if !self.back.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07003948 TokensOrDefault(&self.comma_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003949 self.back.to_tokens(tokens);
3950 } else {
3951 self.comma_token.to_tokens(tokens);
3952 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003953 })
David Tolnayb4ad3b52016-10-01 21:58:13 -07003954 }
3955 }
3956
Michael Layzell734adb42017-06-07 16:58:31 -04003957 #[cfg(feature = "full")]
David Tolnay323279a2017-12-29 11:26:32 -05003958 impl ToTokens for PatMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003959 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay323279a2017-12-29 11:26:32 -05003960 self.mac.to_tokens(tokens);
3961 }
3962 }
3963
3964 #[cfg(feature = "full")]
David Tolnay2ae520a2017-12-29 11:19:50 -05003965 impl ToTokens for PatVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003966 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003967 self.tts.to_tokens(tokens);
3968 }
3969 }
3970
3971 #[cfg(feature = "full")]
David Tolnay8d9e81a2016-10-03 22:36:32 -07003972 impl ToTokens for FieldPat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003973 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay5d7098a2017-12-29 01:35:24 -05003974 if let Some(ref colon_token) = self.colon_token {
David Tolnay85b69a42017-12-27 20:43:10 -05003975 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003976 colon_token.to_tokens(tokens);
David Tolnay8d9e81a2016-10-03 22:36:32 -07003977 }
3978 self.pat.to_tokens(tokens);
3979 }
3980 }
3981
Michael Layzell734adb42017-06-07 16:58:31 -04003982 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003983 impl ToTokens for Block {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003984 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003985 self.brace_token.surround(tokens, |tokens| {
3986 tokens.append_all(&self.stmts);
3987 });
David Tolnay42602292016-10-01 22:25:45 -07003988 }
3989 }
3990
Michael Layzell734adb42017-06-07 16:58:31 -04003991 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003992 impl ToTokens for Stmt {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003993 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay42602292016-10-01 22:25:45 -07003994 match *self {
David Tolnay191e0582016-10-02 18:31:09 -07003995 Stmt::Local(ref local) => local.to_tokens(tokens),
David Tolnay42602292016-10-01 22:25:45 -07003996 Stmt::Item(ref item) => item.to_tokens(tokens),
3997 Stmt::Expr(ref expr) => expr.to_tokens(tokens),
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003998 Stmt::Semi(ref expr, ref semi) => {
David Tolnay42602292016-10-01 22:25:45 -07003999 expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07004000 semi.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -07004001 }
David Tolnay42602292016-10-01 22:25:45 -07004002 }
4003 }
4004 }
David Tolnay191e0582016-10-02 18:31:09 -07004005
Michael Layzell734adb42017-06-07 16:58:31 -04004006 #[cfg(feature = "full")]
David Tolnay191e0582016-10-02 18:31:09 -07004007 impl ToTokens for Local {
Alex Crichtona74a1c82018-05-16 10:20:44 -07004008 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07004009 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07004010 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02004011 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05004012 if let Some((ref colon_token, ref ty)) = self.ty {
4013 colon_token.to_tokens(tokens);
4014 ty.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04004015 }
David Tolnay8b4d3022017-12-29 12:11:10 -05004016 if let Some((ref eq_token, ref init)) = self.init {
4017 eq_token.to_tokens(tokens);
4018 init.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04004019 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07004020 self.semi_token.to_tokens(tokens);
David Tolnay191e0582016-10-02 18:31:09 -07004021 }
4022 }
David Tolnayf4bbbd92016-09-23 14:41:55 -07004023}