blob: eaae23f1af70e8585d10fc331e19799343b108a3 [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 Tolnay10f464a2018-08-30 18:48:55 -0700617 Expr::Verbatim(_) => Vec::new(),
David Tolnay8c91b882017-12-28 23:04:32 -0500618 }
619 }
620}
621
David Tolnay85b69a42017-12-27 20:43:10 -0500622ast_enum! {
623 /// A struct or tuple struct field accessed in a struct literal or field
624 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800625 ///
626 /// *This type is available if Syn is built with the `"derive"` or `"full"`
627 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500628 pub enum Member {
629 /// A named field like `self.x`.
630 Named(Ident),
631 /// An unnamed field like `self.0`.
632 Unnamed(Index),
633 }
634}
635
David Tolnay85b69a42017-12-27 20:43:10 -0500636ast_struct! {
637 /// The index of an unnamed tuple struct field.
David Tolnay461d98e2018-01-07 11:07:19 -0800638 ///
639 /// *This type is available if Syn is built with the `"derive"` or `"full"`
640 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500641 pub struct Index #manual_extra_traits {
642 pub index: u32,
643 pub span: Span,
644 }
645}
646
David Tolnay14982012017-12-29 00:49:51 -0500647impl From<usize> for Index {
648 fn from(index: usize) -> Index {
David Tolnay34071ba2018-05-20 20:00:41 -0700649 assert!(index < u32::max_value() as usize);
David Tolnay14982012017-12-29 00:49:51 -0500650 Index {
651 index: index as u32,
Alex Crichton9a4dca22018-03-28 06:32:19 -0700652 span: Span::call_site(),
David Tolnay14982012017-12-29 00:49:51 -0500653 }
654 }
655}
656
657#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500658impl Eq for Index {}
659
David Tolnay14982012017-12-29 00:49:51 -0500660#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500661impl PartialEq for Index {
662 fn eq(&self, other: &Self) -> bool {
663 self.index == other.index
664 }
665}
666
David Tolnay14982012017-12-29 00:49:51 -0500667#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500668impl Hash for Index {
669 fn hash<H: Hasher>(&self, state: &mut H) {
670 self.index.hash(state);
671 }
672}
673
674#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700675ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800676 /// The `::<>` explicit type parameters passed to a method call:
677 /// `parse::<u64>()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800678 ///
679 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500680 pub struct MethodTurbofish {
681 pub colon2_token: Token![::],
682 pub lt_token: Token![<],
David Tolnayf2cfd722017-12-31 18:02:51 -0500683 pub args: Punctuated<GenericMethodArgument, Token![,]>,
David Tolnayd60cfec2017-12-29 00:21:38 -0500684 pub gt_token: Token![>],
685 }
686}
687
688#[cfg(feature = "full")]
689ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800690 /// An individual generic argument to a method, like `T`.
David Tolnay461d98e2018-01-07 11:07:19 -0800691 ///
692 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500693 pub enum GenericMethodArgument {
David Tolnaya454c8f2018-01-07 01:01:10 -0800694 /// A type argument.
David Tolnayd60cfec2017-12-29 00:21:38 -0500695 Type(Type),
David Tolnaya454c8f2018-01-07 01:01:10 -0800696 /// A const expression. Must be inside of a block.
David Tolnayd60cfec2017-12-29 00:21:38 -0500697 ///
698 /// NOTE: Identity expressions are represented as Type arguments, as
699 /// they are indistinguishable syntactically.
700 Const(Expr),
701 }
702}
703
704#[cfg(feature = "full")]
705ast_struct! {
Alex Crichton62a0a592017-05-22 13:58:53 -0700706 /// A field-value pair in a struct literal.
David Tolnay461d98e2018-01-07 11:07:19 -0800707 ///
708 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700709 pub struct FieldValue {
David Tolnay85b69a42017-12-27 20:43:10 -0500710 /// Attributes tagged on the field.
711 pub attrs: Vec<Attribute>,
712
713 /// Name or index of the field.
714 pub member: Member,
715
David Tolnay5d7098a2017-12-29 01:35:24 -0500716 /// The colon in `Struct { x: x }`. If written in shorthand like
717 /// `Struct { x }`, there is no colon.
David Tolnay85b69a42017-12-27 20:43:10 -0500718 pub colon_token: Option<Token![:]>,
Clar Charrd22b5702017-03-10 15:24:56 -0500719
Alex Crichton62a0a592017-05-22 13:58:53 -0700720 /// Value of the field.
721 pub expr: Expr,
Alex Crichton62a0a592017-05-22 13:58:53 -0700722 }
David Tolnay055a7042016-10-02 19:23:54 -0700723}
724
Michael Layzell734adb42017-06-07 16:58:31 -0400725#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700726ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800727 /// A lifetime labeling a `for`, `while`, or `loop`.
David Tolnay461d98e2018-01-07 11:07:19 -0800728 ///
729 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaybcd498f2017-12-29 12:02:33 -0500730 pub struct Label {
731 pub name: Lifetime,
732 pub colon_token: Token![:],
733 }
734}
735
736#[cfg(feature = "full")]
737ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800738 /// A braced block containing Rust statements.
David Tolnay461d98e2018-01-07 11:07:19 -0800739 ///
740 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700741 pub struct Block {
David Tolnay32954ef2017-12-26 22:43:16 -0500742 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700743 /// Statements in a block
744 pub stmts: Vec<Stmt>,
745 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700746}
747
Michael Layzell734adb42017-06-07 16:58:31 -0400748#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700749ast_enum! {
750 /// A statement, usually ending in a semicolon.
David Tolnay461d98e2018-01-07 11:07:19 -0800751 ///
752 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700753 pub enum Stmt {
754 /// A local (let) binding.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800755 Local(Local),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700756
Alex Crichton62a0a592017-05-22 13:58:53 -0700757 /// An item definition.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800758 Item(Item),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700759
Alex Crichton62a0a592017-05-22 13:58:53 -0700760 /// Expr without trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800761 Expr(Expr),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700762
David Tolnaya454c8f2018-01-07 01:01:10 -0800763 /// Expression with trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800764 Semi(Expr, Token![;]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700765 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700766}
767
Michael Layzell734adb42017-06-07 16:58:31 -0400768#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700769ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800770 /// A local `let` binding: `let x: u64 = s.parse()?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800771 ///
772 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700773 pub struct Local {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500774 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800775 pub let_token: Token![let],
David Tolnay5b5b7d22018-03-31 21:05:00 +0200776 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500777 pub ty: Option<(Token![:], Box<Type>)>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500778 pub init: Option<(Token![=], Box<Expr>)>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500779 pub semi_token: Token![;],
Alex Crichton62a0a592017-05-22 13:58:53 -0700780 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700781}
782
Michael Layzell734adb42017-06-07 16:58:31 -0400783#[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700784ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800785 /// A pattern in a local binding, function signature, match expression, or
786 /// various other places.
David Tolnay614a0142018-01-07 10:25:43 -0800787 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800788 /// *This type is available if Syn is built with the `"full"` feature.*
789 ///
David Tolnay614a0142018-01-07 10:25:43 -0800790 /// # Syntax tree enum
791 ///
792 /// This type is a [syntax tree enum].
793 ///
794 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
Alex Crichton62a0a592017-05-22 13:58:53 -0700795 // Clippy false positive
796 // https://github.com/Manishearth/rust-clippy/issues/1241
797 #[cfg_attr(feature = "cargo-clippy", allow(enum_variant_names))]
798 pub enum Pat {
David Tolnaya454c8f2018-01-07 01:01:10 -0800799 /// A pattern that matches any value: `_`.
David Tolnay461d98e2018-01-07 11:07:19 -0800800 ///
801 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700802 pub Wild(PatWild {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800803 pub underscore_token: Token![_],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700804 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700805
David Tolnaya454c8f2018-01-07 01:01:10 -0800806 /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
David Tolnay461d98e2018-01-07 11:07:19 -0800807 ///
808 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700809 pub Ident(PatIdent {
David Tolnay24237fb2017-12-29 02:15:26 -0500810 pub by_ref: Option<Token![ref]>,
811 pub mutability: Option<Token![mut]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700812 pub ident: Ident,
David Tolnay8b4d3022017-12-29 12:11:10 -0500813 pub subpat: Option<(Token![@], Box<Pat>)>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700814 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700815
David Tolnaya454c8f2018-01-07 01:01:10 -0800816 /// A struct or struct variant pattern: `Variant { x, y, .. }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800817 ///
818 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700819 pub Struct(PatStruct {
820 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500821 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500822 pub fields: Punctuated<FieldPat, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800823 pub dot2_token: Option<Token![..]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700824 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700825
David Tolnaya454c8f2018-01-07 01:01:10 -0800826 /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800827 ///
828 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700829 pub TupleStruct(PatTupleStruct {
830 pub path: Path,
831 pub pat: PatTuple,
832 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700833
David Tolnaya454c8f2018-01-07 01:01:10 -0800834 /// A path pattern like `Color::Red`, optionally qualified with a
835 /// self-type.
836 ///
837 /// Unquailfied path patterns can legally refer to variants, structs,
838 /// constants or associated constants. Quailfied path patterns like
839 /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
840 /// associated constants.
David Tolnay461d98e2018-01-07 11:07:19 -0800841 ///
842 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700843 pub Path(PatPath {
844 pub qself: Option<QSelf>,
845 pub path: Path,
846 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700847
David Tolnaya454c8f2018-01-07 01:01:10 -0800848 /// A tuple pattern: `(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800849 ///
850 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700851 pub Tuple(PatTuple {
David Tolnay32954ef2017-12-26 22:43:16 -0500852 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500853 pub front: Punctuated<Pat, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500854 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500855 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500856 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700857 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800858
859 /// A box pattern: `box v`.
David Tolnay461d98e2018-01-07 11:07:19 -0800860 ///
861 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700862 pub Box(PatBox {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800863 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500864 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700865 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800866
867 /// A reference pattern: `&mut (first, second)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800868 ///
869 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700870 pub Ref(PatRef {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800871 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500872 pub mutability: Option<Token![mut]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500873 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700874 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800875
876 /// A literal pattern: `0`.
877 ///
878 /// This holds an `Expr` rather than a `Lit` because negative numbers
879 /// are represented as an `Expr::Unary`.
David Tolnay461d98e2018-01-07 11:07:19 -0800880 ///
881 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700882 pub Lit(PatLit {
883 pub expr: Box<Expr>,
884 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800885
886 /// A range pattern: `1..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800887 ///
888 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700889 pub Range(PatRange {
890 pub lo: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700891 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500892 pub hi: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700893 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800894
895 /// A dynamically sized slice pattern: `[a, b, i.., y, z]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800896 ///
897 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700898 pub Slice(PatSlice {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500899 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500900 pub front: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700901 pub middle: Option<Box<Pat>>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500902 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500903 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500904 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700905 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800906
907 /// A macro in expression position.
David Tolnay461d98e2018-01-07 11:07:19 -0800908 ///
909 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay323279a2017-12-29 11:26:32 -0500910 pub Macro(PatMacro {
911 pub mac: Macro,
912 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800913
914 /// Tokens in pattern position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800915 ///
916 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500917 pub Verbatim(PatVerbatim #manual_extra_traits {
918 pub tts: TokenStream,
919 }),
920 }
921}
922
David Tolnayc43b44e2017-12-30 23:55:54 -0500923#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500924impl Eq for PatVerbatim {}
925
David Tolnayc43b44e2017-12-30 23:55:54 -0500926#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500927impl PartialEq for PatVerbatim {
928 fn eq(&self, other: &Self) -> bool {
929 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
930 }
931}
932
David Tolnayc43b44e2017-12-30 23:55:54 -0500933#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500934impl Hash for PatVerbatim {
935 fn hash<H>(&self, state: &mut H)
936 where
937 H: Hasher,
938 {
939 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700940 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700941}
942
Michael Layzell734adb42017-06-07 16:58:31 -0400943#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700944ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800945 /// One arm of a `match` expression: `0...10 => { return true; }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700946 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800947 /// As in:
Alex Crichton62a0a592017-05-22 13:58:53 -0700948 ///
David Tolnaybcf26022017-12-25 22:10:52 -0500949 /// ```rust
David Tolnaya454c8f2018-01-07 01:01:10 -0800950 /// # fn f() -> bool {
David Tolnaybcf26022017-12-25 22:10:52 -0500951 /// # let n = 0;
Alex Crichton62a0a592017-05-22 13:58:53 -0700952 /// match n {
David Tolnaya454c8f2018-01-07 01:01:10 -0800953 /// 0...10 => {
954 /// return true;
955 /// }
956 /// // ...
David Tolnaybcf26022017-12-25 22:10:52 -0500957 /// # _ => {}
Alex Crichton62a0a592017-05-22 13:58:53 -0700958 /// }
David Tolnaya454c8f2018-01-07 01:01:10 -0800959 /// # false
David Tolnaybcf26022017-12-25 22:10:52 -0500960 /// # }
Alex Crichton62a0a592017-05-22 13:58:53 -0700961 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800962 ///
963 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700964 pub struct Arm {
965 pub attrs: Vec<Attribute>,
David Tolnay18cc4d42018-03-31 18:47:20 +0200966 pub leading_vert: Option<Token![|]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500967 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500968 pub guard: Option<(Token![if], Box<Expr>)>,
David Tolnaydfb91432018-03-31 19:19:44 +0200969 pub fat_arrow_token: Token![=>],
Alex Crichton62a0a592017-05-22 13:58:53 -0700970 pub body: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800971 pub comma: Option<Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700972 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700973}
974
Michael Layzell734adb42017-06-07 16:58:31 -0400975#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700976ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800977 /// Limit types of a range, inclusive or exclusive.
David Tolnay461d98e2018-01-07 11:07:19 -0800978 ///
979 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton2e0229c2017-05-23 09:34:50 -0700980 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700981 pub enum RangeLimits {
David Tolnaya454c8f2018-01-07 01:01:10 -0800982 /// Inclusive at the beginning, exclusive at the end.
David Tolnayf8db7ba2017-11-11 22:52:16 -0800983 HalfOpen(Token![..]),
David Tolnaya454c8f2018-01-07 01:01:10 -0800984 /// Inclusive at the beginning and end.
David Tolnaybe55d7b2017-12-17 23:41:20 -0800985 Closed(Token![..=]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700986 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700987}
988
Michael Layzell734adb42017-06-07 16:58:31 -0400989#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700990ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800991 /// A single field in a struct pattern.
Alex Crichton62a0a592017-05-22 13:58:53 -0700992 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800993 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
994 /// 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 -0800995 ///
996 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700997 pub struct FieldPat {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500998 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -0500999 pub member: Member,
David Tolnay4a3f59a2017-12-28 21:21:12 -05001000 pub colon_token: Option<Token![:]>,
Alex Crichton62a0a592017-05-22 13:58:53 -07001001 pub pat: Box<Pat>,
Alex Crichton62a0a592017-05-22 13:58:53 -07001002 }
David Tolnayf4bbbd92016-09-23 14:41:55 -07001003}
1004
Michael Layzell3936ceb2017-07-08 00:28:36 -04001005#[cfg(any(feature = "parsing", feature = "printing"))]
1006#[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -07001007fn requires_terminator(expr: &Expr) -> bool {
David Tolnay01218d12018-08-29 18:13:07 -07001008 // see https://github.com/rust-lang/rust/blob/eb8f2586e/src/libsyntax/parse/classify.rs#L17-L37
David Tolnay8c91b882017-12-28 23:04:32 -05001009 match *expr {
1010 Expr::Unsafe(..)
1011 | Expr::Block(..)
1012 | Expr::If(..)
1013 | Expr::IfLet(..)
1014 | Expr::Match(..)
1015 | Expr::While(..)
1016 | Expr::WhileLet(..)
1017 | Expr::Loop(..)
1018 | Expr::ForLoop(..)
David Tolnay02a9c6f2018-08-24 18:58:45 -04001019 | Expr::Async(..)
David Tolnayfb2dd4b2018-08-24 16:45:34 -04001020 | Expr::TryBlock(..) => false,
Alex Crichton03b30272017-08-28 09:35:24 -07001021 _ => true,
Michael Layzell3936ceb2017-07-08 00:28:36 -04001022 }
1023}
1024
David Tolnayb9c8e322016-09-23 20:48:37 -07001025#[cfg(feature = "parsing")]
1026pub mod parsing {
1027 use super::*;
David Tolnay60291082018-08-28 09:54:49 -07001028 use path;
David Tolnayb9c8e322016-09-23 20:48:37 -07001029
David Tolnay9389c382018-08-27 09:13:37 -07001030 use parse::{Parse, ParseStream, Result};
Michael Layzell734adb42017-06-07 16:58:31 -04001031 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001032 use synom::ext::IdentExt;
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001033
David Tolnaybcf26022017-12-25 22:10:52 -05001034 // When we're parsing expressions which occur before blocks, like in an if
1035 // statement's condition, we cannot parse a struct literal.
1036 //
1037 // Struct literals are ambiguous in certain positions
1038 // https://github.com/rust-lang/rfcs/pull/92
David Tolnay9389c382018-08-27 09:13:37 -07001039 #[derive(Copy, Clone)]
1040 pub struct AllowStruct(bool);
1041
David Tolnay01218d12018-08-29 18:13:07 -07001042 #[derive(Copy, Clone, PartialEq, PartialOrd)]
1043 enum Precedence {
1044 Any,
1045 Assign,
1046 Placement,
1047 Range,
1048 Or,
1049 And,
1050 Compare,
1051 BitOr,
1052 BitXor,
1053 BitAnd,
1054 Shift,
1055 Arithmetic,
1056 Term,
1057 Cast,
1058 }
1059
1060 impl Precedence {
1061 fn of(op: &BinOp) -> Self {
1062 match *op {
1063 BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic,
1064 BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term,
1065 BinOp::And(_) => Precedence::And,
1066 BinOp::Or(_) => Precedence::Or,
1067 BinOp::BitXor(_) => Precedence::BitXor,
1068 BinOp::BitAnd(_) => Precedence::BitAnd,
1069 BinOp::BitOr(_) => Precedence::BitOr,
1070 BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
David Tolnay73b7ca12018-08-30 21:05:13 -07001071 BinOp::Eq(_)
1072 | BinOp::Lt(_)
1073 | BinOp::Le(_)
1074 | BinOp::Ne(_)
1075 | BinOp::Ge(_)
1076 | BinOp::Gt(_) => Precedence::Compare,
1077 BinOp::AddEq(_)
1078 | BinOp::SubEq(_)
1079 | BinOp::MulEq(_)
1080 | BinOp::DivEq(_)
1081 | BinOp::RemEq(_)
1082 | BinOp::BitXorEq(_)
1083 | BinOp::BitAndEq(_)
1084 | BinOp::BitOrEq(_)
1085 | BinOp::ShlEq(_)
1086 | BinOp::ShrEq(_) => Precedence::Assign,
David Tolnay01218d12018-08-29 18:13:07 -07001087 }
1088 }
1089 }
1090
David Tolnay9389c382018-08-27 09:13:37 -07001091 impl Parse for Expr {
1092 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001093 ambiguous_expr(input, AllowStruct(true))
Alex Crichton954046c2017-05-30 21:49:42 -07001094 }
1095 }
1096
Michael Layzell734adb42017-06-07 16:58:31 -04001097 #[cfg(feature = "full")]
David Tolnay9fb0aed2018-08-27 10:23:12 -07001098 fn expr_no_struct(input: ParseStream) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001099 ambiguous_expr(input, AllowStruct(false))
David Tolnay9fb0aed2018-08-27 10:23:12 -07001100 }
David Tolnayaf2557e2016-10-24 11:52:21 -07001101
David Tolnay01218d12018-08-29 18:13:07 -07001102 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001103 fn parse_expr(
1104 input: ParseStream,
1105 mut lhs: Expr,
1106 allow_struct: AllowStruct,
1107 base: Precedence,
1108 ) -> Result<Expr> {
David Tolnay01218d12018-08-29 18:13:07 -07001109 loop {
David Tolnay73b7ca12018-08-30 21:05:13 -07001110 if input
1111 .fork()
1112 .parse::<BinOp>()
1113 .ok()
1114 .map_or(false, |op| Precedence::of(&op) >= base)
1115 {
David Tolnay01218d12018-08-29 18:13:07 -07001116 let op: BinOp = input.parse()?;
1117 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001118 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001119 loop {
1120 let next = peek_precedence(input);
1121 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001122 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001123 } else {
1124 break;
1125 }
1126 }
1127 lhs = Expr::Binary(ExprBinary {
1128 attrs: Vec::new(),
1129 left: Box::new(lhs),
1130 op: op,
1131 right: Box::new(rhs),
1132 });
David Tolnay73b7ca12018-08-30 21:05:13 -07001133 } else if Precedence::Assign >= base
1134 && input.peek(Token![=])
1135 && !input.peek(Token![==])
1136 && !input.peek(Token![=>])
1137 {
David Tolnay01218d12018-08-29 18:13:07 -07001138 let eq_token: Token![=] = input.parse()?;
David Tolnay7d2e1db2018-08-30 11:49:04 -07001139 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001140 loop {
1141 let next = peek_precedence(input);
1142 if next >= Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001143 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001144 } else {
1145 break;
1146 }
1147 }
1148 lhs = Expr::Assign(ExprAssign {
1149 attrs: Vec::new(),
1150 left: Box::new(lhs),
1151 eq_token: eq_token,
1152 right: Box::new(rhs),
1153 });
1154 } else if Precedence::Placement >= base && input.peek(Token![<-]) {
1155 let arrow_token: Token![<-] = input.parse()?;
David Tolnay7d2e1db2018-08-30 11:49:04 -07001156 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001157 loop {
1158 let next = peek_precedence(input);
1159 if next > Precedence::Placement {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001160 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001161 } else {
1162 break;
1163 }
1164 }
1165 lhs = Expr::InPlace(ExprInPlace {
1166 attrs: Vec::new(),
1167 place: Box::new(lhs),
1168 arrow_token: arrow_token,
1169 value: Box::new(rhs),
1170 });
1171 } else if Precedence::Range >= base && input.peek(Token![..]) {
1172 let limits: RangeLimits = input.parse()?;
1173 let rhs = if input.is_empty()
1174 || input.peek(Token![,])
1175 || input.peek(Token![;])
1176 || !allow_struct.0 && input.peek(token::Brace)
1177 {
1178 None
1179 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001180 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001181 loop {
1182 let next = peek_precedence(input);
1183 if next > Precedence::Range {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001184 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001185 } else {
1186 break;
1187 }
1188 }
1189 Some(rhs)
1190 };
1191 lhs = Expr::Range(ExprRange {
1192 attrs: Vec::new(),
1193 from: Some(Box::new(lhs)),
1194 limits: limits,
1195 to: rhs.map(Box::new),
1196 });
1197 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1198 let as_token: Token![as] = input.parse()?;
1199 let ty = input.call(Type::without_plus)?;
1200 lhs = Expr::Cast(ExprCast {
1201 attrs: Vec::new(),
1202 expr: Box::new(lhs),
1203 as_token: as_token,
1204 ty: Box::new(ty),
1205 });
1206 } else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) {
1207 let colon_token: Token![:] = input.parse()?;
1208 let ty = input.call(Type::without_plus)?;
1209 lhs = Expr::Type(ExprType {
1210 attrs: Vec::new(),
1211 expr: Box::new(lhs),
1212 colon_token: colon_token,
1213 ty: Box::new(ty),
1214 });
1215 } else {
1216 break;
1217 }
1218 }
1219 Ok(lhs)
1220 }
1221
David Tolnay3e541292018-08-30 11:42:15 -07001222 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001223 fn parse_expr(
1224 input: ParseStream,
1225 mut lhs: Expr,
1226 allow_struct: AllowStruct,
1227 base: Precedence,
1228 ) -> Result<Expr> {
David Tolnay3e541292018-08-30 11:42:15 -07001229 loop {
David Tolnay73b7ca12018-08-30 21:05:13 -07001230 if input
1231 .fork()
1232 .parse::<BinOp>()
1233 .ok()
1234 .map_or(false, |op| Precedence::of(&op) >= base)
1235 {
David Tolnay3e541292018-08-30 11:42:15 -07001236 let op: BinOp = input.parse()?;
1237 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001238 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay3e541292018-08-30 11:42:15 -07001239 loop {
1240 let next = peek_precedence(input);
1241 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001242 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay3e541292018-08-30 11:42:15 -07001243 } else {
1244 break;
1245 }
1246 }
1247 lhs = Expr::Binary(ExprBinary {
1248 attrs: Vec::new(),
1249 left: Box::new(lhs),
1250 op: op,
1251 right: Box::new(rhs),
1252 });
1253 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1254 let as_token: Token![as] = input.parse()?;
1255 let ty = input.call(Type::without_plus)?;
1256 lhs = Expr::Cast(ExprCast {
1257 attrs: Vec::new(),
1258 expr: Box::new(lhs),
1259 as_token: as_token,
1260 ty: Box::new(ty),
1261 });
1262 } else {
1263 break;
1264 }
1265 }
1266 Ok(lhs)
1267 }
1268
David Tolnay01218d12018-08-29 18:13:07 -07001269 fn peek_precedence(input: ParseStream) -> Precedence {
1270 if let Ok(op) = input.fork().parse() {
1271 Precedence::of(&op)
David Tolnay3e541292018-08-30 11:42:15 -07001272 } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
David Tolnay01218d12018-08-29 18:13:07 -07001273 Precedence::Assign
1274 } else if input.peek(Token![<-]) {
1275 Precedence::Placement
1276 } else if input.peek(Token![..]) {
1277 Precedence::Range
1278 } else if input.peek(Token![as]) || input.peek(Token![:]) && !input.peek(Token![::]) {
1279 Precedence::Cast
1280 } else {
1281 Precedence::Any
1282 }
1283 }
1284
David Tolnaybcf26022017-12-25 22:10:52 -05001285 // Parse an arbitrary expression.
David Tolnay73b7ca12018-08-30 21:05:13 -07001286 fn ambiguous_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001287 let lhs = unary_expr(input, allow_struct)?;
1288 parse_expr(input, lhs, allow_struct, Precedence::Any)
Michael Layzellb78f3b52017-06-04 19:03:03 -04001289 }
1290
David Tolnaybcf26022017-12-25 22:10:52 -05001291 // <UnOp> <trailer>
1292 // & <trailer>
1293 // &mut <trailer>
1294 // box <trailer>
Michael Layzell734adb42017-06-07 16:58:31 -04001295 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001296 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001297 let ahead = input.fork();
1298 ahead.call(Attribute::parse_outer)?;
1299 if ahead.peek(Token![&])
1300 || ahead.peek(Token![box])
1301 || ahead.peek(Token![*])
1302 || ahead.peek(Token![!])
1303 || ahead.peek(Token![-])
1304 {
1305 let attrs = input.call(Attribute::parse_outer)?;
1306 if input.peek(Token![&]) {
1307 Ok(Expr::Reference(ExprReference {
1308 attrs: attrs,
1309 and_token: input.parse()?,
1310 mutability: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001311 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001312 }))
1313 } else if input.peek(Token![box]) {
1314 Ok(Expr::Box(ExprBox {
1315 attrs: attrs,
1316 box_token: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001317 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001318 }))
1319 } else {
1320 Ok(Expr::Unary(ExprUnary {
1321 attrs: attrs,
1322 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001323 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001324 }))
1325 }
1326 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001327 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001328 }
1329 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001330
Michael Layzell734adb42017-06-07 16:58:31 -04001331 // XXX: This duplication is ugly
1332 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001333 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001334 let ahead = input.fork();
1335 ahead.call(Attribute::parse_outer)?;
1336 if ahead.peek(Token![*]) || ahead.peek(Token![!]) || ahead.peek(Token![-]) {
1337 Ok(Expr::Unary(ExprUnary {
1338 attrs: input.call(Attribute::parse_outer)?,
1339 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001340 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001341 }))
1342 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001343 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001344 }
1345 }
Michael Layzell734adb42017-06-07 16:58:31 -04001346
David Tolnayd997aef2018-07-21 18:42:31 -07001347 #[cfg(feature = "full")]
David Tolnay5d314dc2018-07-21 16:40:01 -07001348 fn take_outer(attrs: &mut Vec<Attribute>) -> Vec<Attribute> {
1349 let mut outer = Vec::new();
1350 let mut inner = Vec::new();
1351 for attr in mem::replace(attrs, Vec::new()) {
1352 match attr.style {
1353 AttrStyle::Outer => outer.push(attr),
1354 AttrStyle::Inner(_) => inner.push(attr),
1355 }
1356 }
1357 *attrs = inner;
1358 outer
1359 }
1360
David Tolnaybcf26022017-12-25 22:10:52 -05001361 // <atom> (..<args>) ...
1362 // <atom> . <ident> (..<args>) ...
1363 // <atom> . <ident> ...
1364 // <atom> . <lit> ...
1365 // <atom> [ <expr> ] ...
1366 // <atom> ? ...
Michael Layzell734adb42017-06-07 16:58:31 -04001367 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001368 fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001369 let mut e = atom_expr(input, allow_struct)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001370
1371 let mut attrs = e.replace_attrs(Vec::new());
1372 let outer_attrs = take_outer(&mut attrs);
1373 e.replace_attrs(attrs);
1374
David Tolnay01218d12018-08-29 18:13:07 -07001375 e = trailer_helper(input, e)?;
1376
1377 let mut attrs = outer_attrs;
1378 attrs.extend(e.replace_attrs(Vec::new()));
1379 e.replace_attrs(attrs);
1380 Ok(e)
1381 }
1382
1383 #[cfg(feature = "full")]
1384 fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
David Tolnay1501f7e2018-08-27 14:21:03 -07001385 loop {
1386 if input.peek(token::Paren) {
1387 let content;
1388 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001389 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001390 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001391 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001392 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001393 });
1394 } else if input.peek(Token![.]) && !input.peek(Token![..]) {
1395 let dot_token: Token![.] = input.parse()?;
1396 let member: Member = input.parse()?;
1397 let turbofish = if member.is_named() && input.peek(Token![::]) {
1398 Some(MethodTurbofish {
1399 colon2_token: input.parse()?,
1400 lt_token: input.parse()?,
1401 args: {
1402 let mut args = Punctuated::new();
1403 loop {
1404 if input.peek(Token![>]) {
1405 break;
1406 }
David Tolnay310b3262018-08-30 15:33:00 -07001407 let value = input.call(generic_method_argument)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001408 args.push_value(value);
1409 if input.peek(Token![>]) {
1410 break;
1411 }
1412 let punct = input.parse()?;
1413 args.push_punct(punct);
1414 }
1415 args
1416 },
1417 gt_token: input.parse()?,
1418 })
1419 } else {
1420 None
1421 };
1422
1423 if turbofish.is_some() || input.peek(token::Paren) {
1424 if let Member::Named(method) = member {
1425 let content;
1426 e = Expr::MethodCall(ExprMethodCall {
1427 attrs: Vec::new(),
1428 receiver: Box::new(e),
1429 dot_token: dot_token,
1430 method: method,
1431 turbofish: turbofish,
1432 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001433 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001434 });
1435 continue;
1436 }
1437 }
1438
1439 e = Expr::Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -05001440 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001441 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001442 dot_token: dot_token,
David Tolnay85b69a42017-12-27 20:43:10 -05001443 member: member,
David Tolnay1501f7e2018-08-27 14:21:03 -07001444 });
1445 } else if input.peek(token::Bracket) {
1446 let content;
1447 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001448 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001449 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001450 bracket_token: bracketed!(content in input),
1451 index: content.parse()?,
1452 });
1453 } else if input.peek(Token![?]) {
1454 e = Expr::Try(ExprTry {
David Tolnay8c91b882017-12-28 23:04:32 -05001455 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001456 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001457 question_token: input.parse()?,
1458 });
1459 } else {
1460 break;
1461 }
1462 }
David Tolnay1501f7e2018-08-27 14:21:03 -07001463 Ok(e)
1464 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001465
Michael Layzell734adb42017-06-07 16:58:31 -04001466 // XXX: Duplication == ugly
1467 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001468 fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001469 let mut e = atom_expr(input, allow_struct)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001470
1471 loop {
1472 if input.peek(token::Paren) {
1473 let content;
1474 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001475 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001476 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001477 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001478 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001479 });
1480 } else if input.peek(Token![.]) {
1481 e = Expr::Field(ExprField {
David Tolnayd5147742018-06-30 10:09:52 -07001482 attrs: Vec::new(),
1483 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001484 dot_token: input.parse()?,
1485 member: input.parse()?,
1486 });
1487 } else if input.peek(token::Bracket) {
1488 let content;
1489 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001490 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001491 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001492 bracket_token: bracketed!(content in input),
1493 index: content.parse()?,
1494 });
1495 } else {
1496 break;
1497 }
1498 }
1499
1500 Ok(e)
1501 }
Michael Layzell734adb42017-06-07 16:58:31 -04001502
David Tolnaya454c8f2018-01-07 01:01:10 -08001503 // Parse all atomic expressions which don't have to worry about precedence
David Tolnaybcf26022017-12-25 22:10:52 -05001504 // interactions, as they are fully contained.
Michael Layzell734adb42017-06-07 16:58:31 -04001505 #[cfg(feature = "full")]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001506 fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001507 if input.peek(token::Group) {
David Tolnay310b3262018-08-30 15:33:00 -07001508 return input.call(expr_group).map(Expr::Group);
David Tolnay6e1e5052018-08-30 10:21:48 -07001509 }
1510
1511 let mut attrs = input.call(Attribute::parse_outer)?;
1512
1513 let mut expr = if input.peek(token::Group) {
David Tolnay310b3262018-08-30 15:33:00 -07001514 Expr::Group(input.call(expr_group)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001515 } else if input.peek(Lit) {
David Tolnay310b3262018-08-30 15:33:00 -07001516 Expr::Lit(input.call(expr_lit)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001517 } else if input.peek(Token![async])
1518 && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
1519 {
David Tolnay310b3262018-08-30 15:33:00 -07001520 Expr::Async(input.call(expr_async)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001521 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001522 Expr::TryBlock(input.call(expr_try_block)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001523 } else if input.peek(Token![|])
1524 || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1525 || input.peek(Token![static])
1526 || input.peek(Token![move])
1527 {
1528 Expr::Closure(expr_closure(input, allow_struct)?)
1529 } else if input.peek(Ident)
1530 || input.peek(Token![::])
1531 || input.peek(Token![<])
1532 || input.peek(Token![self])
1533 || input.peek(Token![Self])
1534 || input.peek(Token![super])
1535 || input.peek(Token![extern])
1536 || input.peek(Token![crate])
1537 {
1538 path_or_macro_or_struct(input, allow_struct)?
1539 } else if input.peek(token::Paren) {
1540 paren_or_tuple(input)?
1541 } else if input.peek(Token![break]) {
1542 Expr::Break(expr_break(input, allow_struct)?)
1543 } else if input.peek(Token![continue]) {
David Tolnay310b3262018-08-30 15:33:00 -07001544 Expr::Continue(input.call(expr_continue)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001545 } else if input.peek(Token![return]) {
1546 Expr::Return(expr_ret(input, allow_struct)?)
1547 } else if input.peek(token::Bracket) {
1548 array_or_repeat(input)?
1549 } else if input.peek(Token![if]) {
1550 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001551 Expr::IfLet(input.call(expr_if_let)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001552 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001553 Expr::If(input.call(expr_if)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001554 }
1555 } else if input.peek(Token![while]) {
1556 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001557 Expr::WhileLet(input.call(expr_while_let)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001558 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001559 Expr::While(input.call(expr_while)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001560 }
1561 } else if input.peek(Token![for]) {
David Tolnay310b3262018-08-30 15:33:00 -07001562 Expr::ForLoop(input.call(expr_for_loop)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001563 } else if input.peek(Token![loop]) {
David Tolnay310b3262018-08-30 15:33:00 -07001564 Expr::Loop(input.call(expr_loop)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001565 } else if input.peek(Token![match]) {
David Tolnay310b3262018-08-30 15:33:00 -07001566 Expr::Match(input.call(expr_match)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001567 } else if input.peek(Token![yield]) {
David Tolnay310b3262018-08-30 15:33:00 -07001568 Expr::Yield(input.call(expr_yield)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001569 } else if input.peek(Token![unsafe]) {
David Tolnay310b3262018-08-30 15:33:00 -07001570 Expr::Unsafe(input.call(expr_unsafe)?)
David Tolnay7d2e1db2018-08-30 11:49:04 -07001571 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001572 Expr::Block(input.call(expr_block)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001573 } else if input.peek(Token![..]) {
1574 Expr::Range(expr_range(input, allow_struct)?)
1575 } else if input.peek(Lifetime) {
1576 let the_label: Label = input.parse()?;
1577 let mut expr = if input.peek(Token![while]) {
1578 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001579 Expr::WhileLet(input.call(expr_while_let)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001580 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001581 Expr::While(input.call(expr_while)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001582 }
1583 } else if input.peek(Token![for]) {
David Tolnay310b3262018-08-30 15:33:00 -07001584 Expr::ForLoop(input.call(expr_for_loop)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001585 } else if input.peek(Token![loop]) {
David Tolnay310b3262018-08-30 15:33:00 -07001586 Expr::Loop(input.call(expr_loop)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001587 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001588 Expr::Block(input.call(expr_block)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001589 } else {
1590 return Err(input.error("expected loop or block expression"));
1591 };
1592 match expr {
David Tolnay73b7ca12018-08-30 21:05:13 -07001593 Expr::WhileLet(ExprWhileLet { ref mut label, .. })
1594 | Expr::While(ExprWhile { ref mut label, .. })
1595 | Expr::ForLoop(ExprForLoop { ref mut label, .. })
1596 | Expr::Loop(ExprLoop { ref mut label, .. })
1597 | Expr::Block(ExprBlock { ref mut label, .. }) => *label = Some(the_label),
David Tolnay6e1e5052018-08-30 10:21:48 -07001598 _ => unreachable!(),
1599 }
1600 expr
1601 } else {
1602 return Err(input.error("expected expression"));
1603 };
1604
1605 attrs.extend(expr.replace_attrs(Vec::new()));
1606 expr.replace_attrs(attrs);
1607 Ok(expr)
1608 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001609
Michael Layzell734adb42017-06-07 16:58:31 -04001610 #[cfg(not(feature = "full"))]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001611 fn atom_expr(input: ParseStream, _allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001612 if input.peek(Lit) {
David Tolnay310b3262018-08-30 15:33:00 -07001613 input.call(expr_lit).map(Expr::Lit)
David Tolnay6e1e5052018-08-30 10:21:48 -07001614 } else if input.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07001615 input.call(expr_paren).map(Expr::Paren)
David Tolnay6e1e5052018-08-30 10:21:48 -07001616 } else if input.peek(Ident)
1617 || input.peek(Token![::])
1618 || input.peek(Token![<])
1619 || input.peek(Token![self])
1620 || input.peek(Token![Self])
1621 || input.peek(Token![super])
1622 || input.peek(Token![extern])
1623 || input.peek(Token![crate])
1624 {
1625 input.parse().map(Expr::Path)
1626 } else {
1627 Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
1628 }
1629 }
1630
1631 #[cfg(feature = "full")]
1632 fn path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1633 let expr: ExprPath = input.parse()?;
1634 if expr.qself.is_some() {
1635 return Ok(Expr::Path(expr));
1636 }
1637
1638 if input.peek(Token![!]) && !input.peek(Token![!=]) {
1639 let mut contains_arguments = false;
1640 for segment in &expr.path.segments {
1641 match segment.arguments {
1642 PathArguments::None => {}
1643 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
1644 contains_arguments = true;
1645 }
1646 }
1647 }
1648
1649 if !contains_arguments {
1650 let bang_token: Token![!] = input.parse()?;
1651 let (delimiter, tts) = mac::parse_delimiter(input)?;
1652 return Ok(Expr::Macro(ExprMacro {
1653 attrs: Vec::new(),
1654 mac: Macro {
1655 path: expr.path,
1656 bang_token: bang_token,
1657 delimiter: delimiter,
1658 tts: tts,
1659 },
1660 }));
1661 }
1662 }
1663
1664 if allow_struct.0 && input.peek(token::Brace) {
1665 let outer_attrs = Vec::new();
1666 expr_struct_helper(input, outer_attrs, expr.path).map(Expr::Struct)
1667 } else {
1668 Ok(Expr::Path(expr))
1669 }
1670 }
1671
1672 #[cfg(feature = "full")]
1673 fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
1674 let content;
1675 let paren_token = parenthesized!(content in input);
1676 let inner_attrs = content.call(Attribute::parse_inner)?;
1677 if content.is_empty() {
1678 return Ok(Expr::Tuple(ExprTuple {
1679 attrs: inner_attrs,
1680 paren_token: paren_token,
1681 elems: Punctuated::new(),
1682 }));
1683 }
1684
1685 let first: Expr = content.parse()?;
1686 if content.is_empty() {
1687 return Ok(Expr::Paren(ExprParen {
1688 attrs: inner_attrs,
1689 paren_token: paren_token,
1690 expr: Box::new(first),
1691 }));
1692 }
1693
1694 let mut elems = Punctuated::new();
1695 elems.push_value(first);
1696 while !content.is_empty() {
1697 let punct = content.parse()?;
1698 elems.push_punct(punct);
1699 if content.is_empty() {
1700 break;
1701 }
1702 let value = content.parse()?;
1703 elems.push_value(value);
1704 }
1705 Ok(Expr::Tuple(ExprTuple {
1706 attrs: inner_attrs,
1707 paren_token: paren_token,
1708 elems: elems,
1709 }))
1710 }
1711
1712 #[cfg(feature = "full")]
1713 fn array_or_repeat(input: ParseStream) -> Result<Expr> {
1714 let content;
1715 let bracket_token = bracketed!(content in input);
1716 let inner_attrs = content.call(Attribute::parse_inner)?;
1717 if content.is_empty() {
1718 return Ok(Expr::Array(ExprArray {
1719 attrs: inner_attrs,
1720 bracket_token: bracket_token,
1721 elems: Punctuated::new(),
1722 }));
1723 }
1724
1725 let first: Expr = content.parse()?;
1726 if content.is_empty() || content.peek(Token![,]) {
1727 let mut elems = Punctuated::new();
1728 elems.push_value(first);
1729 while !content.is_empty() {
1730 let punct = content.parse()?;
1731 elems.push_punct(punct);
1732 if content.is_empty() {
1733 break;
1734 }
1735 let value = content.parse()?;
1736 elems.push_value(value);
1737 }
1738 Ok(Expr::Array(ExprArray {
1739 attrs: inner_attrs,
1740 bracket_token: bracket_token,
1741 elems: elems,
1742 }))
1743 } else if content.peek(Token![;]) {
1744 let semi_token: Token![;] = content.parse()?;
1745 let len: Expr = content.parse()?;
1746 Ok(Expr::Repeat(ExprRepeat {
1747 attrs: inner_attrs,
1748 bracket_token: bracket_token,
1749 expr: Box::new(first),
1750 semi_token: semi_token,
1751 len: Box::new(len),
1752 }))
1753 } else {
1754 Err(content.error("expected `,` or `;`"))
1755 }
1756 }
Michael Layzell734adb42017-06-07 16:58:31 -04001757
Michael Layzell734adb42017-06-07 16:58:31 -04001758 #[cfg(feature = "full")]
David Tolnay01218d12018-08-29 18:13:07 -07001759 fn expr_early(input: ParseStream) -> Result<Expr> {
1760 let mut attrs = input.call(Attribute::parse_outer)?;
1761 let mut expr = if input.peek(Token![if]) {
1762 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001763 Expr::IfLet(input.call(expr_if_let)?)
David Tolnay01218d12018-08-29 18:13:07 -07001764 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001765 Expr::If(input.call(expr_if)?)
David Tolnay01218d12018-08-29 18:13:07 -07001766 }
1767 } else if input.peek(Token![while]) {
1768 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001769 Expr::WhileLet(input.call(expr_while_let)?)
David Tolnay01218d12018-08-29 18:13:07 -07001770 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001771 Expr::While(input.call(expr_while)?)
David Tolnay01218d12018-08-29 18:13:07 -07001772 }
1773 } else if input.peek(Token![for]) {
David Tolnay310b3262018-08-30 15:33:00 -07001774 Expr::ForLoop(input.call(expr_for_loop)?)
David Tolnay01218d12018-08-29 18:13:07 -07001775 } else if input.peek(Token![loop]) {
David Tolnay310b3262018-08-30 15:33:00 -07001776 Expr::Loop(input.call(expr_loop)?)
David Tolnay01218d12018-08-29 18:13:07 -07001777 } else if input.peek(Token![match]) {
David Tolnay310b3262018-08-30 15:33:00 -07001778 Expr::Match(input.call(expr_match)?)
David Tolnay01218d12018-08-29 18:13:07 -07001779 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001780 Expr::TryBlock(input.call(expr_try_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001781 } else if input.peek(Token![unsafe]) {
David Tolnay310b3262018-08-30 15:33:00 -07001782 Expr::Unsafe(input.call(expr_unsafe)?)
David Tolnay01218d12018-08-29 18:13:07 -07001783 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001784 Expr::Block(input.call(expr_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001785 } else {
1786 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001787 let mut expr = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001788
1789 attrs.extend(expr.replace_attrs(Vec::new()));
1790 expr.replace_attrs(attrs);
1791
David Tolnay7d2e1db2018-08-30 11:49:04 -07001792 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001793 };
1794
1795 if input.peek(Token![.]) || input.peek(Token![?]) {
1796 expr = trailer_helper(input, expr)?;
1797
1798 attrs.extend(expr.replace_attrs(Vec::new()));
1799 expr.replace_attrs(attrs);
1800
1801 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001802 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001803 }
1804
1805 attrs.extend(expr.replace_attrs(Vec::new()));
1806 expr.replace_attrs(attrs);
1807 Ok(expr)
1808 }
Michael Layzell35418782017-06-07 09:20:25 -04001809
David Tolnay310b3262018-08-30 15:33:00 -07001810 pub fn expr_lit(input: ParseStream) -> Result<ExprLit> {
1811 Ok(ExprLit {
1812 attrs: Vec::new(),
1813 lit: input.parse()?,
1814 })
David Tolnay8c91b882017-12-28 23:04:32 -05001815 }
1816
1817 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001818 fn expr_group(input: ParseStream) -> Result<ExprGroup> {
1819 let content;
1820 Ok(ExprGroup {
1821 attrs: Vec::new(),
1822 group_token: grouped!(content in input),
1823 expr: content.parse()?,
1824 })
1825 }
1826
1827 #[cfg(not(feature = "full"))]
1828 fn expr_paren(input: ParseStream) -> Result<ExprParen> {
1829 let content;
1830 Ok(ExprParen {
1831 attrs: Vec::new(),
1832 paren_token: parenthesized!(content in input),
1833 expr: content.parse()?,
1834 })
David Tolnay8c91b882017-12-28 23:04:32 -05001835 }
1836
David Tolnaye98775f2017-12-28 23:17:00 -05001837 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001838 fn generic_method_argument(input: ParseStream) -> Result<GenericMethodArgument> {
David Tolnayd60cfec2017-12-29 00:21:38 -05001839 // TODO parse const generics as well
David Tolnay8db2d662018-08-30 17:40:59 -07001840 input.parse().map(GenericMethodArgument::Type)
David Tolnayd60cfec2017-12-29 00:21:38 -05001841 }
1842
1843 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001844 fn expr_if_let(input: ParseStream) -> Result<ExprIfLet> {
1845 Ok(ExprIfLet {
1846 attrs: Vec::new(),
1847 if_token: input.parse()?,
1848 let_token: input.parse()?,
1849 pats: {
1850 let mut pats = Punctuated::new();
1851 let value: Pat = input.parse()?;
1852 pats.push_value(value);
David Tolnay73b7ca12018-08-30 21:05:13 -07001853 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
David Tolnay310b3262018-08-30 15:33:00 -07001854 let punct = input.parse()?;
1855 pats.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07001856 let value: Pat = input.parse()?;
1857 pats.push_value(value);
David Tolnay310b3262018-08-30 15:33:00 -07001858 }
1859 pats
1860 },
1861 eq_token: input.parse()?,
1862 expr: Box::new(input.call(expr_no_struct)?),
1863 then_branch: input.parse()?,
1864 else_branch: {
1865 if input.peek(Token![else]) {
1866 Some(input.call(else_block)?)
1867 } else {
1868 None
1869 }
1870 },
1871 })
David Tolnay29f9ce12016-10-02 20:58:40 -07001872 }
1873
Michael Layzell734adb42017-06-07 16:58:31 -04001874 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001875 fn expr_if(input: ParseStream) -> Result<ExprIf> {
1876 Ok(ExprIf {
1877 attrs: Vec::new(),
1878 if_token: input.parse()?,
1879 cond: Box::new(input.call(expr_no_struct)?),
1880 then_branch: input.parse()?,
1881 else_branch: {
1882 if input.peek(Token![else]) {
1883 Some(input.call(else_block)?)
1884 } else {
1885 None
1886 }
1887 },
1888 })
Alex Crichton954046c2017-05-30 21:49:42 -07001889 }
David Tolnaybb6feae2016-10-02 21:25:20 -07001890
Michael Layzell734adb42017-06-07 16:58:31 -04001891 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001892 fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
1893 let else_token: Token![else] = input.parse()?;
1894
1895 let lookahead = input.lookahead1();
1896 let else_branch = if input.peek(Token![if]) {
1897 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001898 input.call(expr_if_let).map(Expr::IfLet)?
David Tolnay60291082018-08-28 09:54:49 -07001899 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001900 input.call(expr_if).map(Expr::If)?
David Tolnay60291082018-08-28 09:54:49 -07001901 }
1902 } else if input.peek(token::Brace) {
1903 Expr::Block(ExprBlock {
1904 attrs: Vec::new(),
1905 label: None,
1906 block: input.parse()?,
1907 })
1908 } else {
1909 return Err(lookahead.error());
1910 };
1911
1912 Ok((else_token, Box::new(else_branch)))
1913 }
David Tolnay939766a2016-09-23 23:48:12 -07001914
Michael Layzell734adb42017-06-07 16:58:31 -04001915 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001916 fn expr_for_loop(input: ParseStream) -> Result<ExprForLoop> {
1917 let label: Option<Label> = input.parse()?;
1918 let for_token: Token![for] = input.parse()?;
1919 let pat: Pat = input.parse()?;
1920 let in_token: Token![in] = input.parse()?;
1921 let expr: Expr = input.call(expr_no_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07001922
David Tolnay310b3262018-08-30 15:33:00 -07001923 let content;
1924 let brace_token = braced!(content in input);
1925 let inner_attrs = content.call(Attribute::parse_inner)?;
1926 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07001927
David Tolnay310b3262018-08-30 15:33:00 -07001928 Ok(ExprForLoop {
1929 attrs: inner_attrs,
1930 label: label,
1931 for_token: for_token,
1932 pat: Box::new(pat),
1933 in_token: in_token,
1934 expr: Box::new(expr),
1935 body: Block {
David Tolnay60291082018-08-28 09:54:49 -07001936 brace_token: brace_token,
David Tolnay310b3262018-08-30 15:33:00 -07001937 stmts: stmts,
1938 },
1939 })
Alex Crichton954046c2017-05-30 21:49:42 -07001940 }
David Tolnay1978c672016-10-27 22:05:52 -07001941
Michael Layzell734adb42017-06-07 16:58:31 -04001942 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001943 fn expr_loop(input: ParseStream) -> Result<ExprLoop> {
1944 let label: Option<Label> = input.parse()?;
1945 let loop_token: Token![loop] = input.parse()?;
1946
1947 let content;
1948 let brace_token = braced!(content in input);
1949 let inner_attrs = content.call(Attribute::parse_inner)?;
1950 let stmts = content.call(Block::parse_within)?;
1951
1952 Ok(ExprLoop {
1953 attrs: inner_attrs,
1954 label: label,
1955 loop_token: loop_token,
1956 body: Block {
1957 brace_token: brace_token,
1958 stmts: stmts,
1959 },
1960 })
Alex Crichton954046c2017-05-30 21:49:42 -07001961 }
Arnavion02ef13f2017-04-25 00:54:31 -07001962
Michael Layzell734adb42017-06-07 16:58:31 -04001963 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001964 fn expr_match(input: ParseStream) -> Result<ExprMatch> {
1965 let match_token: Token![match] = input.parse()?;
1966 let expr = expr_no_struct(input)?;
1967
1968 let content;
1969 let brace_token = braced!(content in input);
1970 let inner_attrs = content.call(Attribute::parse_inner)?;
1971
1972 let mut arms = Vec::new();
1973 while !content.is_empty() {
1974 arms.push(content.call(match_arm)?);
1975 }
1976
1977 Ok(ExprMatch {
1978 attrs: inner_attrs,
1979 match_token: match_token,
1980 expr: Box::new(expr),
1981 brace_token: brace_token,
1982 arms: arms,
1983 })
1984 }
1985
1986 #[cfg(feature = "full")]
1987 fn expr_try_block(input: ParseStream) -> Result<ExprTryBlock> {
1988 Ok(ExprTryBlock {
1989 attrs: Vec::new(),
1990 try_token: input.parse()?,
1991 block: input.parse()?,
1992 })
1993 }
1994
1995 #[cfg(feature = "full")]
1996 fn expr_yield(input: ParseStream) -> Result<ExprYield> {
1997 Ok(ExprYield {
1998 attrs: Vec::new(),
1999 yield_token: input.parse()?,
2000 expr: {
2001 if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
2002 Some(input.parse()?)
2003 } else {
2004 None
2005 }
2006 },
2007 })
2008 }
2009
2010 #[cfg(feature = "full")]
2011 fn match_arm(input: ParseStream) -> Result<Arm> {
2012 let requires_comma;
2013 Ok(Arm {
2014 attrs: input.call(Attribute::parse_outer)?,
2015 leading_vert: input.parse()?,
2016 pats: {
2017 let mut pats = Punctuated::new();
2018 let value: Pat = input.parse()?;
2019 pats.push_value(value);
2020 loop {
2021 if !input.peek(Token![|]) {
2022 break;
David Tolnay60291082018-08-28 09:54:49 -07002023 }
David Tolnay310b3262018-08-30 15:33:00 -07002024 let punct = input.parse()?;
2025 pats.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002026 let value: Pat = input.parse()?;
2027 pats.push_value(value);
David Tolnay310b3262018-08-30 15:33:00 -07002028 }
2029 pats
2030 },
2031 guard: {
2032 if input.peek(Token![if]) {
2033 let if_token: Token![if] = input.parse()?;
2034 let guard: Expr = input.parse()?;
2035 Some((if_token, Box::new(guard)))
2036 } else {
2037 None
2038 }
2039 },
2040 fat_arrow_token: input.parse()?,
2041 body: {
2042 let body = input.call(expr_early)?;
David Tolnaye532d6b2018-08-30 16:55:01 -07002043 requires_comma = requires_terminator(&body);
David Tolnay310b3262018-08-30 15:33:00 -07002044 Box::new(body)
2045 },
2046 comma: {
2047 if requires_comma && !input.is_empty() {
2048 Some(input.parse()?)
2049 } else {
2050 input.parse()?
2051 }
2052 },
2053 })
Alex Crichton954046c2017-05-30 21:49:42 -07002054 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07002055
Michael Layzell734adb42017-06-07 16:58:31 -04002056 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002057 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
David Tolnay60291082018-08-28 09:54:49 -07002058 let asyncness: Option<Token![async]> = input.parse()?;
2059 let movability: Option<Token![static]> = if asyncness.is_none() {
2060 input.parse()?
2061 } else {
2062 None
2063 };
2064 let capture: Option<Token![move]> = input.parse()?;
2065 let or1_token: Token![|] = input.parse()?;
2066
2067 let mut inputs = Punctuated::new();
2068 loop {
2069 if input.peek(Token![|]) {
2070 break;
2071 }
2072 let value = fn_arg(input)?;
2073 inputs.push_value(value);
2074 if input.peek(Token![|]) {
2075 break;
2076 }
2077 let punct: Token![,] = input.parse()?;
2078 inputs.push_punct(punct);
2079 }
2080
2081 let or2_token: Token![|] = input.parse()?;
2082
2083 let (output, body) = if input.peek(Token![->]) {
2084 let arrow_token: Token![->] = input.parse()?;
2085 let ty: Type = input.parse()?;
2086 let body: Block = input.parse()?;
2087 let output = ReturnType::Type(arrow_token, Box::new(ty));
2088 let block = Expr::Block(ExprBlock {
2089 attrs: Vec::new(),
2090 label: None,
2091 block: body,
2092 });
2093 (output, block)
2094 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002095 let body = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002096 (ReturnType::Default, body)
2097 };
2098
2099 Ok(ExprClosure {
David Tolnay310b3262018-08-30 15:33:00 -07002100 attrs: Vec::new(),
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002101 asyncness: asyncness,
2102 movability: movability,
2103 capture: capture,
David Tolnay60291082018-08-28 09:54:49 -07002104 or1_token: or1_token,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002105 inputs: inputs,
David Tolnay60291082018-08-28 09:54:49 -07002106 or2_token: or2_token,
2107 output: output,
2108 body: Box::new(body),
2109 })
David Tolnay02a9c6f2018-08-24 18:58:45 -04002110 }
Yusuke Sasaki851062f2018-08-01 06:28:28 +09002111
2112 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002113 fn expr_async(input: ParseStream) -> Result<ExprAsync> {
2114 Ok(ExprAsync {
2115 attrs: Vec::new(),
2116 async_token: input.parse()?,
2117 capture: input.parse()?,
2118 block: input.parse()?,
2119 })
David Tolnay60291082018-08-28 09:54:49 -07002120 }
Gregory Katz3e562cc2016-09-28 18:33:02 -04002121
Michael Layzell734adb42017-06-07 16:58:31 -04002122 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002123 fn fn_arg(input: ParseStream) -> Result<FnArg> {
2124 let pat: Pat = input.parse()?;
2125
2126 if input.peek(Token![:]) {
2127 Ok(FnArg::Captured(ArgCaptured {
2128 pat: pat,
2129 colon_token: input.parse()?,
2130 ty: input.parse()?,
2131 }))
2132 } else {
2133 Ok(FnArg::Inferred(pat))
2134 }
2135 }
2136
2137 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002138 fn expr_while(input: ParseStream) -> Result<ExprWhile> {
2139 let label: Option<Label> = input.parse()?;
2140 let while_token: Token![while] = input.parse()?;
2141 let cond = expr_no_struct(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002142
David Tolnay310b3262018-08-30 15:33:00 -07002143 let content;
2144 let brace_token = braced!(content in input);
2145 let inner_attrs = content.call(Attribute::parse_inner)?;
2146 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002147
David Tolnay310b3262018-08-30 15:33:00 -07002148 Ok(ExprWhile {
2149 attrs: inner_attrs,
2150 label: label,
2151 while_token: while_token,
2152 cond: Box::new(cond),
2153 body: Block {
2154 brace_token: brace_token,
2155 stmts: stmts,
2156 },
2157 })
Alex Crichton954046c2017-05-30 21:49:42 -07002158 }
2159
Michael Layzell734adb42017-06-07 16:58:31 -04002160 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002161 fn expr_while_let(input: ParseStream) -> Result<ExprWhileLet> {
2162 let label: Option<Label> = input.parse()?;
2163 let while_token: Token![while] = input.parse()?;
2164 let let_token: Token![let] = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002165
David Tolnay310b3262018-08-30 15:33:00 -07002166 let mut pats = Punctuated::new();
2167 let value: Pat = input.parse()?;
2168 pats.push_value(value);
2169 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2170 let punct = input.parse()?;
2171 pats.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002172 let value: Pat = input.parse()?;
2173 pats.push_value(value);
David Tolnay60291082018-08-28 09:54:49 -07002174 }
David Tolnay310b3262018-08-30 15:33:00 -07002175
2176 let eq_token: Token![=] = input.parse()?;
2177 let expr = expr_no_struct(input)?;
2178
2179 let content;
2180 let brace_token = braced!(content in input);
2181 let inner_attrs = content.call(Attribute::parse_inner)?;
2182 let stmts = content.call(Block::parse_within)?;
2183
2184 Ok(ExprWhileLet {
2185 attrs: inner_attrs,
2186 label: label,
2187 while_token: while_token,
2188 let_token: let_token,
2189 pats: pats,
2190 eq_token: eq_token,
2191 expr: Box::new(expr),
2192 body: Block {
2193 brace_token: brace_token,
2194 stmts: stmts,
2195 },
2196 })
David Tolnaybcd498f2017-12-29 12:02:33 -05002197 }
2198
2199 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002200 impl Parse for Label {
2201 fn parse(input: ParseStream) -> Result<Self> {
2202 Ok(Label {
2203 name: input.parse()?,
2204 colon_token: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04002205 })
David Tolnay60291082018-08-28 09:54:49 -07002206 }
Alex Crichton954046c2017-05-30 21:49:42 -07002207 }
2208
Michael Layzell734adb42017-06-07 16:58:31 -04002209 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002210 impl Parse for Option<Label> {
2211 fn parse(input: ParseStream) -> Result<Self> {
2212 if input.peek(Lifetime) {
2213 input.parse().map(Some)
2214 } else {
2215 Ok(None)
2216 }
2217 }
2218 }
2219
2220 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002221 fn expr_continue(input: ParseStream) -> Result<ExprContinue> {
2222 Ok(ExprContinue {
2223 attrs: Vec::new(),
2224 continue_token: input.parse()?,
2225 label: input.parse()?,
2226 })
Alex Crichton954046c2017-05-30 21:49:42 -07002227 }
Gregory Katzfd6935d2016-09-30 22:51:25 -04002228
Michael Layzell734adb42017-06-07 16:58:31 -04002229 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002230 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2231 Ok(ExprBreak {
David Tolnay310b3262018-08-30 15:33:00 -07002232 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002233 break_token: input.parse()?,
2234 label: input.parse()?,
2235 expr: {
2236 if input.is_empty()
2237 || input.peek(Token![,])
2238 || input.peek(Token![;])
2239 || !allow_struct.0 && input.peek(token::Brace)
2240 {
2241 None
2242 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002243 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002244 Some(Box::new(expr))
Michael Layzell92639a52017-06-01 00:07:44 -04002245 }
David Tolnay60291082018-08-28 09:54:49 -07002246 },
2247 })
Alex Crichton954046c2017-05-30 21:49:42 -07002248 }
2249
Michael Layzell734adb42017-06-07 16:58:31 -04002250 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002251 fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
2252 Ok(ExprReturn {
David Tolnay310b3262018-08-30 15:33:00 -07002253 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002254 return_token: input.parse()?,
2255 expr: {
2256 if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
2257 None
2258 } else {
2259 // NOTE: return is greedy and eats blocks after it even when in a
2260 // position where structs are not allowed, such as in if statement
2261 // conditions. For example:
2262 //
2263 // if return { println!("A") } {} // Prints "A"
David Tolnay7d2e1db2018-08-30 11:49:04 -07002264 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002265 Some(Box::new(expr))
2266 }
2267 },
2268 })
2269 }
2270
2271 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07002272 fn expr_struct_helper(
2273 input: ParseStream,
2274 outer_attrs: Vec<Attribute>,
2275 path: Path,
2276 ) -> Result<ExprStruct> {
David Tolnay6e1e5052018-08-30 10:21:48 -07002277 let content;
2278 let brace_token = braced!(content in input);
2279 let inner_attrs = content.call(Attribute::parse_inner)?;
David Tolnay60291082018-08-28 09:54:49 -07002280
David Tolnay6e1e5052018-08-30 10:21:48 -07002281 let mut fields = Punctuated::new();
2282 loop {
2283 let attrs = content.call(Attribute::parse_outer)?;
2284 if content.fork().parse::<Member>().is_err() {
2285 if attrs.is_empty() {
David Tolnay60291082018-08-28 09:54:49 -07002286 break;
David Tolnay6e1e5052018-08-30 10:21:48 -07002287 } else {
2288 return Err(content.error("expected struct field"));
David Tolnay60291082018-08-28 09:54:49 -07002289 }
David Tolnay60291082018-08-28 09:54:49 -07002290 }
2291
David Tolnay6e1e5052018-08-30 10:21:48 -07002292 let member: Member = content.parse()?;
2293 let (colon_token, value) = if content.peek(Token![:]) || !member.is_named() {
2294 let colon_token: Token![:] = content.parse()?;
2295 let value: Expr = content.parse()?;
2296 (Some(colon_token), value)
2297 } else if let Member::Named(ref ident) = member {
2298 let value = Expr::Path(ExprPath {
2299 attrs: Vec::new(),
2300 qself: None,
2301 path: Path::from(ident.clone()),
2302 });
2303 (None, value)
David Tolnay60291082018-08-28 09:54:49 -07002304 } else {
David Tolnay6e1e5052018-08-30 10:21:48 -07002305 unreachable!()
David Tolnay60291082018-08-28 09:54:49 -07002306 };
2307
David Tolnay6e1e5052018-08-30 10:21:48 -07002308 fields.push(FieldValue {
2309 attrs: attrs,
2310 member: member,
2311 colon_token: colon_token,
2312 expr: value,
2313 });
2314
2315 if !content.peek(Token![,]) {
2316 break;
2317 }
2318 let punct: Token![,] = content.parse()?;
2319 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002320 }
David Tolnay6e1e5052018-08-30 10:21:48 -07002321
2322 let (dot2_token, rest) = if fields.empty_or_trailing() && content.peek(Token![..]) {
2323 let dot2_token: Token![..] = content.parse()?;
2324 let rest: Expr = content.parse()?;
2325 (Some(dot2_token), Some(Box::new(rest)))
2326 } else {
2327 (None, None)
2328 };
2329
2330 Ok(ExprStruct {
2331 attrs: {
2332 let mut attrs = outer_attrs;
2333 attrs.extend(inner_attrs);
2334 attrs
2335 },
2336 brace_token: brace_token,
2337 path: path,
2338 fields: fields,
2339 dot2_token: dot2_token,
2340 rest: rest,
2341 })
Alex Crichton954046c2017-05-30 21:49:42 -07002342 }
David Tolnay055a7042016-10-02 19:23:54 -07002343
Michael Layzell734adb42017-06-07 16:58:31 -04002344 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002345 fn expr_unsafe(input: ParseStream) -> Result<ExprUnsafe> {
2346 let unsafe_token: Token![unsafe] = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002347
David Tolnay310b3262018-08-30 15:33:00 -07002348 let content;
2349 let brace_token = braced!(content in input);
2350 let inner_attrs = content.call(Attribute::parse_inner)?;
2351 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002352
David Tolnay310b3262018-08-30 15:33:00 -07002353 Ok(ExprUnsafe {
2354 attrs: inner_attrs,
2355 unsafe_token: unsafe_token,
2356 block: Block {
2357 brace_token: brace_token,
2358 stmts: stmts,
2359 },
2360 })
Alex Crichton954046c2017-05-30 21:49:42 -07002361 }
David Tolnay055a7042016-10-02 19:23:54 -07002362
Michael Layzell734adb42017-06-07 16:58:31 -04002363 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002364 pub fn expr_block(input: ParseStream) -> Result<ExprBlock> {
2365 let label: Option<Label> = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002366
David Tolnay310b3262018-08-30 15:33:00 -07002367 let content;
2368 let brace_token = braced!(content in input);
2369 let inner_attrs = content.call(Attribute::parse_inner)?;
2370 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002371
David Tolnay310b3262018-08-30 15:33:00 -07002372 Ok(ExprBlock {
2373 attrs: inner_attrs,
2374 label: label,
2375 block: Block {
2376 brace_token: brace_token,
2377 stmts: stmts,
2378 },
2379 })
Alex Crichton954046c2017-05-30 21:49:42 -07002380 }
David Tolnay89e05672016-10-02 14:39:42 -07002381
Michael Layzell734adb42017-06-07 16:58:31 -04002382 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002383 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2384 Ok(ExprRange {
David Tolnay8c91b882017-12-28 23:04:32 -05002385 attrs: Vec::new(),
2386 from: None,
David Tolnay60291082018-08-28 09:54:49 -07002387 limits: input.parse()?,
2388 to: {
2389 if input.is_empty()
2390 || input.peek(Token![,])
2391 || input.peek(Token![;])
2392 || !allow_struct.0 && input.peek(token::Brace)
2393 {
2394 None
2395 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002396 let to = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002397 Some(Box::new(to))
2398 }
2399 },
2400 })
2401 }
David Tolnay438c9052016-10-07 23:24:48 -07002402
Michael Layzell734adb42017-06-07 16:58:31 -04002403 #[cfg(feature = "full")]
David Tolnayc4c631e2018-08-27 10:44:37 -07002404 impl Parse for RangeLimits {
2405 fn parse(input: ParseStream) -> Result<Self> {
2406 let lookahead = input.lookahead1();
2407 if lookahead.peek(Token![..=]) {
2408 input.parse().map(RangeLimits::Closed)
2409 } else if lookahead.peek(Token![...]) {
2410 let dot3: Token![...] = input.parse()?;
2411 Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2412 } else if lookahead.peek(Token![..]) {
2413 input.parse().map(RangeLimits::HalfOpen)
2414 } else {
2415 Err(lookahead.error())
2416 }
2417 }
Alex Crichton954046c2017-05-30 21:49:42 -07002418 }
David Tolnay438c9052016-10-07 23:24:48 -07002419
David Tolnay60291082018-08-28 09:54:49 -07002420 impl Parse for ExprPath {
2421 fn parse(input: ParseStream) -> Result<Self> {
2422 #[cfg(not(feature = "full"))]
2423 let attrs = Vec::new();
2424 #[cfg(feature = "full")]
2425 let attrs = input.call(Attribute::parse_outer)?;
David Tolnayeb981bb2018-07-21 19:31:38 -07002426
David Tolnay60291082018-08-28 09:54:49 -07002427 let (qself, path) = path::parsing::qpath(input, true)?;
2428
2429 Ok(ExprPath {
David Tolnay73c9b522018-07-21 15:58:40 -07002430 attrs: attrs,
David Tolnay60291082018-08-28 09:54:49 -07002431 qself: qself,
2432 path: path,
Michael Layzell92639a52017-06-01 00:07:44 -04002433 })
David Tolnay60291082018-08-28 09:54:49 -07002434 }
Alex Crichton954046c2017-05-30 21:49:42 -07002435 }
David Tolnay42602292016-10-01 22:25:45 -07002436
Michael Layzell734adb42017-06-07 16:58:31 -04002437 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002438 impl Parse for Block {
2439 fn parse(input: ParseStream) -> Result<Self> {
2440 let content;
2441 Ok(Block {
2442 brace_token: braced!(content in input),
2443 stmts: content.call(Block::parse_within)?,
Michael Layzell92639a52017-06-01 00:07:44 -04002444 })
David Tolnay60291082018-08-28 09:54:49 -07002445 }
Alex Crichton954046c2017-05-30 21:49:42 -07002446 }
David Tolnay939766a2016-09-23 23:48:12 -07002447
Michael Layzell734adb42017-06-07 16:58:31 -04002448 #[cfg(feature = "full")]
Alex Crichton954046c2017-05-30 21:49:42 -07002449 impl Block {
David Tolnay9389c382018-08-27 09:13:37 -07002450 pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002451 let mut stmts = Vec::new();
David Tolnay7158c5f2018-08-30 17:28:34 -07002452 loop {
2453 while input.peek(Token![;]) {
2454 input.parse::<Token![;]>()?;
Michael Layzell92639a52017-06-01 00:07:44 -04002455 }
David Tolnay7158c5f2018-08-30 17:28:34 -07002456 if input.is_empty() {
2457 break;
2458 }
2459 let s = parse_stmt(input, true)?;
2460 let requires_semicolon = if let Stmt::Expr(ref s) = s {
2461 requires_terminator(s)
2462 } else {
2463 false
2464 };
David Tolnaye532d6b2018-08-30 16:55:01 -07002465 stmts.push(s);
David Tolnay7158c5f2018-08-30 17:28:34 -07002466 if input.is_empty() {
2467 break;
2468 } else if requires_semicolon {
2469 return Err(input.error("unexpected token"));
2470 }
David Tolnaye532d6b2018-08-30 16:55:01 -07002471 }
2472 Ok(stmts)
2473 }
Alex Crichton954046c2017-05-30 21:49:42 -07002474 }
2475
Michael Layzell734adb42017-06-07 16:58:31 -04002476 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002477 impl Parse for Stmt {
2478 fn parse(input: ParseStream) -> Result<Self> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002479 parse_stmt(input, false)
2480 }
2481 }
David Tolnay939766a2016-09-23 23:48:12 -07002482
David Tolnaye532d6b2018-08-30 16:55:01 -07002483 #[cfg(feature = "full")]
2484 fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
2485 let ahead = input.fork();
2486 ahead.call(Attribute::parse_outer)?;
2487
David Tolnaye532d6b2018-08-30 16:55:01 -07002488 if {
2489 let ahead = ahead.fork();
2490 // Only parse braces here; paren and bracket will get parsed as
2491 // expression statements
2492 ahead.call(Path::parse_mod_style).is_ok()
2493 && ahead.parse::<Token![!]>().is_ok()
2494 && (ahead.peek(token::Brace) || ahead.peek(Ident))
2495 } {
2496 stmt_mac(input)
2497 } else if ahead.peek(Token![let]) {
2498 stmt_local(input).map(Stmt::Local)
2499 } else if ahead.peek(Token![pub])
2500 || ahead.peek(Token![crate]) && !ahead.peek2(Token![::])
2501 || ahead.peek(Token![extern]) && !ahead.peek2(Token![::])
2502 || ahead.peek(Token![use])
2503 || ahead.peek(Token![static]) && (ahead.peek2(Token![mut]) || ahead.peek2(Ident))
2504 || ahead.peek(Token![const])
2505 || ahead.peek(Token![unsafe]) && !ahead.peek2(token::Brace)
2506 || ahead.peek(Token![async]) && (ahead.peek2(Token![extern]) || ahead.peek2(Token![fn]))
2507 || ahead.peek(Token![fn])
2508 || ahead.peek(Token![mod])
2509 || ahead.peek(Token![type])
2510 || ahead.peek(Token![existential]) && ahead.peek2(Token![type])
2511 || ahead.peek(Token![struct])
2512 || ahead.peek(Token![enum])
2513 || ahead.peek(Token![union]) && ahead.peek2(Ident)
2514 || ahead.peek(Token![auto]) && ahead.peek2(Token![trait])
2515 || ahead.peek(Token![trait])
David Tolnay73b7ca12018-08-30 21:05:13 -07002516 || ahead.peek(Token![default])
2517 && (ahead.peek2(Token![unsafe]) || ahead.peek2(Token![impl ]))
2518 || ahead.peek(Token![impl ])
David Tolnaye532d6b2018-08-30 16:55:01 -07002519 || ahead.peek(Token![macro])
2520 {
2521 input.parse().map(Stmt::Item)
2522 } else {
2523 stmt_expr(input, allow_nosemi)
David Tolnay60291082018-08-28 09:54:49 -07002524 }
Alex Crichton954046c2017-05-30 21:49:42 -07002525 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07002526
Michael Layzell734adb42017-06-07 16:58:31 -04002527 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002528 fn stmt_mac(input: ParseStream) -> Result<Stmt> {
2529 let attrs = input.call(Attribute::parse_outer)?;
2530 let path = input.call(Path::parse_mod_style)?;
2531 let bang_token: Token![!] = input.parse()?;
2532 let ident: Option<Ident> = input.parse()?;
2533 let (delimiter, tts) = mac::parse_delimiter(input)?;
2534 let semi_token: Option<Token![;]> = input.parse()?;
2535
2536 Ok(Stmt::Item(Item::Macro(ItemMacro {
2537 attrs: attrs,
2538 ident: ident,
2539 mac: Macro {
2540 path: path,
2541 bang_token: bang_token,
2542 delimiter: delimiter,
2543 tts: tts,
2544 },
2545 semi_token: semi_token,
2546 })))
Alex Crichton954046c2017-05-30 21:49:42 -07002547 }
David Tolnay84aa0752016-10-02 23:01:13 -07002548
Michael Layzell734adb42017-06-07 16:58:31 -04002549 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002550 fn stmt_local(input: ParseStream) -> Result<Local> {
2551 Ok(Local {
2552 attrs: input.call(Attribute::parse_outer)?,
2553 let_token: input.parse()?,
2554 pats: {
2555 let mut pats = Punctuated::new();
2556 let value: Pat = input.parse()?;
2557 pats.push_value(value);
2558 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2559 let punct = input.parse()?;
2560 pats.push_punct(punct);
2561 let value: Pat = input.parse()?;
2562 pats.push_value(value);
2563 }
2564 pats
2565 },
2566 ty: {
2567 if input.peek(Token![:]) {
2568 let colon_token: Token![:] = input.parse()?;
2569 let ty: Type = input.parse()?;
2570 Some((colon_token, Box::new(ty)))
2571 } else {
2572 None
2573 }
2574 },
2575 init: {
2576 if input.peek(Token![=]) {
2577 let eq_token: Token![=] = input.parse()?;
2578 let init: Expr = input.parse()?;
2579 Some((eq_token, Box::new(init)))
2580 } else {
2581 None
2582 }
2583 },
2584 semi_token: input.parse()?,
2585 })
2586 }
2587
2588 #[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -07002589 fn stmt_expr(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
David Tolnay60291082018-08-28 09:54:49 -07002590 let mut attrs = input.call(Attribute::parse_outer)?;
David Tolnay01218d12018-08-29 18:13:07 -07002591 let mut e = expr_early(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002592
2593 attrs.extend(e.replace_attrs(Vec::new()));
2594 e.replace_attrs(attrs);
2595
2596 if input.peek(Token![;]) {
David Tolnay01218d12018-08-29 18:13:07 -07002597 return Ok(Stmt::Semi(e, input.parse()?));
David Tolnay60291082018-08-28 09:54:49 -07002598 }
David Tolnay60291082018-08-28 09:54:49 -07002599
David Tolnayf00a2762018-08-30 17:22:22 -07002600 if allow_nosemi || !requires_terminator(&e) {
David Tolnaye532d6b2018-08-30 16:55:01 -07002601 Ok(Stmt::Expr(e))
2602 } else {
2603 Err(input.error("expected semicolon"))
David Tolnay01218d12018-08-29 18:13:07 -07002604 }
David Tolnay60291082018-08-28 09:54:49 -07002605 }
2606
2607 #[cfg(feature = "full")]
2608 impl Parse for Pat {
2609 fn parse(input: ParseStream) -> Result<Self> {
2610 // TODO: better error messages
2611 let lookahead = input.lookahead1();
2612 if lookahead.peek(Token![_]) {
David Tolnay310b3262018-08-30 15:33:00 -07002613 input.call(pat_wild).map(Pat::Wild)
David Tolnay60291082018-08-28 09:54:49 -07002614 } else if lookahead.peek(Token![box]) {
David Tolnay310b3262018-08-30 15:33:00 -07002615 input.call(pat_box).map(Pat::Box)
2616 } else if input.fork().call(pat_range).is_ok() {
David Tolnay60291082018-08-28 09:54:49 -07002617 // must be before Pat::Lit
David Tolnay310b3262018-08-30 15:33:00 -07002618 input.call(pat_range).map(Pat::Range)
2619 } else if input.fork().call(pat_tuple_struct).is_ok() {
David Tolnay60291082018-08-28 09:54:49 -07002620 // must be before Pat::Ident
David Tolnay310b3262018-08-30 15:33:00 -07002621 input.call(pat_tuple_struct).map(Pat::TupleStruct)
2622 } else if input.fork().call(pat_struct).is_ok() {
David Tolnay60291082018-08-28 09:54:49 -07002623 // must be before Pat::Ident
David Tolnay310b3262018-08-30 15:33:00 -07002624 input.call(pat_struct).map(Pat::Struct)
2625 } else if input.fork().call(pat_macro).is_ok() {
David Tolnay60291082018-08-28 09:54:49 -07002626 // must be before Pat::Ident
David Tolnay310b3262018-08-30 15:33:00 -07002627 input.call(pat_macro).map(Pat::Macro)
2628 } else if input.fork().call(pat_lit).is_ok() {
David Tolnay60291082018-08-28 09:54:49 -07002629 // must be before Pat::Ident
David Tolnay310b3262018-08-30 15:33:00 -07002630 input.call(pat_lit).map(Pat::Lit)
2631 } else if input.fork().call(pat_ident).is_ok() {
2632 input.call(pat_ident).map(Pat::Ident)
2633 } else if input.fork().call(pat_path).is_ok() {
2634 input.call(pat_path).map(Pat::Path)
David Tolnay60291082018-08-28 09:54:49 -07002635 } else if lookahead.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07002636 input.call(pat_tuple).map(Pat::Tuple)
David Tolnay60291082018-08-28 09:54:49 -07002637 } else if lookahead.peek(Token![&]) {
David Tolnay310b3262018-08-30 15:33:00 -07002638 input.call(pat_ref).map(Pat::Ref)
David Tolnay60291082018-08-28 09:54:49 -07002639 } else if lookahead.peek(token::Bracket) {
David Tolnay310b3262018-08-30 15:33:00 -07002640 input.call(pat_slice).map(Pat::Slice)
David Tolnay60291082018-08-28 09:54:49 -07002641 } else {
2642 Err(lookahead.error())
2643 }
2644 }
2645 }
2646
2647 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002648 fn pat_wild(input: ParseStream) -> Result<PatWild> {
2649 Ok(PatWild {
2650 underscore_token: input.parse()?,
2651 })
Alex Crichton954046c2017-05-30 21:49:42 -07002652 }
2653
Michael Layzell734adb42017-06-07 16:58:31 -04002654 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002655 fn pat_box(input: ParseStream) -> Result<PatBox> {
2656 Ok(PatBox {
2657 box_token: input.parse()?,
2658 pat: input.parse()?,
2659 })
David Tolnay60291082018-08-28 09:54:49 -07002660 }
2661
2662 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002663 fn pat_ident(input: ParseStream) -> Result<PatIdent> {
2664 Ok(PatIdent {
2665 by_ref: input.parse()?,
2666 mutability: input.parse()?,
2667 ident: {
2668 let ident = if input.peek(Ident) || input.peek(Token![self]) {
David Tolnay0dea1b92018-08-30 17:47:29 -07002669 input.call(Ident::parse_any)?
David Tolnay310b3262018-08-30 15:33:00 -07002670 } else {
2671 return Err(input.error("expected identifier or `self`"));
2672 };
2673 if input.peek(Token![<]) || input.peek(Token![::]) {
2674 return Err(input.error("unexpected token"));
David Tolnay60291082018-08-28 09:54:49 -07002675 }
David Tolnay310b3262018-08-30 15:33:00 -07002676 ident
2677 },
2678 subpat: {
2679 if input.peek(Token![@]) {
2680 let at_token: Token![@] = input.parse()?;
2681 let subpat: Pat = input.parse()?;
2682 Some((at_token, Box::new(subpat)))
2683 } else {
2684 None
2685 }
2686 },
2687 })
David Tolnay60291082018-08-28 09:54:49 -07002688 }
2689
2690 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002691 fn pat_tuple_struct(input: ParseStream) -> Result<PatTupleStruct> {
2692 Ok(PatTupleStruct {
2693 path: input.parse()?,
2694 pat: input.call(pat_tuple)?,
2695 })
2696 }
David Tolnay60291082018-08-28 09:54:49 -07002697
David Tolnay310b3262018-08-30 15:33:00 -07002698 #[cfg(feature = "full")]
2699 fn pat_struct(input: ParseStream) -> Result<PatStruct> {
2700 let path: Path = input.parse()?;
2701
2702 let content;
2703 let brace_token = braced!(content in input);
2704
2705 let mut fields = Punctuated::new();
2706 while !content.is_empty() && !content.peek(Token![..]) {
2707 let value = content.call(field_pat)?;
2708 fields.push_value(value);
2709 if !content.peek(Token![,]) {
2710 break;
David Tolnay60291082018-08-28 09:54:49 -07002711 }
David Tolnay310b3262018-08-30 15:33:00 -07002712 let punct: Token![,] = content.parse()?;
2713 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002714 }
David Tolnay310b3262018-08-30 15:33:00 -07002715
2716 let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) {
2717 Some(content.parse()?)
2718 } else {
2719 None
2720 };
2721
2722 Ok(PatStruct {
2723 path: path,
2724 brace_token: brace_token,
2725 fields: fields,
2726 dot2_token: dot2_token,
2727 })
2728 }
2729
2730 #[cfg(feature = "full")]
2731 fn field_pat(input: ParseStream) -> Result<FieldPat> {
2732 let boxed: Option<Token![box]> = input.parse()?;
2733 let by_ref: Option<Token![ref]> = input.parse()?;
2734 let mutability: Option<Token![mut]> = input.parse()?;
2735 let member: Member = input.parse()?;
2736
2737 if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
2738 || member.is_unnamed()
2739 {
2740 return Ok(FieldPat {
2741 attrs: Vec::new(),
2742 member: member,
2743 colon_token: input.parse()?,
2744 pat: input.parse()?,
2745 });
2746 }
2747
2748 let ident = match member {
2749 Member::Named(ident) => ident,
2750 Member::Unnamed(_) => unreachable!(),
2751 };
2752
2753 let mut pat = Pat::Ident(PatIdent {
2754 by_ref: by_ref,
2755 mutability: mutability,
2756 ident: ident.clone(),
2757 subpat: None,
2758 });
2759
2760 if let Some(boxed) = boxed {
2761 pat = Pat::Box(PatBox {
2762 pat: Box::new(pat),
2763 box_token: boxed,
2764 });
2765 }
2766
2767 Ok(FieldPat {
2768 member: Member::Named(ident),
2769 pat: Box::new(pat),
2770 attrs: Vec::new(),
2771 colon_token: None,
2772 })
Alex Crichton954046c2017-05-30 21:49:42 -07002773 }
2774
David Tolnay1501f7e2018-08-27 14:21:03 -07002775 impl Parse for Member {
2776 fn parse(input: ParseStream) -> Result<Self> {
2777 if input.peek(Ident) {
2778 input.parse().map(Member::Named)
2779 } else if input.peek(LitInt) {
2780 input.parse().map(Member::Unnamed)
2781 } else {
2782 Err(input.error("expected identifier or integer"))
2783 }
2784 }
David Tolnay85b69a42017-12-27 20:43:10 -05002785 }
2786
David Tolnay1501f7e2018-08-27 14:21:03 -07002787 impl Parse for Index {
2788 fn parse(input: ParseStream) -> Result<Self> {
2789 let lit: LitInt = input.parse()?;
2790 if let IntSuffix::None = lit.suffix() {
2791 Ok(Index {
2792 index: lit.value() as u32,
2793 span: lit.span(),
2794 })
2795 } else {
2796 Err(input.error("expected unsuffixed integer"))
2797 }
2798 }
David Tolnay85b69a42017-12-27 20:43:10 -05002799 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07002800
Michael Layzell734adb42017-06-07 16:58:31 -04002801 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002802 fn pat_path(input: ParseStream) -> Result<PatPath> {
2803 let p: ExprPath = input.parse()?;
2804 Ok(PatPath {
2805 qself: p.qself,
2806 path: p.path,
2807 })
Alex Crichton954046c2017-05-30 21:49:42 -07002808 }
David Tolnay9636c052016-10-02 17:11:17 -07002809
Michael Layzell734adb42017-06-07 16:58:31 -04002810 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002811 fn pat_tuple(input: ParseStream) -> Result<PatTuple> {
2812 let content;
2813 let paren_token = parenthesized!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002814
David Tolnay310b3262018-08-30 15:33:00 -07002815 let mut front = Punctuated::new();
2816 let mut dot2_token = None::<Token![..]>;
2817 let mut comma_token = None::<Token![,]>;
2818 loop {
2819 if content.is_empty() {
2820 break;
David Tolnay60291082018-08-28 09:54:49 -07002821 }
David Tolnay310b3262018-08-30 15:33:00 -07002822 if content.peek(Token![..]) {
2823 dot2_token = Some(content.parse()?);
2824 comma_token = content.parse()?;
2825 break;
David Tolnay60291082018-08-28 09:54:49 -07002826 }
David Tolnay310b3262018-08-30 15:33:00 -07002827 let value: Pat = content.parse()?;
2828 front.push_value(value);
2829 if content.is_empty() {
2830 break;
2831 }
2832 let punct = content.parse()?;
2833 front.push_punct(punct);
2834 }
2835
David Tolnayf5ebc192018-08-30 18:23:46 -07002836 let mut back = Punctuated::new();
2837 while !content.is_empty() {
2838 let value: Pat = content.parse()?;
2839 back.push_value(value);
2840 if content.is_empty() {
2841 break;
2842 }
2843 let punct = content.parse()?;
2844 back.push_punct(punct);
2845 }
David Tolnay310b3262018-08-30 15:33:00 -07002846
2847 Ok(PatTuple {
2848 paren_token: paren_token,
2849 front: front,
2850 dot2_token: dot2_token,
2851 comma_token: comma_token,
2852 back: back,
2853 })
2854 }
2855
2856 #[cfg(feature = "full")]
2857 fn pat_ref(input: ParseStream) -> Result<PatRef> {
2858 Ok(PatRef {
2859 and_token: input.parse()?,
2860 mutability: input.parse()?,
2861 pat: input.parse()?,
2862 })
2863 }
2864
2865 #[cfg(feature = "full")]
2866 fn pat_lit(input: ParseStream) -> Result<PatLit> {
2867 if input.peek(Lit) || input.peek(Token![-]) && input.peek2(Lit) {
2868 Ok(PatLit {
2869 expr: input.call(pat_lit_expr)?,
2870 })
2871 } else {
2872 Err(input.error("expected literal pattern"))
David Tolnay60291082018-08-28 09:54:49 -07002873 }
2874 }
2875
2876 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002877 fn pat_range(input: ParseStream) -> Result<PatRange> {
2878 Ok(PatRange {
2879 lo: input.call(pat_lit_expr)?,
2880 limits: input.parse()?,
2881 hi: input.call(pat_lit_expr)?,
2882 })
David Tolnay60291082018-08-28 09:54:49 -07002883 }
2884
2885 #[cfg(feature = "full")]
2886 fn pat_lit_expr(input: ParseStream) -> Result<Box<Expr>> {
2887 let neg: Option<Token![-]> = input.parse()?;
2888
2889 let lookahead = input.lookahead1();
2890 let expr = if lookahead.peek(Lit) {
David Tolnay310b3262018-08-30 15:33:00 -07002891 Expr::Lit(input.call(expr_lit)?)
David Tolnay60291082018-08-28 09:54:49 -07002892 } else if lookahead.peek(Ident)
2893 || lookahead.peek(Token![::])
2894 || lookahead.peek(Token![<])
2895 || lookahead.peek(Token![self])
2896 || lookahead.peek(Token![Self])
2897 || lookahead.peek(Token![super])
2898 || lookahead.peek(Token![extern])
2899 || lookahead.peek(Token![crate])
2900 {
2901 Expr::Path(input.parse()?)
2902 } else {
2903 return Err(lookahead.error());
2904 };
2905
2906 Ok(Box::new(if let Some(neg) = neg {
David Tolnay8c91b882017-12-28 23:04:32 -05002907 Expr::Unary(ExprUnary {
2908 attrs: Vec::new(),
David Tolnayc29b9892017-12-27 22:58:14 -05002909 op: UnOp::Neg(neg),
David Tolnay60291082018-08-28 09:54:49 -07002910 expr: Box::new(expr),
David Tolnay3bc597f2017-12-31 02:31:11 -05002911 })
David Tolnay0ad9e9f2016-10-29 22:20:02 -07002912 } else {
David Tolnay60291082018-08-28 09:54:49 -07002913 expr
2914 }))
Alex Crichton954046c2017-05-30 21:49:42 -07002915 }
David Tolnay323279a2017-12-29 11:26:32 -05002916
2917 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002918 fn pat_slice(input: ParseStream) -> Result<PatSlice> {
2919 let content;
2920 let bracket_token = bracketed!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002921
David Tolnay310b3262018-08-30 15:33:00 -07002922 let mut front = Punctuated::new();
2923 let mut middle = None;
2924 loop {
2925 if content.is_empty() || content.peek(Token![..]) {
2926 break;
David Tolnay60291082018-08-28 09:54:49 -07002927 }
David Tolnay310b3262018-08-30 15:33:00 -07002928 let value: Pat = content.parse()?;
2929 if content.peek(Token![..]) {
2930 middle = Some(Box::new(value));
2931 break;
David Tolnay60291082018-08-28 09:54:49 -07002932 }
David Tolnay310b3262018-08-30 15:33:00 -07002933 front.push_value(value);
2934 if content.is_empty() {
2935 break;
2936 }
2937 let punct = content.parse()?;
2938 front.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002939 }
David Tolnay310b3262018-08-30 15:33:00 -07002940
2941 let dot2_token: Option<Token![..]> = content.parse()?;
2942 let mut comma_token = None::<Token![,]>;
2943 let mut back = Punctuated::new();
2944 if dot2_token.is_some() {
2945 comma_token = content.parse()?;
2946 if comma_token.is_some() {
2947 loop {
2948 if content.is_empty() {
2949 break;
2950 }
2951 let value: Pat = content.parse()?;
2952 back.push_value(value);
2953 if content.is_empty() {
2954 break;
2955 }
2956 let punct = content.parse()?;
2957 back.push_punct(punct);
2958 }
2959 }
2960 }
2961
2962 Ok(PatSlice {
2963 bracket_token: bracket_token,
2964 front: front,
2965 middle: middle,
2966 dot2_token: dot2_token,
2967 comma_token: comma_token,
2968 back: back,
2969 })
David Tolnay60291082018-08-28 09:54:49 -07002970 }
2971
2972 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002973 fn pat_macro(input: ParseStream) -> Result<PatMacro> {
2974 Ok(PatMacro {
2975 mac: input.parse()?,
2976 })
David Tolnay323279a2017-12-29 11:26:32 -05002977 }
David Tolnay1501f7e2018-08-27 14:21:03 -07002978
2979 #[cfg(feature = "full")]
2980 impl Member {
2981 fn is_named(&self) -> bool {
2982 match *self {
2983 Member::Named(_) => true,
2984 Member::Unnamed(_) => false,
2985 }
2986 }
David Tolnay60291082018-08-28 09:54:49 -07002987
2988 fn is_unnamed(&self) -> bool {
2989 match *self {
2990 Member::Named(_) => false,
2991 Member::Unnamed(_) => true,
2992 }
2993 }
David Tolnay1501f7e2018-08-27 14:21:03 -07002994 }
David Tolnayb9c8e322016-09-23 20:48:37 -07002995}
2996
David Tolnayf4bbbd92016-09-23 14:41:55 -07002997#[cfg(feature = "printing")]
2998mod printing {
2999 use super::*;
Michael Layzell734adb42017-06-07 16:58:31 -04003000 #[cfg(feature = "full")]
David Tolnay13b3d352016-10-03 00:31:15 -07003001 use attr::FilterAttrs;
Alex Crichtona74a1c82018-05-16 10:20:44 -07003002 use proc_macro2::{Literal, TokenStream};
3003 use quote::{ToTokens, TokenStreamExt};
David Tolnayf4bbbd92016-09-23 14:41:55 -07003004
David Tolnaybcf26022017-12-25 22:10:52 -05003005 // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
David Tolnayb6a0e7d2018-05-20 22:06:47 -07003006 // before appending it to `TokenStream`.
Michael Layzell3936ceb2017-07-08 00:28:36 -04003007 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003008 fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) {
David Tolnay8c91b882017-12-28 23:04:32 -05003009 if let Expr::Struct(_) = *e {
David Tolnay32954ef2017-12-26 22:43:16 -05003010 token::Paren::default().surround(tokens, |tokens| {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003011 e.to_tokens(tokens);
3012 });
3013 } else {
3014 e.to_tokens(tokens);
3015 }
3016 }
3017
David Tolnay8c91b882017-12-28 23:04:32 -05003018 #[cfg(feature = "full")]
David Tolnayd997aef2018-07-21 18:42:31 -07003019 fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
David Tolnay8c91b882017-12-28 23:04:32 -05003020 tokens.append_all(attrs.outer());
3021 }
Michael Layzell734adb42017-06-07 16:58:31 -04003022
David Tolnayd997aef2018-07-21 18:42:31 -07003023 #[cfg(feature = "full")]
3024 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3025 tokens.append_all(attrs.inner());
3026 }
3027
David Tolnay8c91b882017-12-28 23:04:32 -05003028 #[cfg(not(feature = "full"))]
David Tolnayd997aef2018-07-21 18:42:31 -07003029 fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3030
3031 #[cfg(not(feature = "full"))]
3032 fn inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
Alex Crichton62a0a592017-05-22 13:58:53 -07003033
Michael Layzell734adb42017-06-07 16:58:31 -04003034 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003035 impl ToTokens for ExprBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003036 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003037 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003038 self.box_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003039 self.expr.to_tokens(tokens);
3040 }
3041 }
3042
Michael Layzell734adb42017-06-07 16:58:31 -04003043 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003044 impl ToTokens for ExprInPlace {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003045 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003046 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8701a5c2017-12-28 23:31:10 -05003047 self.place.to_tokens(tokens);
3048 self.arrow_token.to_tokens(tokens);
3049 self.value.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003050 }
3051 }
3052
Michael Layzell734adb42017-06-07 16:58:31 -04003053 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003054 impl ToTokens for ExprArray {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003055 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003056 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003057 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003058 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003059 self.elems.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003060 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003061 }
3062 }
3063
3064 impl ToTokens for ExprCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003065 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003066 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003067 self.func.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003068 self.paren_token.surround(tokens, |tokens| {
3069 self.args.to_tokens(tokens);
3070 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003071 }
3072 }
3073
Michael Layzell734adb42017-06-07 16:58:31 -04003074 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003075 impl ToTokens for ExprMethodCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003076 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003077 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay76418512017-12-28 23:47:47 -05003078 self.receiver.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003079 self.dot_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003080 self.method.to_tokens(tokens);
David Tolnayd60cfec2017-12-29 00:21:38 -05003081 self.turbofish.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003082 self.paren_token.surround(tokens, |tokens| {
3083 self.args.to_tokens(tokens);
3084 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003085 }
3086 }
3087
Michael Layzell734adb42017-06-07 16:58:31 -04003088 #[cfg(feature = "full")]
David Tolnayd60cfec2017-12-29 00:21:38 -05003089 impl ToTokens for MethodTurbofish {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003090 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003091 self.colon2_token.to_tokens(tokens);
3092 self.lt_token.to_tokens(tokens);
3093 self.args.to_tokens(tokens);
3094 self.gt_token.to_tokens(tokens);
3095 }
3096 }
3097
3098 #[cfg(feature = "full")]
3099 impl ToTokens for GenericMethodArgument {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003100 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003101 match *self {
3102 GenericMethodArgument::Type(ref t) => t.to_tokens(tokens),
3103 GenericMethodArgument::Const(ref c) => c.to_tokens(tokens),
3104 }
3105 }
3106 }
3107
3108 #[cfg(feature = "full")]
David Tolnay05362582017-12-26 01:33:57 -05003109 impl ToTokens for ExprTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003110 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003111 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003112 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003113 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003114 self.elems.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003115 // If we only have one argument, we need a trailing comma to
David Tolnay05362582017-12-26 01:33:57 -05003116 // distinguish ExprTuple from ExprParen.
David Tolnaya0834b42018-01-01 21:30:02 -08003117 if self.elems.len() == 1 && !self.elems.trailing_punct() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003118 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003119 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003120 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003121 }
3122 }
3123
3124 impl ToTokens for ExprBinary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003125 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003126 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003127 self.left.to_tokens(tokens);
3128 self.op.to_tokens(tokens);
3129 self.right.to_tokens(tokens);
3130 }
3131 }
3132
3133 impl ToTokens for ExprUnary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003134 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003135 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003136 self.op.to_tokens(tokens);
3137 self.expr.to_tokens(tokens);
3138 }
3139 }
3140
David Tolnay8c91b882017-12-28 23:04:32 -05003141 impl ToTokens for ExprLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003142 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003143 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003144 self.lit.to_tokens(tokens);
3145 }
3146 }
3147
Alex Crichton62a0a592017-05-22 13:58:53 -07003148 impl ToTokens for ExprCast {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003149 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003150 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003151 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003152 self.as_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003153 self.ty.to_tokens(tokens);
3154 }
3155 }
3156
David Tolnay0cf94f22017-12-28 23:46:26 -05003157 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003158 impl ToTokens for ExprType {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003159 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003160 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003161 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003162 self.colon_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003163 self.ty.to_tokens(tokens);
3164 }
3165 }
3166
Michael Layzell734adb42017-06-07 16:58:31 -04003167 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003168 fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>) {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003169 if let Some((ref else_token, ref else_)) = *else_ {
3170 else_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003171
3172 // If we are not one of the valid expressions to exist in an else
3173 // clause, wrap ourselves in a block.
David Tolnay2ccf32a2017-12-29 00:34:26 -05003174 match **else_ {
David Tolnay8c91b882017-12-28 23:04:32 -05003175 Expr::If(_) | Expr::IfLet(_) | Expr::Block(_) => {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003176 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003177 }
3178 _ => {
David Tolnay32954ef2017-12-26 22:43:16 -05003179 token::Brace::default().surround(tokens, |tokens| {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003180 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003181 });
3182 }
3183 }
3184 }
3185 }
3186
3187 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003188 impl ToTokens for ExprIf {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003189 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003190 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003191 self.if_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003192 wrap_bare_struct(tokens, &self.cond);
David Tolnay2ccf32a2017-12-29 00:34:26 -05003193 self.then_branch.to_tokens(tokens);
3194 maybe_wrap_else(tokens, &self.else_branch);
Alex Crichton62a0a592017-05-22 13:58:53 -07003195 }
3196 }
3197
Michael Layzell734adb42017-06-07 16:58:31 -04003198 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003199 impl ToTokens for ExprIfLet {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003200 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003201 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003202 self.if_token.to_tokens(tokens);
3203 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003204 self.pats.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003205 self.eq_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003206 wrap_bare_struct(tokens, &self.expr);
David Tolnay2ccf32a2017-12-29 00:34:26 -05003207 self.then_branch.to_tokens(tokens);
3208 maybe_wrap_else(tokens, &self.else_branch);
Alex Crichton62a0a592017-05-22 13:58:53 -07003209 }
3210 }
3211
Michael Layzell734adb42017-06-07 16:58:31 -04003212 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003213 impl ToTokens for ExprWhile {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003214 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003215 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003216 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003217 self.while_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003218 wrap_bare_struct(tokens, &self.cond);
David Tolnay5d314dc2018-07-21 16:40:01 -07003219 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003220 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003221 tokens.append_all(&self.body.stmts);
3222 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003223 }
3224 }
3225
Michael Layzell734adb42017-06-07 16:58:31 -04003226 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003227 impl ToTokens for ExprWhileLet {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003228 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003229 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003230 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003231 self.while_token.to_tokens(tokens);
3232 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003233 self.pats.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003234 self.eq_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003235 wrap_bare_struct(tokens, &self.expr);
David Tolnay5d314dc2018-07-21 16:40:01 -07003236 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003237 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003238 tokens.append_all(&self.body.stmts);
3239 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003240 }
3241 }
3242
Michael Layzell734adb42017-06-07 16:58:31 -04003243 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003244 impl ToTokens for ExprForLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003245 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003246 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003247 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003248 self.for_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003249 self.pat.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003250 self.in_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003251 wrap_bare_struct(tokens, &self.expr);
David Tolnay5d314dc2018-07-21 16:40:01 -07003252 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003253 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003254 tokens.append_all(&self.body.stmts);
3255 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003256 }
3257 }
3258
Michael Layzell734adb42017-06-07 16:58:31 -04003259 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003260 impl ToTokens for ExprLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003261 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003262 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003263 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003264 self.loop_token.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003265 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003266 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003267 tokens.append_all(&self.body.stmts);
3268 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003269 }
3270 }
3271
Michael Layzell734adb42017-06-07 16:58:31 -04003272 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003273 impl ToTokens for ExprMatch {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003274 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003275 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003276 self.match_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003277 wrap_bare_struct(tokens, &self.expr);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003278 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003279 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay51382052017-12-27 13:46:21 -05003280 for (i, arm) in self.arms.iter().enumerate() {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003281 arm.to_tokens(tokens);
3282 // Ensure that we have a comma after a non-block arm, except
3283 // for the last one.
3284 let is_last = i == self.arms.len() - 1;
David Tolnaye532d6b2018-08-30 16:55:01 -07003285 if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003286 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003287 }
3288 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003289 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003290 }
3291 }
3292
Michael Layzell734adb42017-06-07 16:58:31 -04003293 #[cfg(feature = "full")]
David Tolnay02a9c6f2018-08-24 18:58:45 -04003294 impl ToTokens for ExprAsync {
3295 fn to_tokens(&self, tokens: &mut TokenStream) {
3296 outer_attrs_to_tokens(&self.attrs, tokens);
3297 self.async_token.to_tokens(tokens);
3298 self.capture.to_tokens(tokens);
3299 self.block.to_tokens(tokens);
3300 }
3301 }
3302
3303 #[cfg(feature = "full")]
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003304 impl ToTokens for ExprTryBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003305 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003306 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003307 self.try_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003308 self.block.to_tokens(tokens);
3309 }
3310 }
3311
Michael Layzell734adb42017-06-07 16:58:31 -04003312 #[cfg(feature = "full")]
Alex Crichtonfe110462017-06-01 12:49:27 -07003313 impl ToTokens for ExprYield {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003314 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003315 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonfe110462017-06-01 12:49:27 -07003316 self.yield_token.to_tokens(tokens);
3317 self.expr.to_tokens(tokens);
3318 }
3319 }
3320
3321 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003322 impl ToTokens for ExprClosure {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003323 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003324 outer_attrs_to_tokens(&self.attrs, tokens);
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09003325 self.asyncness.to_tokens(tokens);
David Tolnay13d4c0e2018-03-31 20:53:59 +02003326 self.movability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003327 self.capture.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003328 self.or1_token.to_tokens(tokens);
David Tolnay56080682018-01-06 14:01:52 -08003329 for input in self.inputs.pairs() {
3330 match **input.value() {
David Tolnay51382052017-12-27 13:46:21 -05003331 FnArg::Captured(ArgCaptured {
3332 ref pat,
3333 ty: Type::Infer(_),
3334 ..
3335 }) => {
Alex Crichton62a0a592017-05-22 13:58:53 -07003336 pat.to_tokens(tokens);
David Tolnay9636c052016-10-02 17:11:17 -07003337 }
David Tolnay56080682018-01-06 14:01:52 -08003338 _ => input.value().to_tokens(tokens),
David Tolnay3c2467c2016-10-02 17:55:08 -07003339 }
David Tolnayf2cfd722017-12-31 18:02:51 -05003340 input.punct().to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003341 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003342 self.or2_token.to_tokens(tokens);
David Tolnay7f675742017-12-27 22:43:21 -05003343 self.output.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003344 self.body.to_tokens(tokens);
3345 }
3346 }
3347
Michael Layzell734adb42017-06-07 16:58:31 -04003348 #[cfg(feature = "full")]
Nika Layzell640832a2017-12-04 13:37:09 -05003349 impl ToTokens for ExprUnsafe {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003350 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003351 outer_attrs_to_tokens(&self.attrs, tokens);
Nika Layzell640832a2017-12-04 13:37:09 -05003352 self.unsafe_token.to_tokens(tokens);
David Tolnayc4be3512018-08-27 06:25:44 -07003353 self.block.brace_token.surround(tokens, |tokens| {
3354 inner_attrs_to_tokens(&self.attrs, tokens);
3355 tokens.append_all(&self.block.stmts);
3356 });
Nika Layzell640832a2017-12-04 13:37:09 -05003357 }
3358 }
3359
3360 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003361 impl ToTokens for ExprBlock {
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 Tolnay1d8e9962018-08-24 19:04:20 -04003364 self.label.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003365 self.block.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003366 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003367 tokens.append_all(&self.block.stmts);
3368 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003369 }
3370 }
3371
Michael Layzell734adb42017-06-07 16:58:31 -04003372 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003373 impl ToTokens for ExprAssign {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003374 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003375 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003376 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003377 self.eq_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003378 self.right.to_tokens(tokens);
3379 }
3380 }
3381
Michael Layzell734adb42017-06-07 16:58:31 -04003382 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003383 impl ToTokens for ExprAssignOp {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003384 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003385 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003386 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003387 self.op.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003388 self.right.to_tokens(tokens);
3389 }
3390 }
3391
3392 impl ToTokens for ExprField {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003393 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003394 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003395 self.base.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003396 self.dot_token.to_tokens(tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003397 self.member.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003398 }
3399 }
3400
David Tolnay85b69a42017-12-27 20:43:10 -05003401 impl ToTokens for Member {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003402 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay85b69a42017-12-27 20:43:10 -05003403 match *self {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003404 Member::Named(ref ident) => ident.to_tokens(tokens),
David Tolnay85b69a42017-12-27 20:43:10 -05003405 Member::Unnamed(ref index) => index.to_tokens(tokens),
3406 }
3407 }
3408 }
3409
David Tolnay85b69a42017-12-27 20:43:10 -05003410 impl ToTokens for Index {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003411 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichton9a4dca22018-03-28 06:32:19 -07003412 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
3413 lit.set_span(self.span);
3414 tokens.append(lit);
Alex Crichton62a0a592017-05-22 13:58:53 -07003415 }
3416 }
3417
3418 impl ToTokens for ExprIndex {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003419 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003420 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003421 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003422 self.bracket_token.surround(tokens, |tokens| {
3423 self.index.to_tokens(tokens);
3424 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003425 }
3426 }
3427
Michael Layzell734adb42017-06-07 16:58:31 -04003428 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003429 impl ToTokens for ExprRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003430 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003431 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003432 self.from.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003433 match self.limits {
3434 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
3435 RangeLimits::Closed(ref t) => t.to_tokens(tokens),
3436 }
Alex Crichton62a0a592017-05-22 13:58:53 -07003437 self.to.to_tokens(tokens);
3438 }
3439 }
3440
3441 impl ToTokens for ExprPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003442 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003443 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003444 ::PathTokens(&self.qself, &self.path).to_tokens(tokens)
Alex Crichton62a0a592017-05-22 13:58:53 -07003445 }
3446 }
3447
Michael Layzell734adb42017-06-07 16:58:31 -04003448 #[cfg(feature = "full")]
David Tolnay00674ba2018-03-31 18:14:11 +02003449 impl ToTokens for ExprReference {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003450 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003451 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003452 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003453 self.mutability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003454 self.expr.to_tokens(tokens);
3455 }
3456 }
3457
Michael Layzell734adb42017-06-07 16:58:31 -04003458 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003459 impl ToTokens for ExprBreak {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003460 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003461 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003462 self.break_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003463 self.label.to_tokens(tokens);
3464 self.expr.to_tokens(tokens);
3465 }
3466 }
3467
Michael Layzell734adb42017-06-07 16:58:31 -04003468 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003469 impl ToTokens for ExprContinue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003470 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003471 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003472 self.continue_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003473 self.label.to_tokens(tokens);
3474 }
3475 }
3476
Michael Layzell734adb42017-06-07 16:58:31 -04003477 #[cfg(feature = "full")]
David Tolnayc246cd32017-12-28 23:14:32 -05003478 impl ToTokens for ExprReturn {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003479 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003480 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003481 self.return_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003482 self.expr.to_tokens(tokens);
3483 }
3484 }
3485
Michael Layzell734adb42017-06-07 16:58:31 -04003486 #[cfg(feature = "full")]
David Tolnay8c91b882017-12-28 23:04:32 -05003487 impl ToTokens for ExprMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003488 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003489 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003490 self.mac.to_tokens(tokens);
3491 }
3492 }
3493
3494 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003495 impl ToTokens for ExprStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003496 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003497 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003498 self.path.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003499 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003500 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003501 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003502 if self.rest.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -07003503 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003504 self.rest.to_tokens(tokens);
3505 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003506 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003507 }
3508 }
3509
Michael Layzell734adb42017-06-07 16:58:31 -04003510 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003511 impl ToTokens for ExprRepeat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003512 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003513 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003514 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003515 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003516 self.expr.to_tokens(tokens);
3517 self.semi_token.to_tokens(tokens);
David Tolnay84d80442018-01-07 01:03:20 -08003518 self.len.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003519 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003520 }
3521 }
3522
David Tolnaye98775f2017-12-28 23:17:00 -05003523 #[cfg(feature = "full")]
Michael Layzell93c36282017-06-04 20:43:14 -04003524 impl ToTokens for ExprGroup {
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);
Michael Layzell93c36282017-06-04 20:43:14 -04003527 self.group_token.surround(tokens, |tokens| {
3528 self.expr.to_tokens(tokens);
3529 });
3530 }
3531 }
3532
Alex Crichton62a0a592017-05-22 13:58:53 -07003533 impl ToTokens for ExprParen {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003534 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003535 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003536 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003537 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003538 self.expr.to_tokens(tokens);
3539 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003540 }
3541 }
3542
Michael Layzell734adb42017-06-07 16:58:31 -04003543 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003544 impl ToTokens for ExprTry {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003545 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003546 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003547 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003548 self.question_token.to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003549 }
3550 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07003551
David Tolnay2ae520a2017-12-29 11:19:50 -05003552 impl ToTokens for ExprVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003553 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003554 self.tts.to_tokens(tokens);
3555 }
3556 }
3557
Michael Layzell734adb42017-06-07 16:58:31 -04003558 #[cfg(feature = "full")]
David Tolnaybcd498f2017-12-29 12:02:33 -05003559 impl ToTokens for Label {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003560 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaybcd498f2017-12-29 12:02:33 -05003561 self.name.to_tokens(tokens);
3562 self.colon_token.to_tokens(tokens);
3563 }
3564 }
3565
3566 #[cfg(feature = "full")]
David Tolnay055a7042016-10-02 19:23:54 -07003567 impl ToTokens for FieldValue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003568 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003569 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003570 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003571 if let Some(ref colon_token) = self.colon_token {
3572 colon_token.to_tokens(tokens);
David Tolnay276690f2016-10-30 12:06:59 -07003573 self.expr.to_tokens(tokens);
3574 }
David Tolnay055a7042016-10-02 19:23:54 -07003575 }
3576 }
3577
Michael Layzell734adb42017-06-07 16:58:31 -04003578 #[cfg(feature = "full")]
David Tolnayb4ad3b52016-10-01 21:58:13 -07003579 impl ToTokens for Arm {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003580 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003581 tokens.append_all(&self.attrs);
David Tolnay18cc4d42018-03-31 18:47:20 +02003582 self.leading_vert.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003583 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003584 if let Some((ref if_token, ref guard)) = self.guard {
3585 if_token.to_tokens(tokens);
3586 guard.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003587 }
David Tolnaydfb91432018-03-31 19:19:44 +02003588 self.fat_arrow_token.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003589 self.body.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003590 self.comma.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003591 }
3592 }
3593
Michael Layzell734adb42017-06-07 16:58:31 -04003594 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003595 impl ToTokens for PatWild {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003596 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003597 self.underscore_token.to_tokens(tokens);
3598 }
3599 }
3600
Michael Layzell734adb42017-06-07 16:58:31 -04003601 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003602 impl ToTokens for PatIdent {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003603 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay24237fb2017-12-29 02:15:26 -05003604 self.by_ref.to_tokens(tokens);
David Tolnayefc96fb2017-12-29 02:03:15 -05003605 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003606 self.ident.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003607 if let Some((ref at_token, ref subpat)) = self.subpat {
3608 at_token.to_tokens(tokens);
3609 subpat.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003610 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003611 }
3612 }
3613
Michael Layzell734adb42017-06-07 16:58:31 -04003614 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003615 impl ToTokens for PatStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003616 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003617 self.path.to_tokens(tokens);
3618 self.brace_token.surround(tokens, |tokens| {
3619 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003620 // NOTE: We need a comma before the dot2 token if it is present.
3621 if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003622 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003623 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003624 self.dot2_token.to_tokens(tokens);
3625 });
3626 }
3627 }
3628
Michael Layzell734adb42017-06-07 16:58:31 -04003629 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003630 impl ToTokens for PatTupleStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003631 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003632 self.path.to_tokens(tokens);
3633 self.pat.to_tokens(tokens);
3634 }
3635 }
3636
Michael Layzell734adb42017-06-07 16:58:31 -04003637 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003638 impl ToTokens for PatPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003639 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003640 ::PathTokens(&self.qself, &self.path).to_tokens(tokens);
3641 }
3642 }
3643
Michael Layzell734adb42017-06-07 16:58:31 -04003644 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003645 impl ToTokens for PatTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003646 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003647 self.paren_token.surround(tokens, |tokens| {
David Tolnay41871922017-12-29 01:53:45 -05003648 self.front.to_tokens(tokens);
3649 if let Some(ref dot2_token) = self.dot2_token {
3650 if !self.front.empty_or_trailing() {
3651 // Ensure there is a comma before the .. token.
David Tolnayf8db7ba2017-11-11 22:52:16 -08003652 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003653 }
David Tolnay41871922017-12-29 01:53:45 -05003654 dot2_token.to_tokens(tokens);
3655 self.comma_token.to_tokens(tokens);
3656 if self.comma_token.is_none() && !self.back.is_empty() {
3657 // Ensure there is a comma after the .. token.
3658 <Token![,]>::default().to_tokens(tokens);
3659 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07003660 }
David Tolnay41871922017-12-29 01:53:45 -05003661 self.back.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003662 });
3663 }
3664 }
3665
Michael Layzell734adb42017-06-07 16:58:31 -04003666 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003667 impl ToTokens for PatBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003668 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003669 self.box_token.to_tokens(tokens);
3670 self.pat.to_tokens(tokens);
3671 }
3672 }
3673
Michael Layzell734adb42017-06-07 16:58:31 -04003674 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003675 impl ToTokens for PatRef {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003676 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003677 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003678 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003679 self.pat.to_tokens(tokens);
3680 }
3681 }
3682
Michael Layzell734adb42017-06-07 16:58:31 -04003683 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003684 impl ToTokens for PatLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003685 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003686 self.expr.to_tokens(tokens);
3687 }
3688 }
3689
Michael Layzell734adb42017-06-07 16:58:31 -04003690 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003691 impl ToTokens for PatRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003692 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003693 self.lo.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003694 match self.limits {
3695 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
David Tolnay7ac699c2018-08-24 14:00:58 -04003696 RangeLimits::Closed(ref t) => Token![...](t.spans).to_tokens(tokens),
David Tolnay475288a2017-12-19 22:59:44 -08003697 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003698 self.hi.to_tokens(tokens);
3699 }
3700 }
3701
Michael Layzell734adb42017-06-07 16:58:31 -04003702 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003703 impl ToTokens for PatSlice {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003704 fn to_tokens(&self, tokens: &mut TokenStream) {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003705 // XXX: This is a mess, and it will be so easy to screw it up. How
3706 // do we make this correct itself better?
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003707 self.bracket_token.surround(tokens, |tokens| {
3708 self.front.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003709
3710 // If we need a comma before the middle or standalone .. token,
3711 // then make sure it's present.
David Tolnay51382052017-12-27 13:46:21 -05003712 if !self.front.empty_or_trailing()
3713 && (self.middle.is_some() || self.dot2_token.is_some())
Michael Layzell3936ceb2017-07-08 00:28:36 -04003714 {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003715 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003716 }
3717
3718 // If we have an identifier, we always need a .. token.
3719 if self.middle.is_some() {
3720 self.middle.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -07003721 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003722 } else if self.dot2_token.is_some() {
3723 self.dot2_token.to_tokens(tokens);
3724 }
3725
3726 // Make sure we have a comma before the back half.
3727 if !self.back.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07003728 TokensOrDefault(&self.comma_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003729 self.back.to_tokens(tokens);
3730 } else {
3731 self.comma_token.to_tokens(tokens);
3732 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003733 })
David Tolnayb4ad3b52016-10-01 21:58:13 -07003734 }
3735 }
3736
Michael Layzell734adb42017-06-07 16:58:31 -04003737 #[cfg(feature = "full")]
David Tolnay323279a2017-12-29 11:26:32 -05003738 impl ToTokens for PatMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003739 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay323279a2017-12-29 11:26:32 -05003740 self.mac.to_tokens(tokens);
3741 }
3742 }
3743
3744 #[cfg(feature = "full")]
David Tolnay2ae520a2017-12-29 11:19:50 -05003745 impl ToTokens for PatVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003746 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003747 self.tts.to_tokens(tokens);
3748 }
3749 }
3750
3751 #[cfg(feature = "full")]
David Tolnay8d9e81a2016-10-03 22:36:32 -07003752 impl ToTokens for FieldPat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003753 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay5d7098a2017-12-29 01:35:24 -05003754 if let Some(ref colon_token) = self.colon_token {
David Tolnay85b69a42017-12-27 20:43:10 -05003755 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003756 colon_token.to_tokens(tokens);
David Tolnay8d9e81a2016-10-03 22:36:32 -07003757 }
3758 self.pat.to_tokens(tokens);
3759 }
3760 }
3761
Michael Layzell734adb42017-06-07 16:58:31 -04003762 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003763 impl ToTokens for Block {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003764 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003765 self.brace_token.surround(tokens, |tokens| {
3766 tokens.append_all(&self.stmts);
3767 });
David Tolnay42602292016-10-01 22:25:45 -07003768 }
3769 }
3770
Michael Layzell734adb42017-06-07 16:58:31 -04003771 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003772 impl ToTokens for Stmt {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003773 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay42602292016-10-01 22:25:45 -07003774 match *self {
David Tolnay191e0582016-10-02 18:31:09 -07003775 Stmt::Local(ref local) => local.to_tokens(tokens),
David Tolnay42602292016-10-01 22:25:45 -07003776 Stmt::Item(ref item) => item.to_tokens(tokens),
3777 Stmt::Expr(ref expr) => expr.to_tokens(tokens),
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003778 Stmt::Semi(ref expr, ref semi) => {
David Tolnay42602292016-10-01 22:25:45 -07003779 expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003780 semi.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -07003781 }
David Tolnay42602292016-10-01 22:25:45 -07003782 }
3783 }
3784 }
David Tolnay191e0582016-10-02 18:31:09 -07003785
Michael Layzell734adb42017-06-07 16:58:31 -04003786 #[cfg(feature = "full")]
David Tolnay191e0582016-10-02 18:31:09 -07003787 impl ToTokens for Local {
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);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003790 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003791 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003792 if let Some((ref colon_token, ref ty)) = self.ty {
3793 colon_token.to_tokens(tokens);
3794 ty.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003795 }
David Tolnay8b4d3022017-12-29 12:11:10 -05003796 if let Some((ref eq_token, ref init)) = self.init {
3797 eq_token.to_tokens(tokens);
3798 init.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003799 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003800 self.semi_token.to_tokens(tokens);
David Tolnay191e0582016-10-02 18:31:09 -07003801 }
3802 }
David Tolnayf4bbbd92016-09-23 14:41:55 -07003803}