blob: e8fe9f198ceefdf21480b51d4d174ae821d626a6 [file] [log] [blame]
David Tolnay55535012018-01-05 16:39:23 -08001// Copyright 2018 Syn Developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
David Tolnayf4bbbd92016-09-23 14:41:55 -07009use super::*;
David Tolnaye303b7c2018-05-20 16:46:35 -070010use proc_macro2::{Span, TokenStream};
David Tolnay94d2b792018-04-29 12:26:10 -070011use punctuated::Punctuated;
David Tolnay14982012017-12-29 00:49:51 -050012#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -050013use std::hash::{Hash, Hasher};
David Tolnay2ae520a2017-12-29 11:19:50 -050014#[cfg(feature = "full")]
15use std::mem;
David Tolnay94d2b792018-04-29 12:26:10 -070016#[cfg(feature = "extra-traits")]
17use tt::TokenStreamHelper;
David Tolnayf4bbbd92016-09-23 14:41:55 -070018
Alex Crichton62a0a592017-05-22 13:58:53 -070019ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -080020 /// A Rust expression.
David Tolnay614a0142018-01-07 10:25:43 -080021 ///
David Tolnay461d98e2018-01-07 11:07:19 -080022 /// *This type is available if Syn is built with the `"derive"` or `"full"`
23 /// feature.*
24 ///
David Tolnay614a0142018-01-07 10:25:43 -080025 /// # Syntax tree enums
26 ///
27 /// This type is a syntax tree enum. In Syn this and other syntax tree enums
28 /// are designed to be traversed using the following rebinding idiom.
29 ///
30 /// ```
31 /// # use syn::Expr;
32 /// #
33 /// # fn example(expr: Expr) {
34 /// # const IGNORE: &str = stringify! {
35 /// let expr: Expr = /* ... */;
36 /// # };
37 /// match expr {
38 /// Expr::MethodCall(expr) => {
39 /// /* ... */
40 /// }
41 /// Expr::Cast(expr) => {
42 /// /* ... */
43 /// }
44 /// Expr::IfLet(expr) => {
45 /// /* ... */
46 /// }
47 /// /* ... */
48 /// # _ => {}
49 /// }
50 /// # }
51 /// ```
52 ///
53 /// We begin with a variable `expr` of type `Expr` that has no fields
54 /// (because it is an enum), and by matching on it and rebinding a variable
55 /// with the same name `expr` we effectively imbue our variable with all of
56 /// the data fields provided by the variant that it turned out to be. So for
57 /// example above if we ended up in the `MethodCall` case then we get to use
58 /// `expr.receiver`, `expr.args` etc; if we ended up in the `IfLet` case we
59 /// get to use `expr.pat`, `expr.then_branch`, `expr.else_branch`.
60 ///
61 /// The pattern is similar if the input expression is borrowed:
62 ///
63 /// ```
64 /// # use syn::Expr;
65 /// #
66 /// # fn example(expr: &Expr) {
67 /// match *expr {
68 /// Expr::MethodCall(ref expr) => {
69 /// # }
70 /// # _ => {}
71 /// # }
72 /// # }
73 /// ```
74 ///
75 /// This approach avoids repeating the variant names twice on every line.
76 ///
77 /// ```
78 /// # use syn::{Expr, ExprMethodCall};
79 /// #
80 /// # fn example(expr: Expr) {
81 /// # match expr {
82 /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => { // repetitive
83 /// # }
84 /// # _ => {}
85 /// # }
86 /// # }
87 /// ```
88 ///
89 /// In general, the name to which a syntax tree enum variant is bound should
90 /// be a suitable name for the complete syntax tree enum type.
91 ///
92 /// ```
93 /// # use syn::{Expr, ExprField};
94 /// #
95 /// # fn example(discriminant: &ExprField) {
96 /// // Binding is called `base` which is the name I would use if I were
97 /// // assigning `*discriminant.base` without an `if let`.
98 /// if let Expr::Tuple(ref base) = *discriminant.base {
99 /// # }
100 /// # }
101 /// ```
102 ///
103 /// A sign that you may not be choosing the right variable names is if you
104 /// see names getting repeated in your code, like accessing
105 /// `receiver.receiver` or `pat.pat` or `cond.cond`.
David Tolnay8c91b882017-12-28 23:04:32 -0500106 pub enum Expr {
David Tolnaya454c8f2018-01-07 01:01:10 -0800107 /// A box expression: `box f`.
David Tolnay461d98e2018-01-07 11:07:19 -0800108 ///
109 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400110 pub Box(ExprBox #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500111 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800112 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500113 pub expr: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700114 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500115
David Tolnaya454c8f2018-01-07 01:01:10 -0800116 /// A placement expression: `place <- value`.
David Tolnay461d98e2018-01-07 11:07:19 -0800117 ///
118 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400119 pub InPlace(ExprInPlace #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500120 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700121 pub place: Box<Expr>,
David Tolnay8701a5c2017-12-28 23:31:10 -0500122 pub arrow_token: Token![<-],
Alex Crichton62a0a592017-05-22 13:58:53 -0700123 pub value: Box<Expr>,
124 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500125
David Tolnaya454c8f2018-01-07 01:01:10 -0800126 /// A slice literal expression: `[a, b, c, d]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800127 ///
128 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400129 pub Array(ExprArray #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500130 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500131 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500132 pub elems: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700133 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500134
David Tolnaya454c8f2018-01-07 01:01:10 -0800135 /// A function call expression: `invoke(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800136 ///
137 /// *This type is available if Syn is built with the `"derive"` or
138 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700139 pub Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -0500140 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700141 pub func: Box<Expr>,
David Tolnay32954ef2017-12-26 22:43:16 -0500142 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500143 pub args: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700144 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500145
David Tolnaya454c8f2018-01-07 01:01:10 -0800146 /// A method call expression: `x.foo::<T>(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800147 ///
148 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400149 pub MethodCall(ExprMethodCall #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500150 pub attrs: Vec<Attribute>,
David Tolnay76418512017-12-28 23:47:47 -0500151 pub receiver: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800152 pub dot_token: Token![.],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500153 pub method: Ident,
David Tolnayd60cfec2017-12-29 00:21:38 -0500154 pub turbofish: Option<MethodTurbofish>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500155 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500156 pub args: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700157 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500158
David Tolnaya454c8f2018-01-07 01:01:10 -0800159 /// A tuple expression: `(a, b, c, d)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800160 ///
161 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay05362582017-12-26 01:33:57 -0500162 pub Tuple(ExprTuple #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500163 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500164 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500165 pub elems: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700166 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500167
David Tolnaya454c8f2018-01-07 01:01:10 -0800168 /// A binary operation: `a + b`, `a * b`.
David Tolnay461d98e2018-01-07 11:07:19 -0800169 ///
170 /// *This type is available if Syn is built with the `"derive"` or
171 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700172 pub Binary(ExprBinary {
David Tolnay8c91b882017-12-28 23:04:32 -0500173 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700174 pub left: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500175 pub op: BinOp,
Alex Crichton62a0a592017-05-22 13:58:53 -0700176 pub right: Box<Expr>,
177 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500178
David Tolnaya454c8f2018-01-07 01:01:10 -0800179 /// A unary operation: `!x`, `*x`.
David Tolnay461d98e2018-01-07 11:07:19 -0800180 ///
181 /// *This type is available if Syn is built with the `"derive"` or
182 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700183 pub Unary(ExprUnary {
David Tolnay8c91b882017-12-28 23:04:32 -0500184 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700185 pub op: UnOp,
186 pub expr: Box<Expr>,
187 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500188
David Tolnaya454c8f2018-01-07 01:01:10 -0800189 /// A literal in place of an expression: `1`, `"foo"`.
David Tolnay461d98e2018-01-07 11:07:19 -0800190 ///
191 /// *This type is available if Syn is built with the `"derive"` or
192 /// `"full"` feature.*
David Tolnay8c91b882017-12-28 23:04:32 -0500193 pub Lit(ExprLit {
194 pub attrs: Vec<Attribute>,
195 pub lit: Lit,
196 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500197
David Tolnaya454c8f2018-01-07 01:01:10 -0800198 /// A cast expression: `foo as f64`.
David Tolnay461d98e2018-01-07 11:07:19 -0800199 ///
200 /// *This type is available if Syn is built with the `"derive"` or
201 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700202 pub Cast(ExprCast {
David Tolnay8c91b882017-12-28 23:04:32 -0500203 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700204 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800205 pub as_token: Token![as],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800206 pub ty: Box<Type>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700207 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500208
David Tolnaya454c8f2018-01-07 01:01:10 -0800209 /// A type ascription expression: `foo: f64`.
David Tolnay461d98e2018-01-07 11:07:19 -0800210 ///
211 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay0cf94f22017-12-28 23:46:26 -0500212 pub Type(ExprType #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500213 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700214 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800215 pub colon_token: Token![:],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800216 pub ty: Box<Type>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700217 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500218
David Tolnaya454c8f2018-01-07 01:01:10 -0800219 /// An `if` expression with an optional `else` block: `if expr { ... }
220 /// else { ... }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700221 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800222 /// The `else` branch expression may only be an `If`, `IfLet`, or
223 /// `Block` expression, not any of the other types of expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800224 ///
225 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400226 pub If(ExprIf #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500227 pub attrs: Vec<Attribute>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500228 pub if_token: Token![if],
Alex Crichton62a0a592017-05-22 13:58:53 -0700229 pub cond: Box<Expr>,
David Tolnay2ccf32a2017-12-29 00:34:26 -0500230 pub then_branch: Block,
231 pub else_branch: Option<(Token![else], Box<Expr>)>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700232 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500233
David Tolnaya454c8f2018-01-07 01:01:10 -0800234 /// An `if let` expression with an optional `else` block: `if let pat =
235 /// expr { ... } else { ... }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700236 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800237 /// The `else` branch expression may only be an `If`, `IfLet`, or
238 /// `Block` expression, not any of the other types of expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800239 ///
240 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400241 pub IfLet(ExprIfLet #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500242 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800243 pub if_token: Token![if],
244 pub let_token: Token![let],
David Tolnay5b5b7d22018-03-31 21:05:00 +0200245 pub pats: Punctuated<Pat, Token![|]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800246 pub eq_token: Token![=],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500247 pub expr: Box<Expr>,
David Tolnay2ccf32a2017-12-29 00:34:26 -0500248 pub then_branch: Block,
249 pub else_branch: Option<(Token![else], Box<Expr>)>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700250 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500251
David Tolnaya454c8f2018-01-07 01:01:10 -0800252 /// A while loop: `while expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800253 ///
254 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400255 pub While(ExprWhile #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500256 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500257 pub label: Option<Label>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800258 pub while_token: Token![while],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500259 pub cond: Box<Expr>,
260 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700261 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500262
David Tolnaya454c8f2018-01-07 01:01:10 -0800263 /// A while-let loop: `while let pat = expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800264 ///
265 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400266 pub WhileLet(ExprWhileLet #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500267 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500268 pub label: Option<Label>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800269 pub while_token: Token![while],
270 pub let_token: Token![let],
David Tolnay5b5b7d22018-03-31 21:05:00 +0200271 pub pats: Punctuated<Pat, Token![|]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800272 pub eq_token: Token![=],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500273 pub expr: Box<Expr>,
274 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700275 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500276
David Tolnaya454c8f2018-01-07 01:01:10 -0800277 /// A for loop: `for pat in expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800278 ///
279 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400280 pub ForLoop(ExprForLoop #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500281 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500282 pub label: Option<Label>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500283 pub for_token: Token![for],
Alex Crichton62a0a592017-05-22 13:58:53 -0700284 pub pat: Box<Pat>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500285 pub in_token: Token![in],
Alex Crichton62a0a592017-05-22 13:58:53 -0700286 pub expr: Box<Expr>,
287 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700288 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500289
David Tolnaya454c8f2018-01-07 01:01:10 -0800290 /// Conditionless loop: `loop { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800291 ///
292 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400293 pub Loop(ExprLoop #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500294 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500295 pub label: Option<Label>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500296 pub loop_token: Token![loop],
297 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700298 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500299
David Tolnaya454c8f2018-01-07 01:01:10 -0800300 /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800301 ///
302 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400303 pub Match(ExprMatch #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500304 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800305 pub match_token: Token![match],
Alex Crichton62a0a592017-05-22 13:58:53 -0700306 pub expr: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500307 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700308 pub arms: Vec<Arm>,
309 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500310
David Tolnaya454c8f2018-01-07 01:01:10 -0800311 /// A closure expression: `|a, b| a + b`.
David Tolnay461d98e2018-01-07 11:07:19 -0800312 ///
313 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400314 pub Closure(ExprClosure #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500315 pub attrs: Vec<Attribute>,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +0900316 pub asyncness: Option<Token![async]>,
David Tolnay13d4c0e2018-03-31 20:53:59 +0200317 pub movability: Option<Token![static]>,
David Tolnayefc96fb2017-12-29 02:03:15 -0500318 pub capture: Option<Token![move]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800319 pub or1_token: Token![|],
David Tolnayf2cfd722017-12-31 18:02:51 -0500320 pub inputs: Punctuated<FnArg, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800321 pub or2_token: Token![|],
David Tolnay7f675742017-12-27 22:43:21 -0500322 pub output: ReturnType,
323 pub body: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700324 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500325
David Tolnaya454c8f2018-01-07 01:01:10 -0800326 /// An unsafe block: `unsafe { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800327 ///
328 /// *This type is available if Syn is built with the `"full"` feature.*
Nika Layzell640832a2017-12-04 13:37:09 -0500329 pub Unsafe(ExprUnsafe #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500330 pub attrs: Vec<Attribute>,
Nika Layzell640832a2017-12-04 13:37:09 -0500331 pub unsafe_token: Token![unsafe],
332 pub block: Block,
333 }),
334
David Tolnaya454c8f2018-01-07 01:01:10 -0800335 /// A blocked scope: `{ ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800336 ///
337 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400338 pub Block(ExprBlock #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500339 pub attrs: Vec<Attribute>,
David Tolnay1d8e9962018-08-24 19:04:20 -0400340 pub label: Option<Label>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700341 pub block: Block,
342 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700343
David Tolnaya454c8f2018-01-07 01:01:10 -0800344 /// An assignment expression: `a = compute()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800345 ///
346 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400347 pub Assign(ExprAssign #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500348 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700349 pub left: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800350 pub eq_token: Token![=],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500351 pub right: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700352 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500353
David Tolnaya454c8f2018-01-07 01:01:10 -0800354 /// A compound assignment expression: `counter += 1`.
David Tolnay461d98e2018-01-07 11:07:19 -0800355 ///
356 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400357 pub AssignOp(ExprAssignOp #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500358 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700359 pub left: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500360 pub op: BinOp,
Alex Crichton62a0a592017-05-22 13:58:53 -0700361 pub right: Box<Expr>,
362 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500363
David Tolnaya454c8f2018-01-07 01:01:10 -0800364 /// Access of a named struct field (`obj.k`) or unnamed tuple struct
David Tolnay85b69a42017-12-27 20:43:10 -0500365 /// field (`obj.0`).
David Tolnay461d98e2018-01-07 11:07:19 -0800366 ///
367 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd5147742018-06-30 10:09:52 -0700368 pub Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -0500369 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -0500370 pub base: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800371 pub dot_token: Token![.],
David Tolnay85b69a42017-12-27 20:43:10 -0500372 pub member: Member,
Alex Crichton62a0a592017-05-22 13:58:53 -0700373 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500374
David Tolnay05658502018-01-07 09:56:37 -0800375 /// A square bracketed indexing expression: `vector[2]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800376 ///
377 /// *This type is available if Syn is built with the `"derive"` or
378 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700379 pub Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -0500380 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700381 pub expr: Box<Expr>,
David Tolnay32954ef2017-12-26 22:43:16 -0500382 pub bracket_token: token::Bracket,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500383 pub index: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700384 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500385
David Tolnaya454c8f2018-01-07 01:01:10 -0800386 /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800387 ///
388 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400389 pub Range(ExprRange #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500390 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700391 pub from: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700392 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500393 pub to: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700394 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700395
David Tolnaya454c8f2018-01-07 01:01:10 -0800396 /// A path like `std::mem::replace` possibly containing generic
397 /// parameters and a qualified self-type.
Alex Crichton62a0a592017-05-22 13:58:53 -0700398 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800399 /// A plain identifier like `x` is a path of length 1.
David Tolnay461d98e2018-01-07 11:07:19 -0800400 ///
401 /// *This type is available if Syn is built with the `"derive"` or
402 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700403 pub Path(ExprPath {
David Tolnay8c91b882017-12-28 23:04:32 -0500404 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700405 pub qself: Option<QSelf>,
406 pub path: Path,
407 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700408
David Tolnaya454c8f2018-01-07 01:01:10 -0800409 /// A referencing operation: `&a` or `&mut a`.
David Tolnay461d98e2018-01-07 11:07:19 -0800410 ///
411 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay00674ba2018-03-31 18:14:11 +0200412 pub Reference(ExprReference #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500413 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800414 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500415 pub mutability: Option<Token![mut]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700416 pub expr: Box<Expr>,
417 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500418
David Tolnaya454c8f2018-01-07 01:01:10 -0800419 /// A `break`, with an optional label to break and an optional
420 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800421 ///
422 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400423 pub Break(ExprBreak #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500424 pub attrs: Vec<Attribute>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500425 pub break_token: Token![break],
David Tolnay63e3dee2017-06-03 20:13:17 -0700426 pub label: Option<Lifetime>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700427 pub expr: Option<Box<Expr>>,
428 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500429
David Tolnaya454c8f2018-01-07 01:01:10 -0800430 /// A `continue`, with an optional label.
David Tolnay461d98e2018-01-07 11:07:19 -0800431 ///
432 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400433 pub Continue(ExprContinue #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500434 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800435 pub continue_token: Token![continue],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500436 pub label: Option<Lifetime>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700437 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500438
David Tolnaya454c8f2018-01-07 01:01:10 -0800439 /// A `return`, with an optional value to be returned.
David Tolnay461d98e2018-01-07 11:07:19 -0800440 ///
441 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayc246cd32017-12-28 23:14:32 -0500442 pub Return(ExprReturn #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500443 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800444 pub return_token: Token![return],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500445 pub expr: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700446 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700447
David Tolnaya454c8f2018-01-07 01:01:10 -0800448 /// A macro invocation expression: `format!("{}", q)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800449 ///
450 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay8c91b882017-12-28 23:04:32 -0500451 pub Macro(ExprMacro #full {
452 pub attrs: Vec<Attribute>,
453 pub mac: Macro,
454 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700455
David Tolnaya454c8f2018-01-07 01:01:10 -0800456 /// A struct literal expression: `Point { x: 1, y: 1 }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700457 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800458 /// The `rest` provides the value of the remaining fields as in `S { a:
459 /// 1, b: 1, ..rest }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800460 ///
461 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400462 pub Struct(ExprStruct #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500463 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700464 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500465 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500466 pub fields: Punctuated<FieldValue, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500467 pub dot2_token: Option<Token![..]>,
468 pub rest: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700469 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700470
David Tolnaya454c8f2018-01-07 01:01:10 -0800471 /// An array literal constructed from one repeated element: `[0u8; N]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800472 ///
473 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400474 pub Repeat(ExprRepeat #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500475 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500476 pub bracket_token: token::Bracket,
Alex Crichton62a0a592017-05-22 13:58:53 -0700477 pub expr: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500478 pub semi_token: Token![;],
David Tolnay84d80442018-01-07 01:03:20 -0800479 pub len: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700480 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700481
David Tolnaya454c8f2018-01-07 01:01:10 -0800482 /// A parenthesized expression: `(a + b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800483 ///
484 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay9374bc02018-01-27 18:49:36 -0800485 pub Paren(ExprParen {
David Tolnay8c91b882017-12-28 23:04:32 -0500486 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500487 pub paren_token: token::Paren,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500488 pub expr: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700489 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700490
David Tolnaya454c8f2018-01-07 01:01:10 -0800491 /// An expression contained within invisible delimiters.
Michael Layzell93c36282017-06-04 20:43:14 -0400492 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800493 /// This variant is important for faithfully representing the precedence
494 /// of expressions and is related to `None`-delimited spans in a
495 /// `TokenStream`.
David Tolnay461d98e2018-01-07 11:07:19 -0800496 ///
497 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaye98775f2017-12-28 23:17:00 -0500498 pub Group(ExprGroup #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500499 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500500 pub group_token: token::Group,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500501 pub expr: Box<Expr>,
Michael Layzell93c36282017-06-04 20:43:14 -0400502 }),
503
David Tolnaya454c8f2018-01-07 01:01:10 -0800504 /// A try-expression: `expr?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800505 ///
506 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400507 pub Try(ExprTry #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500508 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700509 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800510 pub question_token: Token![?],
Alex Crichton62a0a592017-05-22 13:58:53 -0700511 }),
Arnavion02ef13f2017-04-25 00:54:31 -0700512
David Tolnay02a9c6f2018-08-24 18:58:45 -0400513 /// An async block: `async { ... }`.
514 ///
515 /// *This type is available if Syn is built with the `"full"` feature.*
516 pub Async(ExprAsync #full {
517 pub attrs: Vec<Attribute>,
518 pub async_token: Token![async],
519 pub capture: Option<Token![move]>,
520 pub block: Block,
521 }),
522
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400523 /// A try block: `try { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800524 ///
525 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400526 pub TryBlock(ExprTryBlock #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500527 pub attrs: Vec<Attribute>,
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400528 pub try_token: Token![try],
Alex Crichton62a0a592017-05-22 13:58:53 -0700529 pub block: Block,
530 }),
Alex Crichtonfe110462017-06-01 12:49:27 -0700531
David Tolnaya454c8f2018-01-07 01:01:10 -0800532 /// A yield expression: `yield expr`.
David Tolnay461d98e2018-01-07 11:07:19 -0800533 ///
534 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonfe110462017-06-01 12:49:27 -0700535 pub Yield(ExprYield #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500536 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800537 pub yield_token: Token![yield],
Alex Crichtonfe110462017-06-01 12:49:27 -0700538 pub expr: Option<Box<Expr>>,
539 }),
David Tolnay2ae520a2017-12-29 11:19:50 -0500540
David Tolnaya454c8f2018-01-07 01:01:10 -0800541 /// Tokens in expression position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800542 ///
543 /// *This type is available if Syn is built with the `"derive"` or
544 /// `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500545 pub Verbatim(ExprVerbatim #manual_extra_traits {
546 pub tts: TokenStream,
547 }),
548 }
549}
550
551#[cfg(feature = "extra-traits")]
552impl Eq for ExprVerbatim {}
553
554#[cfg(feature = "extra-traits")]
555impl PartialEq for ExprVerbatim {
556 fn eq(&self, other: &Self) -> bool {
557 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
558 }
559}
560
561#[cfg(feature = "extra-traits")]
562impl Hash for ExprVerbatim {
563 fn hash<H>(&self, state: &mut H)
564 where
565 H: Hasher,
566 {
567 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700568 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700569}
570
David Tolnay8c91b882017-12-28 23:04:32 -0500571impl Expr {
572 // Not public API.
573 #[doc(hidden)]
David Tolnay096d4982017-12-28 23:18:18 -0500574 #[cfg(feature = "full")]
David Tolnay2ae520a2017-12-29 11:19:50 -0500575 pub fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
David Tolnay8c91b882017-12-28 23:04:32 -0500576 match *self {
David Tolnay61037c62018-01-05 16:21:03 -0800577 Expr::Box(ExprBox { ref mut attrs, .. })
578 | Expr::InPlace(ExprInPlace { ref mut attrs, .. })
579 | Expr::Array(ExprArray { ref mut attrs, .. })
580 | Expr::Call(ExprCall { ref mut attrs, .. })
581 | Expr::MethodCall(ExprMethodCall { ref mut attrs, .. })
582 | Expr::Tuple(ExprTuple { ref mut attrs, .. })
583 | Expr::Binary(ExprBinary { ref mut attrs, .. })
584 | Expr::Unary(ExprUnary { ref mut attrs, .. })
585 | Expr::Lit(ExprLit { ref mut attrs, .. })
586 | Expr::Cast(ExprCast { ref mut attrs, .. })
587 | Expr::Type(ExprType { ref mut attrs, .. })
588 | Expr::If(ExprIf { ref mut attrs, .. })
589 | Expr::IfLet(ExprIfLet { ref mut attrs, .. })
590 | Expr::While(ExprWhile { ref mut attrs, .. })
591 | Expr::WhileLet(ExprWhileLet { ref mut attrs, .. })
592 | Expr::ForLoop(ExprForLoop { ref mut attrs, .. })
593 | Expr::Loop(ExprLoop { ref mut attrs, .. })
594 | Expr::Match(ExprMatch { ref mut attrs, .. })
595 | Expr::Closure(ExprClosure { ref mut attrs, .. })
596 | Expr::Unsafe(ExprUnsafe { ref mut attrs, .. })
597 | Expr::Block(ExprBlock { ref mut attrs, .. })
598 | Expr::Assign(ExprAssign { ref mut attrs, .. })
599 | Expr::AssignOp(ExprAssignOp { ref mut attrs, .. })
600 | Expr::Field(ExprField { ref mut attrs, .. })
601 | Expr::Index(ExprIndex { ref mut attrs, .. })
602 | Expr::Range(ExprRange { ref mut attrs, .. })
603 | Expr::Path(ExprPath { ref mut attrs, .. })
David Tolnay00674ba2018-03-31 18:14:11 +0200604 | Expr::Reference(ExprReference { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800605 | Expr::Break(ExprBreak { ref mut attrs, .. })
606 | Expr::Continue(ExprContinue { ref mut attrs, .. })
607 | Expr::Return(ExprReturn { ref mut attrs, .. })
608 | Expr::Macro(ExprMacro { ref mut attrs, .. })
609 | Expr::Struct(ExprStruct { ref mut attrs, .. })
610 | Expr::Repeat(ExprRepeat { ref mut attrs, .. })
611 | Expr::Paren(ExprParen { ref mut attrs, .. })
612 | Expr::Group(ExprGroup { ref mut attrs, .. })
613 | Expr::Try(ExprTry { ref mut attrs, .. })
David Tolnay02a9c6f2018-08-24 18:58:45 -0400614 | Expr::Async(ExprAsync { ref mut attrs, .. })
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400615 | Expr::TryBlock(ExprTryBlock { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800616 | Expr::Yield(ExprYield { ref mut attrs, .. }) => mem::replace(attrs, new),
David Tolnay2ae520a2017-12-29 11:19:50 -0500617 Expr::Verbatim(_) => {
618 // TODO
619 Vec::new()
620 }
David Tolnay8c91b882017-12-28 23:04:32 -0500621 }
622 }
623}
624
David Tolnay85b69a42017-12-27 20:43:10 -0500625ast_enum! {
626 /// A struct or tuple struct field accessed in a struct literal or field
627 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800628 ///
629 /// *This type is available if Syn is built with the `"derive"` or `"full"`
630 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500631 pub enum Member {
632 /// A named field like `self.x`.
633 Named(Ident),
634 /// An unnamed field like `self.0`.
635 Unnamed(Index),
636 }
637}
638
David Tolnay85b69a42017-12-27 20:43:10 -0500639ast_struct! {
640 /// The index of an unnamed tuple struct field.
David Tolnay461d98e2018-01-07 11:07:19 -0800641 ///
642 /// *This type is available if Syn is built with the `"derive"` or `"full"`
643 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500644 pub struct Index #manual_extra_traits {
645 pub index: u32,
646 pub span: Span,
647 }
648}
649
David Tolnay14982012017-12-29 00:49:51 -0500650impl From<usize> for Index {
651 fn from(index: usize) -> Index {
David Tolnay34071ba2018-05-20 20:00:41 -0700652 assert!(index < u32::max_value() as usize);
David Tolnay14982012017-12-29 00:49:51 -0500653 Index {
654 index: index as u32,
Alex Crichton9a4dca22018-03-28 06:32:19 -0700655 span: Span::call_site(),
David Tolnay14982012017-12-29 00:49:51 -0500656 }
657 }
658}
659
660#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500661impl Eq for Index {}
662
David Tolnay14982012017-12-29 00:49:51 -0500663#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500664impl PartialEq for Index {
665 fn eq(&self, other: &Self) -> bool {
666 self.index == other.index
667 }
668}
669
David Tolnay14982012017-12-29 00:49:51 -0500670#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500671impl Hash for Index {
672 fn hash<H: Hasher>(&self, state: &mut H) {
673 self.index.hash(state);
674 }
675}
676
677#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700678ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800679 /// The `::<>` explicit type parameters passed to a method call:
680 /// `parse::<u64>()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800681 ///
682 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500683 pub struct MethodTurbofish {
684 pub colon2_token: Token![::],
685 pub lt_token: Token![<],
David Tolnayf2cfd722017-12-31 18:02:51 -0500686 pub args: Punctuated<GenericMethodArgument, Token![,]>,
David Tolnayd60cfec2017-12-29 00:21:38 -0500687 pub gt_token: Token![>],
688 }
689}
690
691#[cfg(feature = "full")]
692ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800693 /// An individual generic argument to a method, like `T`.
David Tolnay461d98e2018-01-07 11:07:19 -0800694 ///
695 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500696 pub enum GenericMethodArgument {
David Tolnaya454c8f2018-01-07 01:01:10 -0800697 /// A type argument.
David Tolnayd60cfec2017-12-29 00:21:38 -0500698 Type(Type),
David Tolnaya454c8f2018-01-07 01:01:10 -0800699 /// A const expression. Must be inside of a block.
David Tolnayd60cfec2017-12-29 00:21:38 -0500700 ///
701 /// NOTE: Identity expressions are represented as Type arguments, as
702 /// they are indistinguishable syntactically.
703 Const(Expr),
704 }
705}
706
707#[cfg(feature = "full")]
708ast_struct! {
Alex Crichton62a0a592017-05-22 13:58:53 -0700709 /// A field-value pair in a struct literal.
David Tolnay461d98e2018-01-07 11:07:19 -0800710 ///
711 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700712 pub struct FieldValue {
David Tolnay85b69a42017-12-27 20:43:10 -0500713 /// Attributes tagged on the field.
714 pub attrs: Vec<Attribute>,
715
716 /// Name or index of the field.
717 pub member: Member,
718
David Tolnay5d7098a2017-12-29 01:35:24 -0500719 /// The colon in `Struct { x: x }`. If written in shorthand like
720 /// `Struct { x }`, there is no colon.
David Tolnay85b69a42017-12-27 20:43:10 -0500721 pub colon_token: Option<Token![:]>,
Clar Charrd22b5702017-03-10 15:24:56 -0500722
Alex Crichton62a0a592017-05-22 13:58:53 -0700723 /// Value of the field.
724 pub expr: Expr,
Alex Crichton62a0a592017-05-22 13:58:53 -0700725 }
David Tolnay055a7042016-10-02 19:23:54 -0700726}
727
Michael Layzell734adb42017-06-07 16:58:31 -0400728#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700729ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800730 /// A lifetime labeling a `for`, `while`, or `loop`.
David Tolnay461d98e2018-01-07 11:07:19 -0800731 ///
732 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaybcd498f2017-12-29 12:02:33 -0500733 pub struct Label {
734 pub name: Lifetime,
735 pub colon_token: Token![:],
736 }
737}
738
739#[cfg(feature = "full")]
740ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800741 /// A braced block containing Rust statements.
David Tolnay461d98e2018-01-07 11:07:19 -0800742 ///
743 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700744 pub struct Block {
David Tolnay32954ef2017-12-26 22:43:16 -0500745 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700746 /// Statements in a block
747 pub stmts: Vec<Stmt>,
748 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700749}
750
Michael Layzell734adb42017-06-07 16:58:31 -0400751#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700752ast_enum! {
753 /// A statement, usually ending in a semicolon.
David Tolnay461d98e2018-01-07 11:07:19 -0800754 ///
755 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700756 pub enum Stmt {
757 /// A local (let) binding.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800758 Local(Local),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700759
Alex Crichton62a0a592017-05-22 13:58:53 -0700760 /// An item definition.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800761 Item(Item),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700762
Alex Crichton62a0a592017-05-22 13:58:53 -0700763 /// Expr without trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800764 Expr(Expr),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700765
David Tolnaya454c8f2018-01-07 01:01:10 -0800766 /// Expression with trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800767 Semi(Expr, Token![;]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700768 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700769}
770
Michael Layzell734adb42017-06-07 16:58:31 -0400771#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700772ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800773 /// A local `let` binding: `let x: u64 = s.parse()?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800774 ///
775 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700776 pub struct Local {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500777 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800778 pub let_token: Token![let],
David Tolnay5b5b7d22018-03-31 21:05:00 +0200779 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500780 pub ty: Option<(Token![:], Box<Type>)>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500781 pub init: Option<(Token![=], Box<Expr>)>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500782 pub semi_token: Token![;],
Alex Crichton62a0a592017-05-22 13:58:53 -0700783 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700784}
785
Michael Layzell734adb42017-06-07 16:58:31 -0400786#[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700787ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800788 /// A pattern in a local binding, function signature, match expression, or
789 /// various other places.
David Tolnay614a0142018-01-07 10:25:43 -0800790 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800791 /// *This type is available if Syn is built with the `"full"` feature.*
792 ///
David Tolnay614a0142018-01-07 10:25:43 -0800793 /// # Syntax tree enum
794 ///
795 /// This type is a [syntax tree enum].
796 ///
797 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
Alex Crichton62a0a592017-05-22 13:58:53 -0700798 // Clippy false positive
799 // https://github.com/Manishearth/rust-clippy/issues/1241
800 #[cfg_attr(feature = "cargo-clippy", allow(enum_variant_names))]
801 pub enum Pat {
David Tolnaya454c8f2018-01-07 01:01:10 -0800802 /// A pattern that matches any value: `_`.
David Tolnay461d98e2018-01-07 11:07:19 -0800803 ///
804 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700805 pub Wild(PatWild {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800806 pub underscore_token: Token![_],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700807 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700808
David Tolnaya454c8f2018-01-07 01:01:10 -0800809 /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
David Tolnay461d98e2018-01-07 11:07:19 -0800810 ///
811 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700812 pub Ident(PatIdent {
David Tolnay24237fb2017-12-29 02:15:26 -0500813 pub by_ref: Option<Token![ref]>,
814 pub mutability: Option<Token![mut]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700815 pub ident: Ident,
David Tolnay8b4d3022017-12-29 12:11:10 -0500816 pub subpat: Option<(Token![@], Box<Pat>)>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700817 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700818
David Tolnaya454c8f2018-01-07 01:01:10 -0800819 /// A struct or struct variant pattern: `Variant { x, y, .. }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800820 ///
821 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700822 pub Struct(PatStruct {
823 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500824 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500825 pub fields: Punctuated<FieldPat, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800826 pub dot2_token: Option<Token![..]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700827 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700828
David Tolnaya454c8f2018-01-07 01:01:10 -0800829 /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800830 ///
831 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700832 pub TupleStruct(PatTupleStruct {
833 pub path: Path,
834 pub pat: PatTuple,
835 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700836
David Tolnaya454c8f2018-01-07 01:01:10 -0800837 /// A path pattern like `Color::Red`, optionally qualified with a
838 /// self-type.
839 ///
840 /// Unquailfied path patterns can legally refer to variants, structs,
841 /// constants or associated constants. Quailfied path patterns like
842 /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
843 /// associated constants.
David Tolnay461d98e2018-01-07 11:07:19 -0800844 ///
845 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700846 pub Path(PatPath {
847 pub qself: Option<QSelf>,
848 pub path: Path,
849 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700850
David Tolnaya454c8f2018-01-07 01:01:10 -0800851 /// A tuple pattern: `(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800852 ///
853 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700854 pub Tuple(PatTuple {
David Tolnay32954ef2017-12-26 22:43:16 -0500855 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500856 pub front: Punctuated<Pat, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500857 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500858 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500859 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700860 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800861
862 /// A box pattern: `box v`.
David Tolnay461d98e2018-01-07 11:07:19 -0800863 ///
864 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700865 pub Box(PatBox {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800866 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500867 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700868 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800869
870 /// A reference pattern: `&mut (first, second)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800871 ///
872 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700873 pub Ref(PatRef {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800874 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500875 pub mutability: Option<Token![mut]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500876 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700877 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800878
879 /// A literal pattern: `0`.
880 ///
881 /// This holds an `Expr` rather than a `Lit` because negative numbers
882 /// are represented as an `Expr::Unary`.
David Tolnay461d98e2018-01-07 11:07:19 -0800883 ///
884 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700885 pub Lit(PatLit {
886 pub expr: Box<Expr>,
887 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800888
889 /// A range pattern: `1..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800890 ///
891 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700892 pub Range(PatRange {
893 pub lo: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700894 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500895 pub hi: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700896 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800897
898 /// A dynamically sized slice pattern: `[a, b, i.., y, z]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800899 ///
900 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700901 pub Slice(PatSlice {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500902 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500903 pub front: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700904 pub middle: Option<Box<Pat>>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500905 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500906 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500907 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700908 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800909
910 /// A macro in expression position.
David Tolnay461d98e2018-01-07 11:07:19 -0800911 ///
912 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay323279a2017-12-29 11:26:32 -0500913 pub Macro(PatMacro {
914 pub mac: Macro,
915 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800916
917 /// Tokens in pattern position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800918 ///
919 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500920 pub Verbatim(PatVerbatim #manual_extra_traits {
921 pub tts: TokenStream,
922 }),
923 }
924}
925
David Tolnayc43b44e2017-12-30 23:55:54 -0500926#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500927impl Eq for PatVerbatim {}
928
David Tolnayc43b44e2017-12-30 23:55:54 -0500929#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500930impl PartialEq for PatVerbatim {
931 fn eq(&self, other: &Self) -> bool {
932 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
933 }
934}
935
David Tolnayc43b44e2017-12-30 23:55:54 -0500936#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500937impl Hash for PatVerbatim {
938 fn hash<H>(&self, state: &mut H)
939 where
940 H: Hasher,
941 {
942 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700943 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700944}
945
Michael Layzell734adb42017-06-07 16:58:31 -0400946#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700947ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800948 /// One arm of a `match` expression: `0...10 => { return true; }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700949 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800950 /// As in:
Alex Crichton62a0a592017-05-22 13:58:53 -0700951 ///
David Tolnaybcf26022017-12-25 22:10:52 -0500952 /// ```rust
David Tolnaya454c8f2018-01-07 01:01:10 -0800953 /// # fn f() -> bool {
David Tolnaybcf26022017-12-25 22:10:52 -0500954 /// # let n = 0;
Alex Crichton62a0a592017-05-22 13:58:53 -0700955 /// match n {
David Tolnaya454c8f2018-01-07 01:01:10 -0800956 /// 0...10 => {
957 /// return true;
958 /// }
959 /// // ...
David Tolnaybcf26022017-12-25 22:10:52 -0500960 /// # _ => {}
Alex Crichton62a0a592017-05-22 13:58:53 -0700961 /// }
David Tolnaya454c8f2018-01-07 01:01:10 -0800962 /// # false
David Tolnaybcf26022017-12-25 22:10:52 -0500963 /// # }
Alex Crichton62a0a592017-05-22 13:58:53 -0700964 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800965 ///
966 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700967 pub struct Arm {
968 pub attrs: Vec<Attribute>,
David Tolnay18cc4d42018-03-31 18:47:20 +0200969 pub leading_vert: Option<Token![|]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500970 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500971 pub guard: Option<(Token![if], Box<Expr>)>,
David Tolnaydfb91432018-03-31 19:19:44 +0200972 pub fat_arrow_token: Token![=>],
Alex Crichton62a0a592017-05-22 13:58:53 -0700973 pub body: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800974 pub comma: Option<Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700975 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700976}
977
Michael Layzell734adb42017-06-07 16:58:31 -0400978#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700979ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800980 /// Limit types of a range, inclusive or exclusive.
David Tolnay461d98e2018-01-07 11:07:19 -0800981 ///
982 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton2e0229c2017-05-23 09:34:50 -0700983 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700984 pub enum RangeLimits {
David Tolnaya454c8f2018-01-07 01:01:10 -0800985 /// Inclusive at the beginning, exclusive at the end.
David Tolnayf8db7ba2017-11-11 22:52:16 -0800986 HalfOpen(Token![..]),
David Tolnaya454c8f2018-01-07 01:01:10 -0800987 /// Inclusive at the beginning and end.
David Tolnaybe55d7b2017-12-17 23:41:20 -0800988 Closed(Token![..=]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700989 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700990}
991
Michael Layzell734adb42017-06-07 16:58:31 -0400992#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700993ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800994 /// A single field in a struct pattern.
Alex Crichton62a0a592017-05-22 13:58:53 -0700995 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800996 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
997 /// the same as `x: x, y: ref y, z: ref mut z` but there is no colon token.
David Tolnay461d98e2018-01-07 11:07:19 -0800998 ///
999 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -07001000 pub struct FieldPat {
David Tolnay4a3f59a2017-12-28 21:21:12 -05001001 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -05001002 pub member: Member,
David Tolnay4a3f59a2017-12-28 21:21:12 -05001003 pub colon_token: Option<Token![:]>,
Alex Crichton62a0a592017-05-22 13:58:53 -07001004 pub pat: Box<Pat>,
Alex Crichton62a0a592017-05-22 13:58:53 -07001005 }
David Tolnayf4bbbd92016-09-23 14:41:55 -07001006}
1007
Michael Layzell3936ceb2017-07-08 00:28:36 -04001008#[cfg(any(feature = "parsing", feature = "printing"))]
1009#[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -07001010fn requires_terminator(expr: &Expr) -> bool {
David Tolnay01218d12018-08-29 18:13:07 -07001011 // see https://github.com/rust-lang/rust/blob/eb8f2586e/src/libsyntax/parse/classify.rs#L17-L37
David Tolnay8c91b882017-12-28 23:04:32 -05001012 match *expr {
1013 Expr::Unsafe(..)
1014 | Expr::Block(..)
1015 | Expr::If(..)
1016 | Expr::IfLet(..)
1017 | Expr::Match(..)
1018 | Expr::While(..)
1019 | Expr::WhileLet(..)
1020 | Expr::Loop(..)
1021 | Expr::ForLoop(..)
David Tolnay02a9c6f2018-08-24 18:58:45 -04001022 | Expr::Async(..)
David Tolnayfb2dd4b2018-08-24 16:45:34 -04001023 | Expr::TryBlock(..) => false,
Alex Crichton03b30272017-08-28 09:35:24 -07001024 _ => true,
Michael Layzell3936ceb2017-07-08 00:28:36 -04001025 }
1026}
1027
David Tolnayb9c8e322016-09-23 20:48:37 -07001028#[cfg(feature = "parsing")]
1029pub mod parsing {
1030 use super::*;
David Tolnay60291082018-08-28 09:54:49 -07001031 use path;
David Tolnayb9c8e322016-09-23 20:48:37 -07001032
David Tolnay9389c382018-08-27 09:13:37 -07001033 use parse::{Parse, ParseStream, Result};
Michael Layzell734adb42017-06-07 16:58:31 -04001034 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001035 use synom::ext::IdentExt;
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001036
David Tolnaybcf26022017-12-25 22:10:52 -05001037 // When we're parsing expressions which occur before blocks, like in an if
1038 // statement's condition, we cannot parse a struct literal.
1039 //
1040 // Struct literals are ambiguous in certain positions
1041 // https://github.com/rust-lang/rfcs/pull/92
David Tolnay9389c382018-08-27 09:13:37 -07001042 #[derive(Copy, Clone)]
1043 pub struct AllowStruct(bool);
1044
David Tolnay01218d12018-08-29 18:13:07 -07001045 #[derive(Copy, Clone, PartialEq, PartialOrd)]
1046 enum Precedence {
1047 Any,
1048 Assign,
1049 Placement,
1050 Range,
1051 Or,
1052 And,
1053 Compare,
1054 BitOr,
1055 BitXor,
1056 BitAnd,
1057 Shift,
1058 Arithmetic,
1059 Term,
1060 Cast,
1061 }
1062
1063 impl Precedence {
1064 fn of(op: &BinOp) -> Self {
1065 match *op {
1066 BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic,
1067 BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term,
1068 BinOp::And(_) => Precedence::And,
1069 BinOp::Or(_) => Precedence::Or,
1070 BinOp::BitXor(_) => Precedence::BitXor,
1071 BinOp::BitAnd(_) => Precedence::BitAnd,
1072 BinOp::BitOr(_) => Precedence::BitOr,
1073 BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
1074 BinOp::Eq(_) | BinOp::Lt(_) | BinOp::Le(_) | BinOp::Ne(_) | BinOp::Ge(_) | BinOp::Gt(_) => Precedence::Compare,
1075 BinOp::AddEq(_) | BinOp::SubEq(_) | BinOp::MulEq(_) | BinOp::DivEq(_) | BinOp::RemEq(_) | BinOp::BitXorEq(_) | BinOp::BitAndEq(_) | BinOp::BitOrEq(_) | BinOp::ShlEq(_) | BinOp::ShrEq(_) => Precedence::Assign,
1076 }
1077 }
1078 }
1079
David Tolnay9389c382018-08-27 09:13:37 -07001080 impl Parse for Expr {
1081 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001082 ambiguous_expr(input, AllowStruct(true))
Alex Crichton954046c2017-05-30 21:49:42 -07001083 }
1084 }
1085
Michael Layzell734adb42017-06-07 16:58:31 -04001086 #[cfg(feature = "full")]
David Tolnay9fb0aed2018-08-27 10:23:12 -07001087 fn expr_no_struct(input: ParseStream) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001088 ambiguous_expr(input, AllowStruct(false))
David Tolnay9fb0aed2018-08-27 10:23:12 -07001089 }
David Tolnayaf2557e2016-10-24 11:52:21 -07001090
David Tolnay01218d12018-08-29 18:13:07 -07001091 #[cfg(feature = "full")]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001092 fn parse_expr(input: ParseStream, mut lhs: Expr, allow_struct: AllowStruct, base: Precedence) -> Result<Expr> {
David Tolnay01218d12018-08-29 18:13:07 -07001093 loop {
1094 if input.fork().parse::<BinOp>().ok().map_or(false, |op| Precedence::of(&op) >= base) {
1095 let op: BinOp = input.parse()?;
1096 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001097 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001098 loop {
1099 let next = peek_precedence(input);
1100 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001101 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001102 } else {
1103 break;
1104 }
1105 }
1106 lhs = Expr::Binary(ExprBinary {
1107 attrs: Vec::new(),
1108 left: Box::new(lhs),
1109 op: op,
1110 right: Box::new(rhs),
1111 });
1112 } else if Precedence::Assign >= base && input.peek(Token![=]) && !input.peek(Token![==]) && !input.peek(Token![=>]) {
1113 let eq_token: Token![=] = input.parse()?;
David Tolnay7d2e1db2018-08-30 11:49:04 -07001114 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001115 loop {
1116 let next = peek_precedence(input);
1117 if next >= Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001118 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001119 } else {
1120 break;
1121 }
1122 }
1123 lhs = Expr::Assign(ExprAssign {
1124 attrs: Vec::new(),
1125 left: Box::new(lhs),
1126 eq_token: eq_token,
1127 right: Box::new(rhs),
1128 });
1129 } else if Precedence::Placement >= base && input.peek(Token![<-]) {
1130 let arrow_token: Token![<-] = input.parse()?;
David Tolnay7d2e1db2018-08-30 11:49:04 -07001131 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001132 loop {
1133 let next = peek_precedence(input);
1134 if next > Precedence::Placement {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001135 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001136 } else {
1137 break;
1138 }
1139 }
1140 lhs = Expr::InPlace(ExprInPlace {
1141 attrs: Vec::new(),
1142 place: Box::new(lhs),
1143 arrow_token: arrow_token,
1144 value: Box::new(rhs),
1145 });
1146 } else if Precedence::Range >= base && input.peek(Token![..]) {
1147 let limits: RangeLimits = input.parse()?;
1148 let rhs = if input.is_empty()
1149 || input.peek(Token![,])
1150 || input.peek(Token![;])
1151 || !allow_struct.0 && input.peek(token::Brace)
1152 {
1153 None
1154 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001155 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001156 loop {
1157 let next = peek_precedence(input);
1158 if next > Precedence::Range {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001159 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001160 } else {
1161 break;
1162 }
1163 }
1164 Some(rhs)
1165 };
1166 lhs = Expr::Range(ExprRange {
1167 attrs: Vec::new(),
1168 from: Some(Box::new(lhs)),
1169 limits: limits,
1170 to: rhs.map(Box::new),
1171 });
1172 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1173 let as_token: Token![as] = input.parse()?;
1174 let ty = input.call(Type::without_plus)?;
1175 lhs = Expr::Cast(ExprCast {
1176 attrs: Vec::new(),
1177 expr: Box::new(lhs),
1178 as_token: as_token,
1179 ty: Box::new(ty),
1180 });
1181 } else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) {
1182 let colon_token: Token![:] = input.parse()?;
1183 let ty = input.call(Type::without_plus)?;
1184 lhs = Expr::Type(ExprType {
1185 attrs: Vec::new(),
1186 expr: Box::new(lhs),
1187 colon_token: colon_token,
1188 ty: Box::new(ty),
1189 });
1190 } else {
1191 break;
1192 }
1193 }
1194 Ok(lhs)
1195 }
1196
David Tolnay3e541292018-08-30 11:42:15 -07001197 #[cfg(not(feature = "full"))]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001198 fn parse_expr(input: ParseStream, mut lhs: Expr, allow_struct: AllowStruct, base: Precedence) -> Result<Expr> {
David Tolnay3e541292018-08-30 11:42:15 -07001199 loop {
1200 if input.fork().parse::<BinOp>().ok().map_or(false, |op| Precedence::of(&op) >= base) {
1201 let op: BinOp = input.parse()?;
1202 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001203 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay3e541292018-08-30 11:42:15 -07001204 loop {
1205 let next = peek_precedence(input);
1206 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001207 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay3e541292018-08-30 11:42:15 -07001208 } else {
1209 break;
1210 }
1211 }
1212 lhs = Expr::Binary(ExprBinary {
1213 attrs: Vec::new(),
1214 left: Box::new(lhs),
1215 op: op,
1216 right: Box::new(rhs),
1217 });
1218 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1219 let as_token: Token![as] = input.parse()?;
1220 let ty = input.call(Type::without_plus)?;
1221 lhs = Expr::Cast(ExprCast {
1222 attrs: Vec::new(),
1223 expr: Box::new(lhs),
1224 as_token: as_token,
1225 ty: Box::new(ty),
1226 });
1227 } else {
1228 break;
1229 }
1230 }
1231 Ok(lhs)
1232 }
1233
David Tolnay01218d12018-08-29 18:13:07 -07001234 fn peek_precedence(input: ParseStream) -> Precedence {
1235 if let Ok(op) = input.fork().parse() {
1236 Precedence::of(&op)
David Tolnay3e541292018-08-30 11:42:15 -07001237 } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
David Tolnay01218d12018-08-29 18:13:07 -07001238 Precedence::Assign
1239 } else if input.peek(Token![<-]) {
1240 Precedence::Placement
1241 } else if input.peek(Token![..]) {
1242 Precedence::Range
1243 } else if input.peek(Token![as]) || input.peek(Token![:]) && !input.peek(Token![::]) {
1244 Precedence::Cast
1245 } else {
1246 Precedence::Any
1247 }
1248 }
1249
David Tolnaybcf26022017-12-25 22:10:52 -05001250 // Parse an arbitrary expression.
David Tolnay60291082018-08-28 09:54:49 -07001251 fn ambiguous_expr(
1252 input: ParseStream,
1253 allow_struct: AllowStruct,
David Tolnay60291082018-08-28 09:54:49 -07001254 ) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001255 let lhs = unary_expr(input, allow_struct)?;
1256 parse_expr(input, lhs, allow_struct, Precedence::Any)
Michael Layzellb78f3b52017-06-04 19:03:03 -04001257 }
1258
David Tolnaybcf26022017-12-25 22:10:52 -05001259 // <UnOp> <trailer>
1260 // & <trailer>
1261 // &mut <trailer>
1262 // box <trailer>
Michael Layzell734adb42017-06-07 16:58:31 -04001263 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001264 fn unary_expr(
1265 input: ParseStream,
1266 allow_struct: AllowStruct,
David Tolnay60291082018-08-28 09:54:49 -07001267 ) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001268 let ahead = input.fork();
1269 ahead.call(Attribute::parse_outer)?;
1270 if ahead.peek(Token![&])
1271 || ahead.peek(Token![box])
1272 || ahead.peek(Token![*])
1273 || ahead.peek(Token![!])
1274 || ahead.peek(Token![-])
1275 {
1276 let attrs = input.call(Attribute::parse_outer)?;
1277 if input.peek(Token![&]) {
1278 Ok(Expr::Reference(ExprReference {
1279 attrs: attrs,
1280 and_token: input.parse()?,
1281 mutability: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001282 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001283 }))
1284 } else if input.peek(Token![box]) {
1285 Ok(Expr::Box(ExprBox {
1286 attrs: attrs,
1287 box_token: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001288 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001289 }))
1290 } else {
1291 Ok(Expr::Unary(ExprUnary {
1292 attrs: attrs,
1293 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001294 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001295 }))
1296 }
1297 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001298 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001299 }
1300 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001301
Michael Layzell734adb42017-06-07 16:58:31 -04001302 // XXX: This duplication is ugly
1303 #[cfg(not(feature = "full"))]
David Tolnay60291082018-08-28 09:54:49 -07001304 fn unary_expr(
1305 input: ParseStream,
1306 allow_struct: AllowStruct,
David Tolnay60291082018-08-28 09:54:49 -07001307 ) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001308 let ahead = input.fork();
1309 ahead.call(Attribute::parse_outer)?;
1310 if ahead.peek(Token![*]) || ahead.peek(Token![!]) || ahead.peek(Token![-]) {
1311 Ok(Expr::Unary(ExprUnary {
1312 attrs: input.call(Attribute::parse_outer)?,
1313 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001314 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001315 }))
1316 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001317 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001318 }
1319 }
Michael Layzell734adb42017-06-07 16:58:31 -04001320
David Tolnayd997aef2018-07-21 18:42:31 -07001321 #[cfg(feature = "full")]
David Tolnay5d314dc2018-07-21 16:40:01 -07001322 fn take_outer(attrs: &mut Vec<Attribute>) -> Vec<Attribute> {
1323 let mut outer = Vec::new();
1324 let mut inner = Vec::new();
1325 for attr in mem::replace(attrs, Vec::new()) {
1326 match attr.style {
1327 AttrStyle::Outer => outer.push(attr),
1328 AttrStyle::Inner(_) => inner.push(attr),
1329 }
1330 }
1331 *attrs = inner;
1332 outer
1333 }
1334
David Tolnaybcf26022017-12-25 22:10:52 -05001335 // <atom> (..<args>) ...
1336 // <atom> . <ident> (..<args>) ...
1337 // <atom> . <ident> ...
1338 // <atom> . <lit> ...
1339 // <atom> [ <expr> ] ...
1340 // <atom> ? ...
Michael Layzell734adb42017-06-07 16:58:31 -04001341 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001342 fn trailer_expr(
1343 input: ParseStream,
1344 allow_struct: AllowStruct,
David Tolnay60291082018-08-28 09:54:49 -07001345 ) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001346 let mut e = atom_expr(input, allow_struct)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001347
1348 let mut attrs = e.replace_attrs(Vec::new());
1349 let outer_attrs = take_outer(&mut attrs);
1350 e.replace_attrs(attrs);
1351
David Tolnay01218d12018-08-29 18:13:07 -07001352 e = trailer_helper(input, e)?;
1353
1354 let mut attrs = outer_attrs;
1355 attrs.extend(e.replace_attrs(Vec::new()));
1356 e.replace_attrs(attrs);
1357 Ok(e)
1358 }
1359
1360 #[cfg(feature = "full")]
1361 fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
David Tolnay1501f7e2018-08-27 14:21:03 -07001362 loop {
1363 if input.peek(token::Paren) {
1364 let content;
1365 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001366 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001367 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001368 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001369 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001370 });
1371 } else if input.peek(Token![.]) && !input.peek(Token![..]) {
1372 let dot_token: Token![.] = input.parse()?;
1373 let member: Member = input.parse()?;
1374 let turbofish = if member.is_named() && input.peek(Token![::]) {
1375 Some(MethodTurbofish {
1376 colon2_token: input.parse()?,
1377 lt_token: input.parse()?,
1378 args: {
1379 let mut args = Punctuated::new();
1380 loop {
1381 if input.peek(Token![>]) {
1382 break;
1383 }
David Tolnay310b3262018-08-30 15:33:00 -07001384 let value = input.call(generic_method_argument)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001385 args.push_value(value);
1386 if input.peek(Token![>]) {
1387 break;
1388 }
1389 let punct = input.parse()?;
1390 args.push_punct(punct);
1391 }
1392 args
1393 },
1394 gt_token: input.parse()?,
1395 })
1396 } else {
1397 None
1398 };
1399
1400 if turbofish.is_some() || input.peek(token::Paren) {
1401 if let Member::Named(method) = member {
1402 let content;
1403 e = Expr::MethodCall(ExprMethodCall {
1404 attrs: Vec::new(),
1405 receiver: Box::new(e),
1406 dot_token: dot_token,
1407 method: method,
1408 turbofish: turbofish,
1409 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001410 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001411 });
1412 continue;
1413 }
1414 }
1415
1416 e = Expr::Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -05001417 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001418 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001419 dot_token: dot_token,
David Tolnay85b69a42017-12-27 20:43:10 -05001420 member: member,
David Tolnay1501f7e2018-08-27 14:21:03 -07001421 });
1422 } else if input.peek(token::Bracket) {
1423 let content;
1424 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001425 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001426 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001427 bracket_token: bracketed!(content in input),
1428 index: content.parse()?,
1429 });
1430 } else if input.peek(Token![?]) {
1431 e = Expr::Try(ExprTry {
David Tolnay8c91b882017-12-28 23:04:32 -05001432 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001433 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001434 question_token: input.parse()?,
1435 });
1436 } else {
1437 break;
1438 }
1439 }
David Tolnay1501f7e2018-08-27 14:21:03 -07001440 Ok(e)
1441 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001442
Michael Layzell734adb42017-06-07 16:58:31 -04001443 // XXX: Duplication == ugly
1444 #[cfg(not(feature = "full"))]
David Tolnay60291082018-08-28 09:54:49 -07001445 fn trailer_expr(
1446 input: ParseStream,
1447 allow_struct: AllowStruct,
David Tolnay60291082018-08-28 09:54:49 -07001448 ) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001449 let mut e = atom_expr(input, allow_struct)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001450
1451 loop {
1452 if input.peek(token::Paren) {
1453 let content;
1454 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001455 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001456 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001457 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001458 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001459 });
1460 } else if input.peek(Token![.]) {
1461 e = Expr::Field(ExprField {
David Tolnayd5147742018-06-30 10:09:52 -07001462 attrs: Vec::new(),
1463 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001464 dot_token: input.parse()?,
1465 member: input.parse()?,
1466 });
1467 } else if input.peek(token::Bracket) {
1468 let content;
1469 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001470 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001471 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001472 bracket_token: bracketed!(content in input),
1473 index: content.parse()?,
1474 });
1475 } else {
1476 break;
1477 }
1478 }
1479
1480 Ok(e)
1481 }
Michael Layzell734adb42017-06-07 16:58:31 -04001482
David Tolnaya454c8f2018-01-07 01:01:10 -08001483 // Parse all atomic expressions which don't have to worry about precedence
David Tolnaybcf26022017-12-25 22:10:52 -05001484 // interactions, as they are fully contained.
Michael Layzell734adb42017-06-07 16:58:31 -04001485 #[cfg(feature = "full")]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001486 fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001487 if input.peek(token::Group) {
David Tolnay310b3262018-08-30 15:33:00 -07001488 return input.call(expr_group).map(Expr::Group);
David Tolnay6e1e5052018-08-30 10:21:48 -07001489 }
1490
1491 let mut attrs = input.call(Attribute::parse_outer)?;
1492
1493 let mut expr = if input.peek(token::Group) {
David Tolnay310b3262018-08-30 15:33:00 -07001494 Expr::Group(input.call(expr_group)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001495 } else if input.peek(Lit) {
David Tolnay310b3262018-08-30 15:33:00 -07001496 Expr::Lit(input.call(expr_lit)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001497 } else if input.peek(Token![async])
1498 && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
1499 {
David Tolnay310b3262018-08-30 15:33:00 -07001500 Expr::Async(input.call(expr_async)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001501 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001502 Expr::TryBlock(input.call(expr_try_block)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001503 } else if input.peek(Token![|])
1504 || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1505 || input.peek(Token![static])
1506 || input.peek(Token![move])
1507 {
1508 Expr::Closure(expr_closure(input, allow_struct)?)
1509 } else if input.peek(Ident)
1510 || input.peek(Token![::])
1511 || input.peek(Token![<])
1512 || input.peek(Token![self])
1513 || input.peek(Token![Self])
1514 || input.peek(Token![super])
1515 || input.peek(Token![extern])
1516 || input.peek(Token![crate])
1517 {
1518 path_or_macro_or_struct(input, allow_struct)?
1519 } else if input.peek(token::Paren) {
1520 paren_or_tuple(input)?
1521 } else if input.peek(Token![break]) {
1522 Expr::Break(expr_break(input, allow_struct)?)
1523 } else if input.peek(Token![continue]) {
David Tolnay310b3262018-08-30 15:33:00 -07001524 Expr::Continue(input.call(expr_continue)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001525 } else if input.peek(Token![return]) {
1526 Expr::Return(expr_ret(input, allow_struct)?)
1527 } else if input.peek(token::Bracket) {
1528 array_or_repeat(input)?
1529 } else if input.peek(Token![if]) {
1530 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001531 Expr::IfLet(input.call(expr_if_let)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001532 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001533 Expr::If(input.call(expr_if)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001534 }
1535 } else if input.peek(Token![while]) {
1536 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001537 Expr::WhileLet(input.call(expr_while_let)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001538 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001539 Expr::While(input.call(expr_while)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001540 }
1541 } else if input.peek(Token![for]) {
David Tolnay310b3262018-08-30 15:33:00 -07001542 Expr::ForLoop(input.call(expr_for_loop)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001543 } else if input.peek(Token![loop]) {
David Tolnay310b3262018-08-30 15:33:00 -07001544 Expr::Loop(input.call(expr_loop)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001545 } else if input.peek(Token![match]) {
David Tolnay310b3262018-08-30 15:33:00 -07001546 Expr::Match(input.call(expr_match)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001547 } else if input.peek(Token![yield]) {
David Tolnay310b3262018-08-30 15:33:00 -07001548 Expr::Yield(input.call(expr_yield)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001549 } else if input.peek(Token![unsafe]) {
David Tolnay310b3262018-08-30 15:33:00 -07001550 Expr::Unsafe(input.call(expr_unsafe)?)
David Tolnay7d2e1db2018-08-30 11:49:04 -07001551 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001552 Expr::Block(input.call(expr_block)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001553 } else if input.peek(Token![..]) {
1554 Expr::Range(expr_range(input, allow_struct)?)
1555 } else if input.peek(Lifetime) {
1556 let the_label: Label = input.parse()?;
1557 let mut expr = if input.peek(Token![while]) {
1558 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001559 Expr::WhileLet(input.call(expr_while_let)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001560 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001561 Expr::While(input.call(expr_while)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001562 }
1563 } else if input.peek(Token![for]) {
David Tolnay310b3262018-08-30 15:33:00 -07001564 Expr::ForLoop(input.call(expr_for_loop)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001565 } else if input.peek(Token![loop]) {
David Tolnay310b3262018-08-30 15:33:00 -07001566 Expr::Loop(input.call(expr_loop)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001567 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001568 Expr::Block(input.call(expr_block)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001569 } else {
1570 return Err(input.error("expected loop or block expression"));
1571 };
1572 match expr {
1573 Expr::WhileLet(ExprWhileLet { ref mut label, .. }) |
1574 Expr::While(ExprWhile { ref mut label, .. }) |
1575 Expr::ForLoop(ExprForLoop { ref mut label, .. }) |
1576 Expr::Loop(ExprLoop { ref mut label, .. }) |
1577 Expr::Block(ExprBlock { ref mut label, .. }) => *label = Some(the_label),
1578 _ => unreachable!(),
1579 }
1580 expr
1581 } else {
1582 return Err(input.error("expected expression"));
1583 };
1584
1585 attrs.extend(expr.replace_attrs(Vec::new()));
1586 expr.replace_attrs(attrs);
1587 Ok(expr)
1588 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001589
Michael Layzell734adb42017-06-07 16:58:31 -04001590 #[cfg(not(feature = "full"))]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001591 fn atom_expr(input: ParseStream, _allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001592 if input.peek(Lit) {
David Tolnay310b3262018-08-30 15:33:00 -07001593 input.call(expr_lit).map(Expr::Lit)
David Tolnay6e1e5052018-08-30 10:21:48 -07001594 } else if input.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07001595 input.call(expr_paren).map(Expr::Paren)
David Tolnay6e1e5052018-08-30 10:21:48 -07001596 } else if input.peek(Ident)
1597 || input.peek(Token![::])
1598 || input.peek(Token![<])
1599 || input.peek(Token![self])
1600 || input.peek(Token![Self])
1601 || input.peek(Token![super])
1602 || input.peek(Token![extern])
1603 || input.peek(Token![crate])
1604 {
1605 input.parse().map(Expr::Path)
1606 } else {
1607 Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
1608 }
1609 }
1610
1611 #[cfg(feature = "full")]
1612 fn path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1613 let expr: ExprPath = input.parse()?;
1614 if expr.qself.is_some() {
1615 return Ok(Expr::Path(expr));
1616 }
1617
1618 if input.peek(Token![!]) && !input.peek(Token![!=]) {
1619 let mut contains_arguments = false;
1620 for segment in &expr.path.segments {
1621 match segment.arguments {
1622 PathArguments::None => {}
1623 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
1624 contains_arguments = true;
1625 }
1626 }
1627 }
1628
1629 if !contains_arguments {
1630 let bang_token: Token![!] = input.parse()?;
1631 let (delimiter, tts) = mac::parse_delimiter(input)?;
1632 return Ok(Expr::Macro(ExprMacro {
1633 attrs: Vec::new(),
1634 mac: Macro {
1635 path: expr.path,
1636 bang_token: bang_token,
1637 delimiter: delimiter,
1638 tts: tts,
1639 },
1640 }));
1641 }
1642 }
1643
1644 if allow_struct.0 && input.peek(token::Brace) {
1645 let outer_attrs = Vec::new();
1646 expr_struct_helper(input, outer_attrs, expr.path).map(Expr::Struct)
1647 } else {
1648 Ok(Expr::Path(expr))
1649 }
1650 }
1651
1652 #[cfg(feature = "full")]
1653 fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
1654 let content;
1655 let paren_token = parenthesized!(content in input);
1656 let inner_attrs = content.call(Attribute::parse_inner)?;
1657 if content.is_empty() {
1658 return Ok(Expr::Tuple(ExprTuple {
1659 attrs: inner_attrs,
1660 paren_token: paren_token,
1661 elems: Punctuated::new(),
1662 }));
1663 }
1664
1665 let first: Expr = content.parse()?;
1666 if content.is_empty() {
1667 return Ok(Expr::Paren(ExprParen {
1668 attrs: inner_attrs,
1669 paren_token: paren_token,
1670 expr: Box::new(first),
1671 }));
1672 }
1673
1674 let mut elems = Punctuated::new();
1675 elems.push_value(first);
1676 while !content.is_empty() {
1677 let punct = content.parse()?;
1678 elems.push_punct(punct);
1679 if content.is_empty() {
1680 break;
1681 }
1682 let value = content.parse()?;
1683 elems.push_value(value);
1684 }
1685 Ok(Expr::Tuple(ExprTuple {
1686 attrs: inner_attrs,
1687 paren_token: paren_token,
1688 elems: elems,
1689 }))
1690 }
1691
1692 #[cfg(feature = "full")]
1693 fn array_or_repeat(input: ParseStream) -> Result<Expr> {
1694 let content;
1695 let bracket_token = bracketed!(content in input);
1696 let inner_attrs = content.call(Attribute::parse_inner)?;
1697 if content.is_empty() {
1698 return Ok(Expr::Array(ExprArray {
1699 attrs: inner_attrs,
1700 bracket_token: bracket_token,
1701 elems: Punctuated::new(),
1702 }));
1703 }
1704
1705 let first: Expr = content.parse()?;
1706 if content.is_empty() || content.peek(Token![,]) {
1707 let mut elems = Punctuated::new();
1708 elems.push_value(first);
1709 while !content.is_empty() {
1710 let punct = content.parse()?;
1711 elems.push_punct(punct);
1712 if content.is_empty() {
1713 break;
1714 }
1715 let value = content.parse()?;
1716 elems.push_value(value);
1717 }
1718 Ok(Expr::Array(ExprArray {
1719 attrs: inner_attrs,
1720 bracket_token: bracket_token,
1721 elems: elems,
1722 }))
1723 } else if content.peek(Token![;]) {
1724 let semi_token: Token![;] = content.parse()?;
1725 let len: Expr = content.parse()?;
1726 Ok(Expr::Repeat(ExprRepeat {
1727 attrs: inner_attrs,
1728 bracket_token: bracket_token,
1729 expr: Box::new(first),
1730 semi_token: semi_token,
1731 len: Box::new(len),
1732 }))
1733 } else {
1734 Err(content.error("expected `,` or `;`"))
1735 }
1736 }
Michael Layzell734adb42017-06-07 16:58:31 -04001737
Michael Layzell734adb42017-06-07 16:58:31 -04001738 #[cfg(feature = "full")]
David Tolnay01218d12018-08-29 18:13:07 -07001739 fn expr_early(input: ParseStream) -> Result<Expr> {
1740 let mut attrs = input.call(Attribute::parse_outer)?;
1741 let mut expr = if input.peek(Token![if]) {
1742 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001743 Expr::IfLet(input.call(expr_if_let)?)
David Tolnay01218d12018-08-29 18:13:07 -07001744 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001745 Expr::If(input.call(expr_if)?)
David Tolnay01218d12018-08-29 18:13:07 -07001746 }
1747 } else if input.peek(Token![while]) {
1748 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001749 Expr::WhileLet(input.call(expr_while_let)?)
David Tolnay01218d12018-08-29 18:13:07 -07001750 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001751 Expr::While(input.call(expr_while)?)
David Tolnay01218d12018-08-29 18:13:07 -07001752 }
1753 } else if input.peek(Token![for]) {
David Tolnay310b3262018-08-30 15:33:00 -07001754 Expr::ForLoop(input.call(expr_for_loop)?)
David Tolnay01218d12018-08-29 18:13:07 -07001755 } else if input.peek(Token![loop]) {
David Tolnay310b3262018-08-30 15:33:00 -07001756 Expr::Loop(input.call(expr_loop)?)
David Tolnay01218d12018-08-29 18:13:07 -07001757 } else if input.peek(Token![match]) {
David Tolnay310b3262018-08-30 15:33:00 -07001758 Expr::Match(input.call(expr_match)?)
David Tolnay01218d12018-08-29 18:13:07 -07001759 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001760 Expr::TryBlock(input.call(expr_try_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001761 } else if input.peek(Token![unsafe]) {
David Tolnay310b3262018-08-30 15:33:00 -07001762 Expr::Unsafe(input.call(expr_unsafe)?)
David Tolnay01218d12018-08-29 18:13:07 -07001763 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001764 Expr::Block(input.call(expr_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001765 } else {
1766 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001767 let mut expr = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001768
1769 attrs.extend(expr.replace_attrs(Vec::new()));
1770 expr.replace_attrs(attrs);
1771
David Tolnay7d2e1db2018-08-30 11:49:04 -07001772 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001773 };
1774
1775 if input.peek(Token![.]) || input.peek(Token![?]) {
1776 expr = trailer_helper(input, expr)?;
1777
1778 attrs.extend(expr.replace_attrs(Vec::new()));
1779 expr.replace_attrs(attrs);
1780
1781 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001782 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001783 }
1784
1785 attrs.extend(expr.replace_attrs(Vec::new()));
1786 expr.replace_attrs(attrs);
1787 Ok(expr)
1788 }
Michael Layzell35418782017-06-07 09:20:25 -04001789
David Tolnay310b3262018-08-30 15:33:00 -07001790 pub fn expr_lit(input: ParseStream) -> Result<ExprLit> {
1791 Ok(ExprLit {
1792 attrs: Vec::new(),
1793 lit: input.parse()?,
1794 })
David Tolnay8c91b882017-12-28 23:04:32 -05001795 }
1796
1797 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001798 fn expr_group(input: ParseStream) -> Result<ExprGroup> {
1799 let content;
1800 Ok(ExprGroup {
1801 attrs: Vec::new(),
1802 group_token: grouped!(content in input),
1803 expr: content.parse()?,
1804 })
1805 }
1806
1807 #[cfg(not(feature = "full"))]
1808 fn expr_paren(input: ParseStream) -> Result<ExprParen> {
1809 let content;
1810 Ok(ExprParen {
1811 attrs: Vec::new(),
1812 paren_token: parenthesized!(content in input),
1813 expr: content.parse()?,
1814 })
David Tolnay8c91b882017-12-28 23:04:32 -05001815 }
1816
David Tolnaye98775f2017-12-28 23:17:00 -05001817 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001818 fn generic_method_argument(input: ParseStream) -> Result<GenericMethodArgument> {
David Tolnayd60cfec2017-12-29 00:21:38 -05001819 // TODO parse const generics as well
David Tolnay8db2d662018-08-30 17:40:59 -07001820 input.parse().map(GenericMethodArgument::Type)
David Tolnayd60cfec2017-12-29 00:21:38 -05001821 }
1822
1823 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001824 fn expr_if_let(input: ParseStream) -> Result<ExprIfLet> {
1825 Ok(ExprIfLet {
1826 attrs: Vec::new(),
1827 if_token: input.parse()?,
1828 let_token: input.parse()?,
1829 pats: {
1830 let mut pats = Punctuated::new();
1831 let value: Pat = input.parse()?;
1832 pats.push_value(value);
1833 while input.peek(Token![|])
1834 && !input.peek(Token![||])
1835 && !input.peek(Token![|=])
1836 {
1837 let punct = input.parse()?;
1838 pats.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07001839 let value: Pat = input.parse()?;
1840 pats.push_value(value);
David Tolnay310b3262018-08-30 15:33:00 -07001841 }
1842 pats
1843 },
1844 eq_token: input.parse()?,
1845 expr: Box::new(input.call(expr_no_struct)?),
1846 then_branch: input.parse()?,
1847 else_branch: {
1848 if input.peek(Token![else]) {
1849 Some(input.call(else_block)?)
1850 } else {
1851 None
1852 }
1853 },
1854 })
David Tolnay29f9ce12016-10-02 20:58:40 -07001855 }
1856
Michael Layzell734adb42017-06-07 16:58:31 -04001857 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001858 fn expr_if(input: ParseStream) -> Result<ExprIf> {
1859 Ok(ExprIf {
1860 attrs: Vec::new(),
1861 if_token: input.parse()?,
1862 cond: 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 })
Alex Crichton954046c2017-05-30 21:49:42 -07001872 }
David Tolnaybb6feae2016-10-02 21:25:20 -07001873
Michael Layzell734adb42017-06-07 16:58:31 -04001874 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001875 fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
1876 let else_token: Token![else] = input.parse()?;
1877
1878 let lookahead = input.lookahead1();
1879 let else_branch = if input.peek(Token![if]) {
1880 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001881 input.call(expr_if_let).map(Expr::IfLet)?
David Tolnay60291082018-08-28 09:54:49 -07001882 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001883 input.call(expr_if).map(Expr::If)?
David Tolnay60291082018-08-28 09:54:49 -07001884 }
1885 } else if input.peek(token::Brace) {
1886 Expr::Block(ExprBlock {
1887 attrs: Vec::new(),
1888 label: None,
1889 block: input.parse()?,
1890 })
1891 } else {
1892 return Err(lookahead.error());
1893 };
1894
1895 Ok((else_token, Box::new(else_branch)))
1896 }
David Tolnay939766a2016-09-23 23:48:12 -07001897
Michael Layzell734adb42017-06-07 16:58:31 -04001898 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001899 fn expr_for_loop(input: ParseStream) -> Result<ExprForLoop> {
1900 let label: Option<Label> = input.parse()?;
1901 let for_token: Token![for] = input.parse()?;
1902 let pat: Pat = input.parse()?;
1903 let in_token: Token![in] = input.parse()?;
1904 let expr: Expr = input.call(expr_no_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07001905
David Tolnay310b3262018-08-30 15:33:00 -07001906 let content;
1907 let brace_token = braced!(content in input);
1908 let inner_attrs = content.call(Attribute::parse_inner)?;
1909 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07001910
David Tolnay310b3262018-08-30 15:33:00 -07001911 Ok(ExprForLoop {
1912 attrs: inner_attrs,
1913 label: label,
1914 for_token: for_token,
1915 pat: Box::new(pat),
1916 in_token: in_token,
1917 expr: Box::new(expr),
1918 body: Block {
David Tolnay60291082018-08-28 09:54:49 -07001919 brace_token: brace_token,
David Tolnay310b3262018-08-30 15:33:00 -07001920 stmts: stmts,
1921 },
1922 })
Alex Crichton954046c2017-05-30 21:49:42 -07001923 }
David Tolnay1978c672016-10-27 22:05:52 -07001924
Michael Layzell734adb42017-06-07 16:58:31 -04001925 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001926 fn expr_loop(input: ParseStream) -> Result<ExprLoop> {
1927 let label: Option<Label> = input.parse()?;
1928 let loop_token: Token![loop] = input.parse()?;
1929
1930 let content;
1931 let brace_token = braced!(content in input);
1932 let inner_attrs = content.call(Attribute::parse_inner)?;
1933 let stmts = content.call(Block::parse_within)?;
1934
1935 Ok(ExprLoop {
1936 attrs: inner_attrs,
1937 label: label,
1938 loop_token: loop_token,
1939 body: Block {
1940 brace_token: brace_token,
1941 stmts: stmts,
1942 },
1943 })
Alex Crichton954046c2017-05-30 21:49:42 -07001944 }
Arnavion02ef13f2017-04-25 00:54:31 -07001945
Michael Layzell734adb42017-06-07 16:58:31 -04001946 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001947 fn expr_match(input: ParseStream) -> Result<ExprMatch> {
1948 let match_token: Token![match] = input.parse()?;
1949 let expr = expr_no_struct(input)?;
1950
1951 let content;
1952 let brace_token = braced!(content in input);
1953 let inner_attrs = content.call(Attribute::parse_inner)?;
1954
1955 let mut arms = Vec::new();
1956 while !content.is_empty() {
1957 arms.push(content.call(match_arm)?);
1958 }
1959
1960 Ok(ExprMatch {
1961 attrs: inner_attrs,
1962 match_token: match_token,
1963 expr: Box::new(expr),
1964 brace_token: brace_token,
1965 arms: arms,
1966 })
1967 }
1968
1969 #[cfg(feature = "full")]
1970 fn expr_try_block(input: ParseStream) -> Result<ExprTryBlock> {
1971 Ok(ExprTryBlock {
1972 attrs: Vec::new(),
1973 try_token: input.parse()?,
1974 block: input.parse()?,
1975 })
1976 }
1977
1978 #[cfg(feature = "full")]
1979 fn expr_yield(input: ParseStream) -> Result<ExprYield> {
1980 Ok(ExprYield {
1981 attrs: Vec::new(),
1982 yield_token: input.parse()?,
1983 expr: {
1984 if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
1985 Some(input.parse()?)
1986 } else {
1987 None
1988 }
1989 },
1990 })
1991 }
1992
1993 #[cfg(feature = "full")]
1994 fn match_arm(input: ParseStream) -> Result<Arm> {
1995 let requires_comma;
1996 Ok(Arm {
1997 attrs: input.call(Attribute::parse_outer)?,
1998 leading_vert: input.parse()?,
1999 pats: {
2000 let mut pats = Punctuated::new();
2001 let value: Pat = input.parse()?;
2002 pats.push_value(value);
2003 loop {
2004 if !input.peek(Token![|]) {
2005 break;
David Tolnay60291082018-08-28 09:54:49 -07002006 }
David Tolnay310b3262018-08-30 15:33:00 -07002007 let punct = input.parse()?;
2008 pats.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002009 let value: Pat = input.parse()?;
2010 pats.push_value(value);
David Tolnay310b3262018-08-30 15:33:00 -07002011 }
2012 pats
2013 },
2014 guard: {
2015 if input.peek(Token![if]) {
2016 let if_token: Token![if] = input.parse()?;
2017 let guard: Expr = input.parse()?;
2018 Some((if_token, Box::new(guard)))
2019 } else {
2020 None
2021 }
2022 },
2023 fat_arrow_token: input.parse()?,
2024 body: {
2025 let body = input.call(expr_early)?;
David Tolnaye532d6b2018-08-30 16:55:01 -07002026 requires_comma = requires_terminator(&body);
David Tolnay310b3262018-08-30 15:33:00 -07002027 Box::new(body)
2028 },
2029 comma: {
2030 if requires_comma && !input.is_empty() {
2031 Some(input.parse()?)
2032 } else {
2033 input.parse()?
2034 }
2035 },
2036 })
Alex Crichton954046c2017-05-30 21:49:42 -07002037 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07002038
Michael Layzell734adb42017-06-07 16:58:31 -04002039 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002040 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
David Tolnay60291082018-08-28 09:54:49 -07002041 let asyncness: Option<Token![async]> = input.parse()?;
2042 let movability: Option<Token![static]> = if asyncness.is_none() {
2043 input.parse()?
2044 } else {
2045 None
2046 };
2047 let capture: Option<Token![move]> = input.parse()?;
2048 let or1_token: Token![|] = input.parse()?;
2049
2050 let mut inputs = Punctuated::new();
2051 loop {
2052 if input.peek(Token![|]) {
2053 break;
2054 }
2055 let value = fn_arg(input)?;
2056 inputs.push_value(value);
2057 if input.peek(Token![|]) {
2058 break;
2059 }
2060 let punct: Token![,] = input.parse()?;
2061 inputs.push_punct(punct);
2062 }
2063
2064 let or2_token: Token![|] = input.parse()?;
2065
2066 let (output, body) = if input.peek(Token![->]) {
2067 let arrow_token: Token![->] = input.parse()?;
2068 let ty: Type = input.parse()?;
2069 let body: Block = input.parse()?;
2070 let output = ReturnType::Type(arrow_token, Box::new(ty));
2071 let block = Expr::Block(ExprBlock {
2072 attrs: Vec::new(),
2073 label: None,
2074 block: body,
2075 });
2076 (output, block)
2077 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002078 let body = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002079 (ReturnType::Default, body)
2080 };
2081
2082 Ok(ExprClosure {
David Tolnay310b3262018-08-30 15:33:00 -07002083 attrs: Vec::new(),
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002084 asyncness: asyncness,
2085 movability: movability,
2086 capture: capture,
David Tolnay60291082018-08-28 09:54:49 -07002087 or1_token: or1_token,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002088 inputs: inputs,
David Tolnay60291082018-08-28 09:54:49 -07002089 or2_token: or2_token,
2090 output: output,
2091 body: Box::new(body),
2092 })
David Tolnay02a9c6f2018-08-24 18:58:45 -04002093 }
Yusuke Sasaki851062f2018-08-01 06:28:28 +09002094
2095 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002096 fn expr_async(input: ParseStream) -> Result<ExprAsync> {
2097 Ok(ExprAsync {
2098 attrs: Vec::new(),
2099 async_token: input.parse()?,
2100 capture: input.parse()?,
2101 block: input.parse()?,
2102 })
David Tolnay60291082018-08-28 09:54:49 -07002103 }
Gregory Katz3e562cc2016-09-28 18:33:02 -04002104
Michael Layzell734adb42017-06-07 16:58:31 -04002105 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002106 fn fn_arg(input: ParseStream) -> Result<FnArg> {
2107 let pat: Pat = input.parse()?;
2108
2109 if input.peek(Token![:]) {
2110 Ok(FnArg::Captured(ArgCaptured {
2111 pat: pat,
2112 colon_token: input.parse()?,
2113 ty: input.parse()?,
2114 }))
2115 } else {
2116 Ok(FnArg::Inferred(pat))
2117 }
2118 }
2119
2120 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002121 fn expr_while(input: ParseStream) -> Result<ExprWhile> {
2122 let label: Option<Label> = input.parse()?;
2123 let while_token: Token![while] = input.parse()?;
2124 let cond = expr_no_struct(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002125
David Tolnay310b3262018-08-30 15:33:00 -07002126 let content;
2127 let brace_token = braced!(content in input);
2128 let inner_attrs = content.call(Attribute::parse_inner)?;
2129 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002130
David Tolnay310b3262018-08-30 15:33:00 -07002131 Ok(ExprWhile {
2132 attrs: inner_attrs,
2133 label: label,
2134 while_token: while_token,
2135 cond: Box::new(cond),
2136 body: Block {
2137 brace_token: brace_token,
2138 stmts: stmts,
2139 },
2140 })
Alex Crichton954046c2017-05-30 21:49:42 -07002141 }
2142
Michael Layzell734adb42017-06-07 16:58:31 -04002143 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002144 fn expr_while_let(input: ParseStream) -> Result<ExprWhileLet> {
2145 let label: Option<Label> = input.parse()?;
2146 let while_token: Token![while] = input.parse()?;
2147 let let_token: Token![let] = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002148
David Tolnay310b3262018-08-30 15:33:00 -07002149 let mut pats = Punctuated::new();
2150 let value: Pat = input.parse()?;
2151 pats.push_value(value);
2152 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2153 let punct = input.parse()?;
2154 pats.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002155 let value: Pat = input.parse()?;
2156 pats.push_value(value);
David Tolnay60291082018-08-28 09:54:49 -07002157 }
David Tolnay310b3262018-08-30 15:33:00 -07002158
2159 let eq_token: Token![=] = input.parse()?;
2160 let expr = expr_no_struct(input)?;
2161
2162 let content;
2163 let brace_token = braced!(content in input);
2164 let inner_attrs = content.call(Attribute::parse_inner)?;
2165 let stmts = content.call(Block::parse_within)?;
2166
2167 Ok(ExprWhileLet {
2168 attrs: inner_attrs,
2169 label: label,
2170 while_token: while_token,
2171 let_token: let_token,
2172 pats: pats,
2173 eq_token: eq_token,
2174 expr: Box::new(expr),
2175 body: Block {
2176 brace_token: brace_token,
2177 stmts: stmts,
2178 },
2179 })
David Tolnaybcd498f2017-12-29 12:02:33 -05002180 }
2181
2182 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002183 impl Parse for Label {
2184 fn parse(input: ParseStream) -> Result<Self> {
2185 Ok(Label {
2186 name: input.parse()?,
2187 colon_token: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04002188 })
David Tolnay60291082018-08-28 09:54:49 -07002189 }
Alex Crichton954046c2017-05-30 21:49:42 -07002190 }
2191
Michael Layzell734adb42017-06-07 16:58:31 -04002192 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002193 impl Parse for Option<Label> {
2194 fn parse(input: ParseStream) -> Result<Self> {
2195 if input.peek(Lifetime) {
2196 input.parse().map(Some)
2197 } else {
2198 Ok(None)
2199 }
2200 }
2201 }
2202
2203 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002204 fn expr_continue(input: ParseStream) -> Result<ExprContinue> {
2205 Ok(ExprContinue {
2206 attrs: Vec::new(),
2207 continue_token: input.parse()?,
2208 label: input.parse()?,
2209 })
Alex Crichton954046c2017-05-30 21:49:42 -07002210 }
Gregory Katzfd6935d2016-09-30 22:51:25 -04002211
Michael Layzell734adb42017-06-07 16:58:31 -04002212 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002213 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2214 Ok(ExprBreak {
David Tolnay310b3262018-08-30 15:33:00 -07002215 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002216 break_token: input.parse()?,
2217 label: input.parse()?,
2218 expr: {
2219 if input.is_empty()
2220 || input.peek(Token![,])
2221 || input.peek(Token![;])
2222 || !allow_struct.0 && input.peek(token::Brace)
2223 {
2224 None
2225 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002226 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002227 Some(Box::new(expr))
Michael Layzell92639a52017-06-01 00:07:44 -04002228 }
David Tolnay60291082018-08-28 09:54:49 -07002229 },
2230 })
Alex Crichton954046c2017-05-30 21:49:42 -07002231 }
2232
Michael Layzell734adb42017-06-07 16:58:31 -04002233 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002234 fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
2235 Ok(ExprReturn {
David Tolnay310b3262018-08-30 15:33:00 -07002236 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002237 return_token: input.parse()?,
2238 expr: {
2239 if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
2240 None
2241 } else {
2242 // NOTE: return is greedy and eats blocks after it even when in a
2243 // position where structs are not allowed, such as in if statement
2244 // conditions. For example:
2245 //
2246 // if return { println!("A") } {} // Prints "A"
David Tolnay7d2e1db2018-08-30 11:49:04 -07002247 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002248 Some(Box::new(expr))
2249 }
2250 },
2251 })
2252 }
2253
2254 #[cfg(feature = "full")]
David Tolnay6e1e5052018-08-30 10:21:48 -07002255 fn expr_struct_helper(input: ParseStream, outer_attrs: Vec<Attribute>, path: Path) -> Result<ExprStruct> {
2256 let content;
2257 let brace_token = braced!(content in input);
2258 let inner_attrs = content.call(Attribute::parse_inner)?;
David Tolnay60291082018-08-28 09:54:49 -07002259
David Tolnay6e1e5052018-08-30 10:21:48 -07002260 let mut fields = Punctuated::new();
2261 loop {
2262 let attrs = content.call(Attribute::parse_outer)?;
2263 if content.fork().parse::<Member>().is_err() {
2264 if attrs.is_empty() {
David Tolnay60291082018-08-28 09:54:49 -07002265 break;
David Tolnay6e1e5052018-08-30 10:21:48 -07002266 } else {
2267 return Err(content.error("expected struct field"));
David Tolnay60291082018-08-28 09:54:49 -07002268 }
David Tolnay60291082018-08-28 09:54:49 -07002269 }
2270
David Tolnay6e1e5052018-08-30 10:21:48 -07002271 let member: Member = content.parse()?;
2272 let (colon_token, value) = if content.peek(Token![:]) || !member.is_named() {
2273 let colon_token: Token![:] = content.parse()?;
2274 let value: Expr = content.parse()?;
2275 (Some(colon_token), value)
2276 } else if let Member::Named(ref ident) = member {
2277 let value = Expr::Path(ExprPath {
2278 attrs: Vec::new(),
2279 qself: None,
2280 path: Path::from(ident.clone()),
2281 });
2282 (None, value)
David Tolnay60291082018-08-28 09:54:49 -07002283 } else {
David Tolnay6e1e5052018-08-30 10:21:48 -07002284 unreachable!()
David Tolnay60291082018-08-28 09:54:49 -07002285 };
2286
David Tolnay6e1e5052018-08-30 10:21:48 -07002287 fields.push(FieldValue {
2288 attrs: attrs,
2289 member: member,
2290 colon_token: colon_token,
2291 expr: value,
2292 });
2293
2294 if !content.peek(Token![,]) {
2295 break;
2296 }
2297 let punct: Token![,] = content.parse()?;
2298 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002299 }
David Tolnay6e1e5052018-08-30 10:21:48 -07002300
2301 let (dot2_token, rest) = if fields.empty_or_trailing() && content.peek(Token![..]) {
2302 let dot2_token: Token![..] = content.parse()?;
2303 let rest: Expr = content.parse()?;
2304 (Some(dot2_token), Some(Box::new(rest)))
2305 } else {
2306 (None, None)
2307 };
2308
2309 Ok(ExprStruct {
2310 attrs: {
2311 let mut attrs = outer_attrs;
2312 attrs.extend(inner_attrs);
2313 attrs
2314 },
2315 brace_token: brace_token,
2316 path: path,
2317 fields: fields,
2318 dot2_token: dot2_token,
2319 rest: rest,
2320 })
Alex Crichton954046c2017-05-30 21:49:42 -07002321 }
David Tolnay055a7042016-10-02 19:23:54 -07002322
Michael Layzell734adb42017-06-07 16:58:31 -04002323 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002324 fn expr_unsafe(input: ParseStream) -> Result<ExprUnsafe> {
2325 let unsafe_token: Token![unsafe] = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002326
David Tolnay310b3262018-08-30 15:33:00 -07002327 let content;
2328 let brace_token = braced!(content in input);
2329 let inner_attrs = content.call(Attribute::parse_inner)?;
2330 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002331
David Tolnay310b3262018-08-30 15:33:00 -07002332 Ok(ExprUnsafe {
2333 attrs: inner_attrs,
2334 unsafe_token: unsafe_token,
2335 block: Block {
2336 brace_token: brace_token,
2337 stmts: stmts,
2338 },
2339 })
Alex Crichton954046c2017-05-30 21:49:42 -07002340 }
David Tolnay055a7042016-10-02 19:23:54 -07002341
Michael Layzell734adb42017-06-07 16:58:31 -04002342 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002343 pub fn expr_block(input: ParseStream) -> Result<ExprBlock> {
2344 let label: Option<Label> = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002345
David Tolnay310b3262018-08-30 15:33:00 -07002346 let content;
2347 let brace_token = braced!(content in input);
2348 let inner_attrs = content.call(Attribute::parse_inner)?;
2349 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002350
David Tolnay310b3262018-08-30 15:33:00 -07002351 Ok(ExprBlock {
2352 attrs: inner_attrs,
2353 label: label,
2354 block: Block {
2355 brace_token: brace_token,
2356 stmts: stmts,
2357 },
2358 })
Alex Crichton954046c2017-05-30 21:49:42 -07002359 }
David Tolnay89e05672016-10-02 14:39:42 -07002360
Michael Layzell734adb42017-06-07 16:58:31 -04002361 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002362 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2363 Ok(ExprRange {
David Tolnay8c91b882017-12-28 23:04:32 -05002364 attrs: Vec::new(),
2365 from: None,
David Tolnay60291082018-08-28 09:54:49 -07002366 limits: input.parse()?,
2367 to: {
2368 if input.is_empty()
2369 || input.peek(Token![,])
2370 || input.peek(Token![;])
2371 || !allow_struct.0 && input.peek(token::Brace)
2372 {
2373 None
2374 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002375 let to = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002376 Some(Box::new(to))
2377 }
2378 },
2379 })
2380 }
David Tolnay438c9052016-10-07 23:24:48 -07002381
Michael Layzell734adb42017-06-07 16:58:31 -04002382 #[cfg(feature = "full")]
David Tolnayc4c631e2018-08-27 10:44:37 -07002383 impl Parse for RangeLimits {
2384 fn parse(input: ParseStream) -> Result<Self> {
2385 let lookahead = input.lookahead1();
2386 if lookahead.peek(Token![..=]) {
2387 input.parse().map(RangeLimits::Closed)
2388 } else if lookahead.peek(Token![...]) {
2389 let dot3: Token![...] = input.parse()?;
2390 Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2391 } else if lookahead.peek(Token![..]) {
2392 input.parse().map(RangeLimits::HalfOpen)
2393 } else {
2394 Err(lookahead.error())
2395 }
2396 }
Alex Crichton954046c2017-05-30 21:49:42 -07002397 }
David Tolnay438c9052016-10-07 23:24:48 -07002398
David Tolnay60291082018-08-28 09:54:49 -07002399 impl Parse for ExprPath {
2400 fn parse(input: ParseStream) -> Result<Self> {
2401 #[cfg(not(feature = "full"))]
2402 let attrs = Vec::new();
2403 #[cfg(feature = "full")]
2404 let attrs = input.call(Attribute::parse_outer)?;
David Tolnayeb981bb2018-07-21 19:31:38 -07002405
David Tolnay60291082018-08-28 09:54:49 -07002406 let (qself, path) = path::parsing::qpath(input, true)?;
2407
2408 Ok(ExprPath {
David Tolnay73c9b522018-07-21 15:58:40 -07002409 attrs: attrs,
David Tolnay60291082018-08-28 09:54:49 -07002410 qself: qself,
2411 path: path,
Michael Layzell92639a52017-06-01 00:07:44 -04002412 })
David Tolnay60291082018-08-28 09:54:49 -07002413 }
Alex Crichton954046c2017-05-30 21:49:42 -07002414 }
David Tolnay42602292016-10-01 22:25:45 -07002415
Michael Layzell734adb42017-06-07 16:58:31 -04002416 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002417 impl Parse for Block {
2418 fn parse(input: ParseStream) -> Result<Self> {
2419 let content;
2420 Ok(Block {
2421 brace_token: braced!(content in input),
2422 stmts: content.call(Block::parse_within)?,
Michael Layzell92639a52017-06-01 00:07:44 -04002423 })
David Tolnay60291082018-08-28 09:54:49 -07002424 }
Alex Crichton954046c2017-05-30 21:49:42 -07002425 }
David Tolnay939766a2016-09-23 23:48:12 -07002426
Michael Layzell734adb42017-06-07 16:58:31 -04002427 #[cfg(feature = "full")]
Alex Crichton954046c2017-05-30 21:49:42 -07002428 impl Block {
David Tolnay9389c382018-08-27 09:13:37 -07002429 pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002430 let mut stmts = Vec::new();
David Tolnay7158c5f2018-08-30 17:28:34 -07002431 loop {
2432 while input.peek(Token![;]) {
2433 input.parse::<Token![;]>()?;
Michael Layzell92639a52017-06-01 00:07:44 -04002434 }
David Tolnay7158c5f2018-08-30 17:28:34 -07002435 if input.is_empty() {
2436 break;
2437 }
2438 let s = parse_stmt(input, true)?;
2439 let requires_semicolon = if let Stmt::Expr(ref s) = s {
2440 requires_terminator(s)
2441 } else {
2442 false
2443 };
David Tolnaye532d6b2018-08-30 16:55:01 -07002444 stmts.push(s);
David Tolnay7158c5f2018-08-30 17:28:34 -07002445 if input.is_empty() {
2446 break;
2447 } else if requires_semicolon {
2448 return Err(input.error("unexpected token"));
2449 }
David Tolnaye532d6b2018-08-30 16:55:01 -07002450 }
2451 Ok(stmts)
2452 }
Alex Crichton954046c2017-05-30 21:49:42 -07002453 }
2454
Michael Layzell734adb42017-06-07 16:58:31 -04002455 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002456 impl Parse for Stmt {
2457 fn parse(input: ParseStream) -> Result<Self> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002458 parse_stmt(input, false)
2459 }
2460 }
David Tolnay939766a2016-09-23 23:48:12 -07002461
David Tolnaye532d6b2018-08-30 16:55:01 -07002462 #[cfg(feature = "full")]
2463 fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
2464 let ahead = input.fork();
2465 ahead.call(Attribute::parse_outer)?;
2466
2467 // TODO: better error messages
2468 if {
2469 let ahead = ahead.fork();
2470 // Only parse braces here; paren and bracket will get parsed as
2471 // expression statements
2472 ahead.call(Path::parse_mod_style).is_ok()
2473 && ahead.parse::<Token![!]>().is_ok()
2474 && (ahead.peek(token::Brace) || ahead.peek(Ident))
2475 } {
2476 stmt_mac(input)
2477 } else if ahead.peek(Token![let]) {
2478 stmt_local(input).map(Stmt::Local)
2479 } else if ahead.peek(Token![pub])
2480 || ahead.peek(Token![crate]) && !ahead.peek2(Token![::])
2481 || ahead.peek(Token![extern]) && !ahead.peek2(Token![::])
2482 || ahead.peek(Token![use])
2483 || ahead.peek(Token![static]) && (ahead.peek2(Token![mut]) || ahead.peek2(Ident))
2484 || ahead.peek(Token![const])
2485 || ahead.peek(Token![unsafe]) && !ahead.peek2(token::Brace)
2486 || ahead.peek(Token![async]) && (ahead.peek2(Token![extern]) || ahead.peek2(Token![fn]))
2487 || ahead.peek(Token![fn])
2488 || ahead.peek(Token![mod])
2489 || ahead.peek(Token![type])
2490 || ahead.peek(Token![existential]) && ahead.peek2(Token![type])
2491 || ahead.peek(Token![struct])
2492 || ahead.peek(Token![enum])
2493 || ahead.peek(Token![union]) && ahead.peek2(Ident)
2494 || ahead.peek(Token![auto]) && ahead.peek2(Token![trait])
2495 || ahead.peek(Token![trait])
2496 || ahead.peek(Token![default]) && (ahead.peek2(Token![unsafe]) || ahead.peek2(Token![impl]))
2497 || ahead.peek(Token![impl])
2498 || ahead.peek(Token![macro])
2499 {
2500 input.parse().map(Stmt::Item)
2501 } else {
2502 stmt_expr(input, allow_nosemi)
David Tolnay60291082018-08-28 09:54:49 -07002503 }
Alex Crichton954046c2017-05-30 21:49:42 -07002504 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07002505
Michael Layzell734adb42017-06-07 16:58:31 -04002506 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002507 fn stmt_mac(input: ParseStream) -> Result<Stmt> {
2508 let attrs = input.call(Attribute::parse_outer)?;
2509 let path = input.call(Path::parse_mod_style)?;
2510 let bang_token: Token![!] = input.parse()?;
2511 let ident: Option<Ident> = input.parse()?;
2512 let (delimiter, tts) = mac::parse_delimiter(input)?;
2513 let semi_token: Option<Token![;]> = input.parse()?;
2514
2515 Ok(Stmt::Item(Item::Macro(ItemMacro {
2516 attrs: attrs,
2517 ident: ident,
2518 mac: Macro {
2519 path: path,
2520 bang_token: bang_token,
2521 delimiter: delimiter,
2522 tts: tts,
2523 },
2524 semi_token: semi_token,
2525 })))
Alex Crichton954046c2017-05-30 21:49:42 -07002526 }
David Tolnay84aa0752016-10-02 23:01:13 -07002527
Michael Layzell734adb42017-06-07 16:58:31 -04002528 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002529 fn stmt_local(input: ParseStream) -> Result<Local> {
2530 Ok(Local {
2531 attrs: input.call(Attribute::parse_outer)?,
2532 let_token: input.parse()?,
2533 pats: {
2534 let mut pats = Punctuated::new();
2535 let value: Pat = input.parse()?;
2536 pats.push_value(value);
2537 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2538 let punct = input.parse()?;
2539 pats.push_punct(punct);
2540 let value: Pat = input.parse()?;
2541 pats.push_value(value);
2542 }
2543 pats
2544 },
2545 ty: {
2546 if input.peek(Token![:]) {
2547 let colon_token: Token![:] = input.parse()?;
2548 let ty: Type = input.parse()?;
2549 Some((colon_token, Box::new(ty)))
2550 } else {
2551 None
2552 }
2553 },
2554 init: {
2555 if input.peek(Token![=]) {
2556 let eq_token: Token![=] = input.parse()?;
2557 let init: Expr = input.parse()?;
2558 Some((eq_token, Box::new(init)))
2559 } else {
2560 None
2561 }
2562 },
2563 semi_token: input.parse()?,
2564 })
2565 }
2566
2567 #[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -07002568 fn stmt_expr(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
David Tolnay60291082018-08-28 09:54:49 -07002569 let mut attrs = input.call(Attribute::parse_outer)?;
David Tolnay01218d12018-08-29 18:13:07 -07002570 let mut e = expr_early(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002571
2572 attrs.extend(e.replace_attrs(Vec::new()));
2573 e.replace_attrs(attrs);
2574
2575 if input.peek(Token![;]) {
David Tolnay01218d12018-08-29 18:13:07 -07002576 return Ok(Stmt::Semi(e, input.parse()?));
David Tolnay60291082018-08-28 09:54:49 -07002577 }
David Tolnay60291082018-08-28 09:54:49 -07002578
David Tolnayf00a2762018-08-30 17:22:22 -07002579 if allow_nosemi || !requires_terminator(&e) {
David Tolnaye532d6b2018-08-30 16:55:01 -07002580 Ok(Stmt::Expr(e))
2581 } else {
2582 Err(input.error("expected semicolon"))
David Tolnay01218d12018-08-29 18:13:07 -07002583 }
David Tolnay60291082018-08-28 09:54:49 -07002584 }
2585
2586 #[cfg(feature = "full")]
2587 impl Parse for Pat {
2588 fn parse(input: ParseStream) -> Result<Self> {
2589 // TODO: better error messages
2590 let lookahead = input.lookahead1();
2591 if lookahead.peek(Token![_]) {
David Tolnay310b3262018-08-30 15:33:00 -07002592 input.call(pat_wild).map(Pat::Wild)
David Tolnay60291082018-08-28 09:54:49 -07002593 } else if lookahead.peek(Token![box]) {
David Tolnay310b3262018-08-30 15:33:00 -07002594 input.call(pat_box).map(Pat::Box)
2595 } else if input.fork().call(pat_range).is_ok() {
David Tolnay60291082018-08-28 09:54:49 -07002596 // must be before Pat::Lit
David Tolnay310b3262018-08-30 15:33:00 -07002597 input.call(pat_range).map(Pat::Range)
2598 } else if input.fork().call(pat_tuple_struct).is_ok() {
David Tolnay60291082018-08-28 09:54:49 -07002599 // must be before Pat::Ident
David Tolnay310b3262018-08-30 15:33:00 -07002600 input.call(pat_tuple_struct).map(Pat::TupleStruct)
2601 } else if input.fork().call(pat_struct).is_ok() {
David Tolnay60291082018-08-28 09:54:49 -07002602 // must be before Pat::Ident
David Tolnay310b3262018-08-30 15:33:00 -07002603 input.call(pat_struct).map(Pat::Struct)
2604 } else if input.fork().call(pat_macro).is_ok() {
David Tolnay60291082018-08-28 09:54:49 -07002605 // must be before Pat::Ident
David Tolnay310b3262018-08-30 15:33:00 -07002606 input.call(pat_macro).map(Pat::Macro)
2607 } else if input.fork().call(pat_lit).is_ok() {
David Tolnay60291082018-08-28 09:54:49 -07002608 // must be before Pat::Ident
David Tolnay310b3262018-08-30 15:33:00 -07002609 input.call(pat_lit).map(Pat::Lit)
2610 } else if input.fork().call(pat_ident).is_ok() {
2611 input.call(pat_ident).map(Pat::Ident)
2612 } else if input.fork().call(pat_path).is_ok() {
2613 input.call(pat_path).map(Pat::Path)
David Tolnay60291082018-08-28 09:54:49 -07002614 } else if lookahead.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07002615 input.call(pat_tuple).map(Pat::Tuple)
David Tolnay60291082018-08-28 09:54:49 -07002616 } else if lookahead.peek(Token![&]) {
David Tolnay310b3262018-08-30 15:33:00 -07002617 input.call(pat_ref).map(Pat::Ref)
David Tolnay60291082018-08-28 09:54:49 -07002618 } else if lookahead.peek(token::Bracket) {
David Tolnay310b3262018-08-30 15:33:00 -07002619 input.call(pat_slice).map(Pat::Slice)
David Tolnay60291082018-08-28 09:54:49 -07002620 } else {
2621 Err(lookahead.error())
2622 }
2623 }
2624 }
2625
2626 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002627 fn pat_wild(input: ParseStream) -> Result<PatWild> {
2628 Ok(PatWild {
2629 underscore_token: input.parse()?,
2630 })
Alex Crichton954046c2017-05-30 21:49:42 -07002631 }
2632
Michael Layzell734adb42017-06-07 16:58:31 -04002633 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002634 fn pat_box(input: ParseStream) -> Result<PatBox> {
2635 Ok(PatBox {
2636 box_token: input.parse()?,
2637 pat: input.parse()?,
2638 })
David Tolnay60291082018-08-28 09:54:49 -07002639 }
2640
2641 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002642 fn pat_ident(input: ParseStream) -> Result<PatIdent> {
2643 Ok(PatIdent {
2644 by_ref: input.parse()?,
2645 mutability: input.parse()?,
2646 ident: {
2647 let ident = if input.peek(Ident) || input.peek(Token![self]) {
David Tolnay0dea1b92018-08-30 17:47:29 -07002648 input.call(Ident::parse_any)?
David Tolnay310b3262018-08-30 15:33:00 -07002649 } else {
2650 return Err(input.error("expected identifier or `self`"));
2651 };
2652 if input.peek(Token![<]) || input.peek(Token![::]) {
2653 return Err(input.error("unexpected token"));
David Tolnay60291082018-08-28 09:54:49 -07002654 }
David Tolnay310b3262018-08-30 15:33:00 -07002655 ident
2656 },
2657 subpat: {
2658 if input.peek(Token![@]) {
2659 let at_token: Token![@] = input.parse()?;
2660 let subpat: Pat = input.parse()?;
2661 Some((at_token, Box::new(subpat)))
2662 } else {
2663 None
2664 }
2665 },
2666 })
David Tolnay60291082018-08-28 09:54:49 -07002667 }
2668
2669 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002670 fn pat_tuple_struct(input: ParseStream) -> Result<PatTupleStruct> {
2671 Ok(PatTupleStruct {
2672 path: input.parse()?,
2673 pat: input.call(pat_tuple)?,
2674 })
2675 }
David Tolnay60291082018-08-28 09:54:49 -07002676
David Tolnay310b3262018-08-30 15:33:00 -07002677 #[cfg(feature = "full")]
2678 fn pat_struct(input: ParseStream) -> Result<PatStruct> {
2679 let path: Path = input.parse()?;
2680
2681 let content;
2682 let brace_token = braced!(content in input);
2683
2684 let mut fields = Punctuated::new();
2685 while !content.is_empty() && !content.peek(Token![..]) {
2686 let value = content.call(field_pat)?;
2687 fields.push_value(value);
2688 if !content.peek(Token![,]) {
2689 break;
David Tolnay60291082018-08-28 09:54:49 -07002690 }
David Tolnay310b3262018-08-30 15:33:00 -07002691 let punct: Token![,] = content.parse()?;
2692 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002693 }
David Tolnay310b3262018-08-30 15:33:00 -07002694
2695 let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) {
2696 Some(content.parse()?)
2697 } else {
2698 None
2699 };
2700
2701 Ok(PatStruct {
2702 path: path,
2703 brace_token: brace_token,
2704 fields: fields,
2705 dot2_token: dot2_token,
2706 })
2707 }
2708
2709 #[cfg(feature = "full")]
2710 fn field_pat(input: ParseStream) -> Result<FieldPat> {
2711 let boxed: Option<Token![box]> = input.parse()?;
2712 let by_ref: Option<Token![ref]> = input.parse()?;
2713 let mutability: Option<Token![mut]> = input.parse()?;
2714 let member: Member = input.parse()?;
2715
2716 if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
2717 || member.is_unnamed()
2718 {
2719 return Ok(FieldPat {
2720 attrs: Vec::new(),
2721 member: member,
2722 colon_token: input.parse()?,
2723 pat: input.parse()?,
2724 });
2725 }
2726
2727 let ident = match member {
2728 Member::Named(ident) => ident,
2729 Member::Unnamed(_) => unreachable!(),
2730 };
2731
2732 let mut pat = Pat::Ident(PatIdent {
2733 by_ref: by_ref,
2734 mutability: mutability,
2735 ident: ident.clone(),
2736 subpat: None,
2737 });
2738
2739 if let Some(boxed) = boxed {
2740 pat = Pat::Box(PatBox {
2741 pat: Box::new(pat),
2742 box_token: boxed,
2743 });
2744 }
2745
2746 Ok(FieldPat {
2747 member: Member::Named(ident),
2748 pat: Box::new(pat),
2749 attrs: Vec::new(),
2750 colon_token: None,
2751 })
Alex Crichton954046c2017-05-30 21:49:42 -07002752 }
2753
David Tolnay1501f7e2018-08-27 14:21:03 -07002754 impl Parse for Member {
2755 fn parse(input: ParseStream) -> Result<Self> {
2756 if input.peek(Ident) {
2757 input.parse().map(Member::Named)
2758 } else if input.peek(LitInt) {
2759 input.parse().map(Member::Unnamed)
2760 } else {
2761 Err(input.error("expected identifier or integer"))
2762 }
2763 }
David Tolnay85b69a42017-12-27 20:43:10 -05002764 }
2765
David Tolnay1501f7e2018-08-27 14:21:03 -07002766 impl Parse for Index {
2767 fn parse(input: ParseStream) -> Result<Self> {
2768 let lit: LitInt = input.parse()?;
2769 if let IntSuffix::None = lit.suffix() {
2770 Ok(Index {
2771 index: lit.value() as u32,
2772 span: lit.span(),
2773 })
2774 } else {
2775 Err(input.error("expected unsuffixed integer"))
2776 }
2777 }
David Tolnay85b69a42017-12-27 20:43:10 -05002778 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07002779
Michael Layzell734adb42017-06-07 16:58:31 -04002780 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002781 fn pat_path(input: ParseStream) -> Result<PatPath> {
2782 let p: ExprPath = input.parse()?;
2783 Ok(PatPath {
2784 qself: p.qself,
2785 path: p.path,
2786 })
Alex Crichton954046c2017-05-30 21:49:42 -07002787 }
David Tolnay9636c052016-10-02 17:11:17 -07002788
Michael Layzell734adb42017-06-07 16:58:31 -04002789 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002790 fn pat_tuple(input: ParseStream) -> Result<PatTuple> {
2791 let content;
2792 let paren_token = parenthesized!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002793
David Tolnay310b3262018-08-30 15:33:00 -07002794 let mut front = Punctuated::new();
2795 let mut dot2_token = None::<Token![..]>;
2796 let mut comma_token = None::<Token![,]>;
2797 loop {
2798 if content.is_empty() {
2799 break;
David Tolnay60291082018-08-28 09:54:49 -07002800 }
David Tolnay310b3262018-08-30 15:33:00 -07002801 if content.peek(Token![..]) {
2802 dot2_token = Some(content.parse()?);
2803 comma_token = content.parse()?;
2804 break;
David Tolnay60291082018-08-28 09:54:49 -07002805 }
David Tolnay310b3262018-08-30 15:33:00 -07002806 let value: Pat = content.parse()?;
2807 front.push_value(value);
2808 if content.is_empty() {
2809 break;
2810 }
2811 let punct = content.parse()?;
2812 front.push_punct(punct);
2813 }
2814
David Tolnayf5ebc192018-08-30 18:23:46 -07002815 let mut back = Punctuated::new();
2816 while !content.is_empty() {
2817 let value: Pat = content.parse()?;
2818 back.push_value(value);
2819 if content.is_empty() {
2820 break;
2821 }
2822 let punct = content.parse()?;
2823 back.push_punct(punct);
2824 }
David Tolnay310b3262018-08-30 15:33:00 -07002825
2826 Ok(PatTuple {
2827 paren_token: paren_token,
2828 front: front,
2829 dot2_token: dot2_token,
2830 comma_token: comma_token,
2831 back: back,
2832 })
2833 }
2834
2835 #[cfg(feature = "full")]
2836 fn pat_ref(input: ParseStream) -> Result<PatRef> {
2837 Ok(PatRef {
2838 and_token: input.parse()?,
2839 mutability: input.parse()?,
2840 pat: input.parse()?,
2841 })
2842 }
2843
2844 #[cfg(feature = "full")]
2845 fn pat_lit(input: ParseStream) -> Result<PatLit> {
2846 if input.peek(Lit) || input.peek(Token![-]) && input.peek2(Lit) {
2847 Ok(PatLit {
2848 expr: input.call(pat_lit_expr)?,
2849 })
2850 } else {
2851 Err(input.error("expected literal pattern"))
David Tolnay60291082018-08-28 09:54:49 -07002852 }
2853 }
2854
2855 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002856 fn pat_range(input: ParseStream) -> Result<PatRange> {
2857 Ok(PatRange {
2858 lo: input.call(pat_lit_expr)?,
2859 limits: input.parse()?,
2860 hi: input.call(pat_lit_expr)?,
2861 })
David Tolnay60291082018-08-28 09:54:49 -07002862 }
2863
2864 #[cfg(feature = "full")]
2865 fn pat_lit_expr(input: ParseStream) -> Result<Box<Expr>> {
2866 let neg: Option<Token![-]> = input.parse()?;
2867
2868 let lookahead = input.lookahead1();
2869 let expr = if lookahead.peek(Lit) {
David Tolnay310b3262018-08-30 15:33:00 -07002870 Expr::Lit(input.call(expr_lit)?)
David Tolnay60291082018-08-28 09:54:49 -07002871 } else if lookahead.peek(Ident)
2872 || lookahead.peek(Token![::])
2873 || lookahead.peek(Token![<])
2874 || lookahead.peek(Token![self])
2875 || lookahead.peek(Token![Self])
2876 || lookahead.peek(Token![super])
2877 || lookahead.peek(Token![extern])
2878 || lookahead.peek(Token![crate])
2879 {
2880 Expr::Path(input.parse()?)
2881 } else {
2882 return Err(lookahead.error());
2883 };
2884
2885 Ok(Box::new(if let Some(neg) = neg {
David Tolnay8c91b882017-12-28 23:04:32 -05002886 Expr::Unary(ExprUnary {
2887 attrs: Vec::new(),
David Tolnayc29b9892017-12-27 22:58:14 -05002888 op: UnOp::Neg(neg),
David Tolnay60291082018-08-28 09:54:49 -07002889 expr: Box::new(expr),
David Tolnay3bc597f2017-12-31 02:31:11 -05002890 })
David Tolnay0ad9e9f2016-10-29 22:20:02 -07002891 } else {
David Tolnay60291082018-08-28 09:54:49 -07002892 expr
2893 }))
Alex Crichton954046c2017-05-30 21:49:42 -07002894 }
David Tolnay323279a2017-12-29 11:26:32 -05002895
2896 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002897 fn pat_slice(input: ParseStream) -> Result<PatSlice> {
2898 let content;
2899 let bracket_token = bracketed!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002900
David Tolnay310b3262018-08-30 15:33:00 -07002901 let mut front = Punctuated::new();
2902 let mut middle = None;
2903 loop {
2904 if content.is_empty() || content.peek(Token![..]) {
2905 break;
David Tolnay60291082018-08-28 09:54:49 -07002906 }
David Tolnay310b3262018-08-30 15:33:00 -07002907 let value: Pat = content.parse()?;
2908 if content.peek(Token![..]) {
2909 middle = Some(Box::new(value));
2910 break;
David Tolnay60291082018-08-28 09:54:49 -07002911 }
David Tolnay310b3262018-08-30 15:33:00 -07002912 front.push_value(value);
2913 if content.is_empty() {
2914 break;
2915 }
2916 let punct = content.parse()?;
2917 front.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002918 }
David Tolnay310b3262018-08-30 15:33:00 -07002919
2920 let dot2_token: Option<Token![..]> = content.parse()?;
2921 let mut comma_token = None::<Token![,]>;
2922 let mut back = Punctuated::new();
2923 if dot2_token.is_some() {
2924 comma_token = content.parse()?;
2925 if comma_token.is_some() {
2926 loop {
2927 if content.is_empty() {
2928 break;
2929 }
2930 let value: Pat = content.parse()?;
2931 back.push_value(value);
2932 if content.is_empty() {
2933 break;
2934 }
2935 let punct = content.parse()?;
2936 back.push_punct(punct);
2937 }
2938 }
2939 }
2940
2941 Ok(PatSlice {
2942 bracket_token: bracket_token,
2943 front: front,
2944 middle: middle,
2945 dot2_token: dot2_token,
2946 comma_token: comma_token,
2947 back: back,
2948 })
David Tolnay60291082018-08-28 09:54:49 -07002949 }
2950
2951 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002952 fn pat_macro(input: ParseStream) -> Result<PatMacro> {
2953 Ok(PatMacro {
2954 mac: input.parse()?,
2955 })
David Tolnay323279a2017-12-29 11:26:32 -05002956 }
David Tolnay1501f7e2018-08-27 14:21:03 -07002957
2958 #[cfg(feature = "full")]
2959 impl Member {
2960 fn is_named(&self) -> bool {
2961 match *self {
2962 Member::Named(_) => true,
2963 Member::Unnamed(_) => false,
2964 }
2965 }
David Tolnay60291082018-08-28 09:54:49 -07002966
2967 fn is_unnamed(&self) -> bool {
2968 match *self {
2969 Member::Named(_) => false,
2970 Member::Unnamed(_) => true,
2971 }
2972 }
David Tolnay1501f7e2018-08-27 14:21:03 -07002973 }
David Tolnayb9c8e322016-09-23 20:48:37 -07002974}
2975
David Tolnayf4bbbd92016-09-23 14:41:55 -07002976#[cfg(feature = "printing")]
2977mod printing {
2978 use super::*;
Michael Layzell734adb42017-06-07 16:58:31 -04002979 #[cfg(feature = "full")]
David Tolnay13b3d352016-10-03 00:31:15 -07002980 use attr::FilterAttrs;
Alex Crichtona74a1c82018-05-16 10:20:44 -07002981 use proc_macro2::{Literal, TokenStream};
2982 use quote::{ToTokens, TokenStreamExt};
David Tolnayf4bbbd92016-09-23 14:41:55 -07002983
David Tolnaybcf26022017-12-25 22:10:52 -05002984 // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
David Tolnayb6a0e7d2018-05-20 22:06:47 -07002985 // before appending it to `TokenStream`.
Michael Layzell3936ceb2017-07-08 00:28:36 -04002986 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07002987 fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) {
David Tolnay8c91b882017-12-28 23:04:32 -05002988 if let Expr::Struct(_) = *e {
David Tolnay32954ef2017-12-26 22:43:16 -05002989 token::Paren::default().surround(tokens, |tokens| {
Michael Layzell3936ceb2017-07-08 00:28:36 -04002990 e.to_tokens(tokens);
2991 });
2992 } else {
2993 e.to_tokens(tokens);
2994 }
2995 }
2996
David Tolnay8c91b882017-12-28 23:04:32 -05002997 #[cfg(feature = "full")]
David Tolnayd997aef2018-07-21 18:42:31 -07002998 fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
David Tolnay8c91b882017-12-28 23:04:32 -05002999 tokens.append_all(attrs.outer());
3000 }
Michael Layzell734adb42017-06-07 16:58:31 -04003001
David Tolnayd997aef2018-07-21 18:42:31 -07003002 #[cfg(feature = "full")]
3003 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3004 tokens.append_all(attrs.inner());
3005 }
3006
David Tolnay8c91b882017-12-28 23:04:32 -05003007 #[cfg(not(feature = "full"))]
David Tolnayd997aef2018-07-21 18:42:31 -07003008 fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3009
3010 #[cfg(not(feature = "full"))]
3011 fn inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
Alex Crichton62a0a592017-05-22 13:58:53 -07003012
Michael Layzell734adb42017-06-07 16:58:31 -04003013 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003014 impl ToTokens for ExprBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003015 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003016 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003017 self.box_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003018 self.expr.to_tokens(tokens);
3019 }
3020 }
3021
Michael Layzell734adb42017-06-07 16:58:31 -04003022 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003023 impl ToTokens for ExprInPlace {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003024 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003025 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8701a5c2017-12-28 23:31:10 -05003026 self.place.to_tokens(tokens);
3027 self.arrow_token.to_tokens(tokens);
3028 self.value.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003029 }
3030 }
3031
Michael Layzell734adb42017-06-07 16:58:31 -04003032 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003033 impl ToTokens for ExprArray {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003034 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003035 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003036 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003037 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003038 self.elems.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003039 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003040 }
3041 }
3042
3043 impl ToTokens for ExprCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003044 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003045 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003046 self.func.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003047 self.paren_token.surround(tokens, |tokens| {
3048 self.args.to_tokens(tokens);
3049 })
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 ExprMethodCall {
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);
David Tolnay76418512017-12-28 23:47:47 -05003057 self.receiver.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003058 self.dot_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003059 self.method.to_tokens(tokens);
David Tolnayd60cfec2017-12-29 00:21:38 -05003060 self.turbofish.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003061 self.paren_token.surround(tokens, |tokens| {
3062 self.args.to_tokens(tokens);
3063 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003064 }
3065 }
3066
Michael Layzell734adb42017-06-07 16:58:31 -04003067 #[cfg(feature = "full")]
David Tolnayd60cfec2017-12-29 00:21:38 -05003068 impl ToTokens for MethodTurbofish {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003069 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003070 self.colon2_token.to_tokens(tokens);
3071 self.lt_token.to_tokens(tokens);
3072 self.args.to_tokens(tokens);
3073 self.gt_token.to_tokens(tokens);
3074 }
3075 }
3076
3077 #[cfg(feature = "full")]
3078 impl ToTokens for GenericMethodArgument {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003079 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003080 match *self {
3081 GenericMethodArgument::Type(ref t) => t.to_tokens(tokens),
3082 GenericMethodArgument::Const(ref c) => c.to_tokens(tokens),
3083 }
3084 }
3085 }
3086
3087 #[cfg(feature = "full")]
David Tolnay05362582017-12-26 01:33:57 -05003088 impl ToTokens for ExprTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003089 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003090 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003091 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003092 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003093 self.elems.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003094 // If we only have one argument, we need a trailing comma to
David Tolnay05362582017-12-26 01:33:57 -05003095 // distinguish ExprTuple from ExprParen.
David Tolnaya0834b42018-01-01 21:30:02 -08003096 if self.elems.len() == 1 && !self.elems.trailing_punct() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003097 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003098 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003099 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003100 }
3101 }
3102
3103 impl ToTokens for ExprBinary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003104 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003105 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003106 self.left.to_tokens(tokens);
3107 self.op.to_tokens(tokens);
3108 self.right.to_tokens(tokens);
3109 }
3110 }
3111
3112 impl ToTokens for ExprUnary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003113 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003114 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003115 self.op.to_tokens(tokens);
3116 self.expr.to_tokens(tokens);
3117 }
3118 }
3119
David Tolnay8c91b882017-12-28 23:04:32 -05003120 impl ToTokens for ExprLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003121 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003122 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003123 self.lit.to_tokens(tokens);
3124 }
3125 }
3126
Alex Crichton62a0a592017-05-22 13:58:53 -07003127 impl ToTokens for ExprCast {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003128 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003129 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003130 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003131 self.as_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003132 self.ty.to_tokens(tokens);
3133 }
3134 }
3135
David Tolnay0cf94f22017-12-28 23:46:26 -05003136 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003137 impl ToTokens for ExprType {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003138 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003139 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003140 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003141 self.colon_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003142 self.ty.to_tokens(tokens);
3143 }
3144 }
3145
Michael Layzell734adb42017-06-07 16:58:31 -04003146 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003147 fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>) {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003148 if let Some((ref else_token, ref else_)) = *else_ {
3149 else_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003150
3151 // If we are not one of the valid expressions to exist in an else
3152 // clause, wrap ourselves in a block.
David Tolnay2ccf32a2017-12-29 00:34:26 -05003153 match **else_ {
David Tolnay8c91b882017-12-28 23:04:32 -05003154 Expr::If(_) | Expr::IfLet(_) | Expr::Block(_) => {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003155 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003156 }
3157 _ => {
David Tolnay32954ef2017-12-26 22:43:16 -05003158 token::Brace::default().surround(tokens, |tokens| {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003159 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003160 });
3161 }
3162 }
3163 }
3164 }
3165
3166 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003167 impl ToTokens for ExprIf {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003168 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003169 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003170 self.if_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003171 wrap_bare_struct(tokens, &self.cond);
David Tolnay2ccf32a2017-12-29 00:34:26 -05003172 self.then_branch.to_tokens(tokens);
3173 maybe_wrap_else(tokens, &self.else_branch);
Alex Crichton62a0a592017-05-22 13:58:53 -07003174 }
3175 }
3176
Michael Layzell734adb42017-06-07 16:58:31 -04003177 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003178 impl ToTokens for ExprIfLet {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003179 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003180 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003181 self.if_token.to_tokens(tokens);
3182 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003183 self.pats.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003184 self.eq_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003185 wrap_bare_struct(tokens, &self.expr);
David Tolnay2ccf32a2017-12-29 00:34:26 -05003186 self.then_branch.to_tokens(tokens);
3187 maybe_wrap_else(tokens, &self.else_branch);
Alex Crichton62a0a592017-05-22 13:58:53 -07003188 }
3189 }
3190
Michael Layzell734adb42017-06-07 16:58:31 -04003191 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003192 impl ToTokens for ExprWhile {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003193 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003194 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003195 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003196 self.while_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003197 wrap_bare_struct(tokens, &self.cond);
David Tolnay5d314dc2018-07-21 16:40:01 -07003198 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003199 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003200 tokens.append_all(&self.body.stmts);
3201 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003202 }
3203 }
3204
Michael Layzell734adb42017-06-07 16:58:31 -04003205 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003206 impl ToTokens for ExprWhileLet {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003207 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003208 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003209 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003210 self.while_token.to_tokens(tokens);
3211 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003212 self.pats.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003213 self.eq_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003214 wrap_bare_struct(tokens, &self.expr);
David Tolnay5d314dc2018-07-21 16:40:01 -07003215 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003216 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003217 tokens.append_all(&self.body.stmts);
3218 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003219 }
3220 }
3221
Michael Layzell734adb42017-06-07 16:58:31 -04003222 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003223 impl ToTokens for ExprForLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003224 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003225 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003226 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003227 self.for_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003228 self.pat.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003229 self.in_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003230 wrap_bare_struct(tokens, &self.expr);
David Tolnay5d314dc2018-07-21 16:40:01 -07003231 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003232 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003233 tokens.append_all(&self.body.stmts);
3234 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003235 }
3236 }
3237
Michael Layzell734adb42017-06-07 16:58:31 -04003238 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003239 impl ToTokens for ExprLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003240 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003241 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003242 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003243 self.loop_token.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003244 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003245 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003246 tokens.append_all(&self.body.stmts);
3247 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003248 }
3249 }
3250
Michael Layzell734adb42017-06-07 16:58:31 -04003251 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003252 impl ToTokens for ExprMatch {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003253 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003254 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003255 self.match_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003256 wrap_bare_struct(tokens, &self.expr);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003257 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003258 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay51382052017-12-27 13:46:21 -05003259 for (i, arm) in self.arms.iter().enumerate() {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003260 arm.to_tokens(tokens);
3261 // Ensure that we have a comma after a non-block arm, except
3262 // for the last one.
3263 let is_last = i == self.arms.len() - 1;
David Tolnaye532d6b2018-08-30 16:55:01 -07003264 if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003265 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003266 }
3267 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003268 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003269 }
3270 }
3271
Michael Layzell734adb42017-06-07 16:58:31 -04003272 #[cfg(feature = "full")]
David Tolnay02a9c6f2018-08-24 18:58:45 -04003273 impl ToTokens for ExprAsync {
3274 fn to_tokens(&self, tokens: &mut TokenStream) {
3275 outer_attrs_to_tokens(&self.attrs, tokens);
3276 self.async_token.to_tokens(tokens);
3277 self.capture.to_tokens(tokens);
3278 self.block.to_tokens(tokens);
3279 }
3280 }
3281
3282 #[cfg(feature = "full")]
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003283 impl ToTokens for ExprTryBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003284 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003285 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003286 self.try_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003287 self.block.to_tokens(tokens);
3288 }
3289 }
3290
Michael Layzell734adb42017-06-07 16:58:31 -04003291 #[cfg(feature = "full")]
Alex Crichtonfe110462017-06-01 12:49:27 -07003292 impl ToTokens for ExprYield {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003293 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003294 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonfe110462017-06-01 12:49:27 -07003295 self.yield_token.to_tokens(tokens);
3296 self.expr.to_tokens(tokens);
3297 }
3298 }
3299
3300 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003301 impl ToTokens for ExprClosure {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003302 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003303 outer_attrs_to_tokens(&self.attrs, tokens);
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09003304 self.asyncness.to_tokens(tokens);
David Tolnay13d4c0e2018-03-31 20:53:59 +02003305 self.movability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003306 self.capture.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003307 self.or1_token.to_tokens(tokens);
David Tolnay56080682018-01-06 14:01:52 -08003308 for input in self.inputs.pairs() {
3309 match **input.value() {
David Tolnay51382052017-12-27 13:46:21 -05003310 FnArg::Captured(ArgCaptured {
3311 ref pat,
3312 ty: Type::Infer(_),
3313 ..
3314 }) => {
Alex Crichton62a0a592017-05-22 13:58:53 -07003315 pat.to_tokens(tokens);
David Tolnay9636c052016-10-02 17:11:17 -07003316 }
David Tolnay56080682018-01-06 14:01:52 -08003317 _ => input.value().to_tokens(tokens),
David Tolnay3c2467c2016-10-02 17:55:08 -07003318 }
David Tolnayf2cfd722017-12-31 18:02:51 -05003319 input.punct().to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003320 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003321 self.or2_token.to_tokens(tokens);
David Tolnay7f675742017-12-27 22:43:21 -05003322 self.output.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003323 self.body.to_tokens(tokens);
3324 }
3325 }
3326
Michael Layzell734adb42017-06-07 16:58:31 -04003327 #[cfg(feature = "full")]
Nika Layzell640832a2017-12-04 13:37:09 -05003328 impl ToTokens for ExprUnsafe {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003329 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003330 outer_attrs_to_tokens(&self.attrs, tokens);
Nika Layzell640832a2017-12-04 13:37:09 -05003331 self.unsafe_token.to_tokens(tokens);
David Tolnayc4be3512018-08-27 06:25:44 -07003332 self.block.brace_token.surround(tokens, |tokens| {
3333 inner_attrs_to_tokens(&self.attrs, tokens);
3334 tokens.append_all(&self.block.stmts);
3335 });
Nika Layzell640832a2017-12-04 13:37:09 -05003336 }
3337 }
3338
3339 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003340 impl ToTokens for ExprBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003341 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003342 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay1d8e9962018-08-24 19:04:20 -04003343 self.label.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003344 self.block.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003345 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003346 tokens.append_all(&self.block.stmts);
3347 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003348 }
3349 }
3350
Michael Layzell734adb42017-06-07 16:58:31 -04003351 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003352 impl ToTokens for ExprAssign {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003353 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003354 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003355 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003356 self.eq_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003357 self.right.to_tokens(tokens);
3358 }
3359 }
3360
Michael Layzell734adb42017-06-07 16:58:31 -04003361 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003362 impl ToTokens for ExprAssignOp {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003363 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003364 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003365 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003366 self.op.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003367 self.right.to_tokens(tokens);
3368 }
3369 }
3370
3371 impl ToTokens for ExprField {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003372 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003373 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003374 self.base.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003375 self.dot_token.to_tokens(tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003376 self.member.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003377 }
3378 }
3379
David Tolnay85b69a42017-12-27 20:43:10 -05003380 impl ToTokens for Member {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003381 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay85b69a42017-12-27 20:43:10 -05003382 match *self {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003383 Member::Named(ref ident) => ident.to_tokens(tokens),
David Tolnay85b69a42017-12-27 20:43:10 -05003384 Member::Unnamed(ref index) => index.to_tokens(tokens),
3385 }
3386 }
3387 }
3388
David Tolnay85b69a42017-12-27 20:43:10 -05003389 impl ToTokens for Index {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003390 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichton9a4dca22018-03-28 06:32:19 -07003391 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
3392 lit.set_span(self.span);
3393 tokens.append(lit);
Alex Crichton62a0a592017-05-22 13:58:53 -07003394 }
3395 }
3396
3397 impl ToTokens for ExprIndex {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003398 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003399 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003400 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003401 self.bracket_token.surround(tokens, |tokens| {
3402 self.index.to_tokens(tokens);
3403 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003404 }
3405 }
3406
Michael Layzell734adb42017-06-07 16:58:31 -04003407 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003408 impl ToTokens for ExprRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003409 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003410 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003411 self.from.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003412 match self.limits {
3413 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
3414 RangeLimits::Closed(ref t) => t.to_tokens(tokens),
3415 }
Alex Crichton62a0a592017-05-22 13:58:53 -07003416 self.to.to_tokens(tokens);
3417 }
3418 }
3419
3420 impl ToTokens for ExprPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003421 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003422 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003423 ::PathTokens(&self.qself, &self.path).to_tokens(tokens)
Alex Crichton62a0a592017-05-22 13:58:53 -07003424 }
3425 }
3426
Michael Layzell734adb42017-06-07 16:58:31 -04003427 #[cfg(feature = "full")]
David Tolnay00674ba2018-03-31 18:14:11 +02003428 impl ToTokens for ExprReference {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003429 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003430 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003431 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003432 self.mutability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003433 self.expr.to_tokens(tokens);
3434 }
3435 }
3436
Michael Layzell734adb42017-06-07 16:58:31 -04003437 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003438 impl ToTokens for ExprBreak {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003439 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003440 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003441 self.break_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003442 self.label.to_tokens(tokens);
3443 self.expr.to_tokens(tokens);
3444 }
3445 }
3446
Michael Layzell734adb42017-06-07 16:58:31 -04003447 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003448 impl ToTokens for ExprContinue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003449 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003450 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003451 self.continue_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003452 self.label.to_tokens(tokens);
3453 }
3454 }
3455
Michael Layzell734adb42017-06-07 16:58:31 -04003456 #[cfg(feature = "full")]
David Tolnayc246cd32017-12-28 23:14:32 -05003457 impl ToTokens for ExprReturn {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003458 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003459 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003460 self.return_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003461 self.expr.to_tokens(tokens);
3462 }
3463 }
3464
Michael Layzell734adb42017-06-07 16:58:31 -04003465 #[cfg(feature = "full")]
David Tolnay8c91b882017-12-28 23:04:32 -05003466 impl ToTokens for ExprMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003467 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003468 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003469 self.mac.to_tokens(tokens);
3470 }
3471 }
3472
3473 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003474 impl ToTokens for ExprStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003475 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003476 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003477 self.path.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003478 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003479 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003480 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003481 if self.rest.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -07003482 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003483 self.rest.to_tokens(tokens);
3484 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003485 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003486 }
3487 }
3488
Michael Layzell734adb42017-06-07 16:58:31 -04003489 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003490 impl ToTokens for ExprRepeat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003491 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003492 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003493 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003494 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003495 self.expr.to_tokens(tokens);
3496 self.semi_token.to_tokens(tokens);
David Tolnay84d80442018-01-07 01:03:20 -08003497 self.len.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003498 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003499 }
3500 }
3501
David Tolnaye98775f2017-12-28 23:17:00 -05003502 #[cfg(feature = "full")]
Michael Layzell93c36282017-06-04 20:43:14 -04003503 impl ToTokens for ExprGroup {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003504 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003505 outer_attrs_to_tokens(&self.attrs, tokens);
Michael Layzell93c36282017-06-04 20:43:14 -04003506 self.group_token.surround(tokens, |tokens| {
3507 self.expr.to_tokens(tokens);
3508 });
3509 }
3510 }
3511
Alex Crichton62a0a592017-05-22 13:58:53 -07003512 impl ToTokens for ExprParen {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003513 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003514 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003515 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003516 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003517 self.expr.to_tokens(tokens);
3518 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003519 }
3520 }
3521
Michael Layzell734adb42017-06-07 16:58:31 -04003522 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003523 impl ToTokens for ExprTry {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003524 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003525 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003526 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003527 self.question_token.to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003528 }
3529 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07003530
David Tolnay2ae520a2017-12-29 11:19:50 -05003531 impl ToTokens for ExprVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003532 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003533 self.tts.to_tokens(tokens);
3534 }
3535 }
3536
Michael Layzell734adb42017-06-07 16:58:31 -04003537 #[cfg(feature = "full")]
David Tolnaybcd498f2017-12-29 12:02:33 -05003538 impl ToTokens for Label {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003539 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaybcd498f2017-12-29 12:02:33 -05003540 self.name.to_tokens(tokens);
3541 self.colon_token.to_tokens(tokens);
3542 }
3543 }
3544
3545 #[cfg(feature = "full")]
David Tolnay055a7042016-10-02 19:23:54 -07003546 impl ToTokens for FieldValue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003547 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003548 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003549 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003550 if let Some(ref colon_token) = self.colon_token {
3551 colon_token.to_tokens(tokens);
David Tolnay276690f2016-10-30 12:06:59 -07003552 self.expr.to_tokens(tokens);
3553 }
David Tolnay055a7042016-10-02 19:23:54 -07003554 }
3555 }
3556
Michael Layzell734adb42017-06-07 16:58:31 -04003557 #[cfg(feature = "full")]
David Tolnayb4ad3b52016-10-01 21:58:13 -07003558 impl ToTokens for Arm {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003559 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003560 tokens.append_all(&self.attrs);
David Tolnay18cc4d42018-03-31 18:47:20 +02003561 self.leading_vert.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003562 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003563 if let Some((ref if_token, ref guard)) = self.guard {
3564 if_token.to_tokens(tokens);
3565 guard.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003566 }
David Tolnaydfb91432018-03-31 19:19:44 +02003567 self.fat_arrow_token.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003568 self.body.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003569 self.comma.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003570 }
3571 }
3572
Michael Layzell734adb42017-06-07 16:58:31 -04003573 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003574 impl ToTokens for PatWild {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003575 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003576 self.underscore_token.to_tokens(tokens);
3577 }
3578 }
3579
Michael Layzell734adb42017-06-07 16:58:31 -04003580 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003581 impl ToTokens for PatIdent {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003582 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay24237fb2017-12-29 02:15:26 -05003583 self.by_ref.to_tokens(tokens);
David Tolnayefc96fb2017-12-29 02:03:15 -05003584 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003585 self.ident.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003586 if let Some((ref at_token, ref subpat)) = self.subpat {
3587 at_token.to_tokens(tokens);
3588 subpat.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003589 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003590 }
3591 }
3592
Michael Layzell734adb42017-06-07 16:58:31 -04003593 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003594 impl ToTokens for PatStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003595 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003596 self.path.to_tokens(tokens);
3597 self.brace_token.surround(tokens, |tokens| {
3598 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003599 // NOTE: We need a comma before the dot2 token if it is present.
3600 if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003601 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003602 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003603 self.dot2_token.to_tokens(tokens);
3604 });
3605 }
3606 }
3607
Michael Layzell734adb42017-06-07 16:58:31 -04003608 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003609 impl ToTokens for PatTupleStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003610 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003611 self.path.to_tokens(tokens);
3612 self.pat.to_tokens(tokens);
3613 }
3614 }
3615
Michael Layzell734adb42017-06-07 16:58:31 -04003616 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003617 impl ToTokens for PatPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003618 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003619 ::PathTokens(&self.qself, &self.path).to_tokens(tokens);
3620 }
3621 }
3622
Michael Layzell734adb42017-06-07 16:58:31 -04003623 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003624 impl ToTokens for PatTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003625 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003626 self.paren_token.surround(tokens, |tokens| {
David Tolnay41871922017-12-29 01:53:45 -05003627 self.front.to_tokens(tokens);
3628 if let Some(ref dot2_token) = self.dot2_token {
3629 if !self.front.empty_or_trailing() {
3630 // Ensure there is a comma before the .. token.
David Tolnayf8db7ba2017-11-11 22:52:16 -08003631 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003632 }
David Tolnay41871922017-12-29 01:53:45 -05003633 dot2_token.to_tokens(tokens);
3634 self.comma_token.to_tokens(tokens);
3635 if self.comma_token.is_none() && !self.back.is_empty() {
3636 // Ensure there is a comma after the .. token.
3637 <Token![,]>::default().to_tokens(tokens);
3638 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07003639 }
David Tolnay41871922017-12-29 01:53:45 -05003640 self.back.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003641 });
3642 }
3643 }
3644
Michael Layzell734adb42017-06-07 16:58:31 -04003645 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003646 impl ToTokens for PatBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003647 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003648 self.box_token.to_tokens(tokens);
3649 self.pat.to_tokens(tokens);
3650 }
3651 }
3652
Michael Layzell734adb42017-06-07 16:58:31 -04003653 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003654 impl ToTokens for PatRef {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003655 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003656 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003657 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003658 self.pat.to_tokens(tokens);
3659 }
3660 }
3661
Michael Layzell734adb42017-06-07 16:58:31 -04003662 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003663 impl ToTokens for PatLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003664 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003665 self.expr.to_tokens(tokens);
3666 }
3667 }
3668
Michael Layzell734adb42017-06-07 16:58:31 -04003669 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003670 impl ToTokens for PatRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003671 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003672 self.lo.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003673 match self.limits {
3674 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
David Tolnay7ac699c2018-08-24 14:00:58 -04003675 RangeLimits::Closed(ref t) => Token![...](t.spans).to_tokens(tokens),
David Tolnay475288a2017-12-19 22:59:44 -08003676 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003677 self.hi.to_tokens(tokens);
3678 }
3679 }
3680
Michael Layzell734adb42017-06-07 16:58:31 -04003681 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003682 impl ToTokens for PatSlice {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003683 fn to_tokens(&self, tokens: &mut TokenStream) {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003684 // XXX: This is a mess, and it will be so easy to screw it up. How
3685 // do we make this correct itself better?
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003686 self.bracket_token.surround(tokens, |tokens| {
3687 self.front.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003688
3689 // If we need a comma before the middle or standalone .. token,
3690 // then make sure it's present.
David Tolnay51382052017-12-27 13:46:21 -05003691 if !self.front.empty_or_trailing()
3692 && (self.middle.is_some() || self.dot2_token.is_some())
Michael Layzell3936ceb2017-07-08 00:28:36 -04003693 {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003694 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003695 }
3696
3697 // If we have an identifier, we always need a .. token.
3698 if self.middle.is_some() {
3699 self.middle.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -07003700 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003701 } else if self.dot2_token.is_some() {
3702 self.dot2_token.to_tokens(tokens);
3703 }
3704
3705 // Make sure we have a comma before the back half.
3706 if !self.back.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07003707 TokensOrDefault(&self.comma_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003708 self.back.to_tokens(tokens);
3709 } else {
3710 self.comma_token.to_tokens(tokens);
3711 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003712 })
David Tolnayb4ad3b52016-10-01 21:58:13 -07003713 }
3714 }
3715
Michael Layzell734adb42017-06-07 16:58:31 -04003716 #[cfg(feature = "full")]
David Tolnay323279a2017-12-29 11:26:32 -05003717 impl ToTokens for PatMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003718 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay323279a2017-12-29 11:26:32 -05003719 self.mac.to_tokens(tokens);
3720 }
3721 }
3722
3723 #[cfg(feature = "full")]
David Tolnay2ae520a2017-12-29 11:19:50 -05003724 impl ToTokens for PatVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003725 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003726 self.tts.to_tokens(tokens);
3727 }
3728 }
3729
3730 #[cfg(feature = "full")]
David Tolnay8d9e81a2016-10-03 22:36:32 -07003731 impl ToTokens for FieldPat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003732 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay5d7098a2017-12-29 01:35:24 -05003733 if let Some(ref colon_token) = self.colon_token {
David Tolnay85b69a42017-12-27 20:43:10 -05003734 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003735 colon_token.to_tokens(tokens);
David Tolnay8d9e81a2016-10-03 22:36:32 -07003736 }
3737 self.pat.to_tokens(tokens);
3738 }
3739 }
3740
Michael Layzell734adb42017-06-07 16:58:31 -04003741 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003742 impl ToTokens for Block {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003743 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003744 self.brace_token.surround(tokens, |tokens| {
3745 tokens.append_all(&self.stmts);
3746 });
David Tolnay42602292016-10-01 22:25:45 -07003747 }
3748 }
3749
Michael Layzell734adb42017-06-07 16:58:31 -04003750 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003751 impl ToTokens for Stmt {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003752 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay42602292016-10-01 22:25:45 -07003753 match *self {
David Tolnay191e0582016-10-02 18:31:09 -07003754 Stmt::Local(ref local) => local.to_tokens(tokens),
David Tolnay42602292016-10-01 22:25:45 -07003755 Stmt::Item(ref item) => item.to_tokens(tokens),
3756 Stmt::Expr(ref expr) => expr.to_tokens(tokens),
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003757 Stmt::Semi(ref expr, ref semi) => {
David Tolnay42602292016-10-01 22:25:45 -07003758 expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003759 semi.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -07003760 }
David Tolnay42602292016-10-01 22:25:45 -07003761 }
3762 }
3763 }
David Tolnay191e0582016-10-02 18:31:09 -07003764
Michael Layzell734adb42017-06-07 16:58:31 -04003765 #[cfg(feature = "full")]
David Tolnay191e0582016-10-02 18:31:09 -07003766 impl ToTokens for Local {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003767 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003768 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003769 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003770 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003771 if let Some((ref colon_token, ref ty)) = self.ty {
3772 colon_token.to_tokens(tokens);
3773 ty.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003774 }
David Tolnay8b4d3022017-12-29 12:11:10 -05003775 if let Some((ref eq_token, ref init)) = self.init {
3776 eq_token.to_tokens(tokens);
3777 init.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003778 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003779 self.semi_token.to_tokens(tokens);
David Tolnay191e0582016-10-02 18:31:09 -07003780 }
3781 }
David Tolnayf4bbbd92016-09-23 14:41:55 -07003782}