blob: 5d9ce1dba2e8579cfe1d4d84da21848f91d1d5db [file] [log] [blame]
David Tolnay55535012018-01-05 16:39:23 -08001// Copyright 2018 Syn Developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
David Tolnayf4bbbd92016-09-23 14:41:55 -07009use super::*;
David Tolnaye303b7c2018-05-20 16:46:35 -070010use proc_macro2::{Span, TokenStream};
David Tolnay94d2b792018-04-29 12:26:10 -070011use punctuated::Punctuated;
David Tolnay14982012017-12-29 00:49:51 -050012#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -050013use std::hash::{Hash, Hasher};
David Tolnay2ae520a2017-12-29 11:19:50 -050014#[cfg(feature = "full")]
15use std::mem;
David Tolnay94d2b792018-04-29 12:26:10 -070016#[cfg(feature = "extra-traits")]
17use tt::TokenStreamHelper;
David Tolnayf4bbbd92016-09-23 14:41:55 -070018
Alex Crichton62a0a592017-05-22 13:58:53 -070019ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -080020 /// A Rust expression.
David Tolnay614a0142018-01-07 10:25:43 -080021 ///
David Tolnay461d98e2018-01-07 11:07:19 -080022 /// *This type is available if Syn is built with the `"derive"` or `"full"`
23 /// feature.*
24 ///
David Tolnay614a0142018-01-07 10:25:43 -080025 /// # Syntax tree enums
26 ///
27 /// This type is a syntax tree enum. In Syn this and other syntax tree enums
28 /// are designed to be traversed using the following rebinding idiom.
29 ///
30 /// ```
31 /// # use syn::Expr;
32 /// #
33 /// # fn example(expr: Expr) {
34 /// # const IGNORE: &str = stringify! {
35 /// let expr: Expr = /* ... */;
36 /// # };
37 /// match expr {
38 /// Expr::MethodCall(expr) => {
39 /// /* ... */
40 /// }
41 /// Expr::Cast(expr) => {
42 /// /* ... */
43 /// }
44 /// Expr::IfLet(expr) => {
45 /// /* ... */
46 /// }
47 /// /* ... */
48 /// # _ => {}
49 /// }
50 /// # }
51 /// ```
52 ///
53 /// We begin with a variable `expr` of type `Expr` that has no fields
54 /// (because it is an enum), and by matching on it and rebinding a variable
55 /// with the same name `expr` we effectively imbue our variable with all of
56 /// the data fields provided by the variant that it turned out to be. So for
57 /// example above if we ended up in the `MethodCall` case then we get to use
58 /// `expr.receiver`, `expr.args` etc; if we ended up in the `IfLet` case we
59 /// get to use `expr.pat`, `expr.then_branch`, `expr.else_branch`.
60 ///
61 /// The pattern is similar if the input expression is borrowed:
62 ///
63 /// ```
64 /// # use syn::Expr;
65 /// #
66 /// # fn example(expr: &Expr) {
67 /// match *expr {
68 /// Expr::MethodCall(ref expr) => {
69 /// # }
70 /// # _ => {}
71 /// # }
72 /// # }
73 /// ```
74 ///
75 /// This approach avoids repeating the variant names twice on every line.
76 ///
77 /// ```
78 /// # use syn::{Expr, ExprMethodCall};
79 /// #
80 /// # fn example(expr: Expr) {
81 /// # match expr {
82 /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => { // repetitive
83 /// # }
84 /// # _ => {}
85 /// # }
86 /// # }
87 /// ```
88 ///
89 /// In general, the name to which a syntax tree enum variant is bound should
90 /// be a suitable name for the complete syntax tree enum type.
91 ///
92 /// ```
93 /// # use syn::{Expr, ExprField};
94 /// #
95 /// # fn example(discriminant: &ExprField) {
96 /// // Binding is called `base` which is the name I would use if I were
97 /// // assigning `*discriminant.base` without an `if let`.
98 /// if let Expr::Tuple(ref base) = *discriminant.base {
99 /// # }
100 /// # }
101 /// ```
102 ///
103 /// A sign that you may not be choosing the right variable names is if you
104 /// see names getting repeated in your code, like accessing
105 /// `receiver.receiver` or `pat.pat` or `cond.cond`.
David Tolnay8c91b882017-12-28 23:04:32 -0500106 pub enum Expr {
David Tolnaya454c8f2018-01-07 01:01:10 -0800107 /// A box expression: `box f`.
David Tolnay461d98e2018-01-07 11:07:19 -0800108 ///
109 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400110 pub Box(ExprBox #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500111 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800112 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500113 pub expr: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700114 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500115
David Tolnaya454c8f2018-01-07 01:01:10 -0800116 /// A placement expression: `place <- value`.
David Tolnay461d98e2018-01-07 11:07:19 -0800117 ///
118 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400119 pub InPlace(ExprInPlace #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500120 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700121 pub place: Box<Expr>,
David Tolnay8701a5c2017-12-28 23:31:10 -0500122 pub arrow_token: Token![<-],
Alex Crichton62a0a592017-05-22 13:58:53 -0700123 pub value: Box<Expr>,
124 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500125
David Tolnaya454c8f2018-01-07 01:01:10 -0800126 /// A slice literal expression: `[a, b, c, d]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800127 ///
128 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400129 pub Array(ExprArray #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500130 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500131 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500132 pub elems: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700133 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500134
David Tolnaya454c8f2018-01-07 01:01:10 -0800135 /// A function call expression: `invoke(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800136 ///
137 /// *This type is available if Syn is built with the `"derive"` or
138 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700139 pub Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -0500140 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700141 pub func: Box<Expr>,
David Tolnay32954ef2017-12-26 22:43:16 -0500142 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500143 pub args: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700144 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500145
David Tolnaya454c8f2018-01-07 01:01:10 -0800146 /// A method call expression: `x.foo::<T>(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800147 ///
148 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400149 pub MethodCall(ExprMethodCall #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500150 pub attrs: Vec<Attribute>,
David Tolnay76418512017-12-28 23:47:47 -0500151 pub receiver: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800152 pub dot_token: Token![.],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500153 pub method: Ident,
David Tolnayd60cfec2017-12-29 00:21:38 -0500154 pub turbofish: Option<MethodTurbofish>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500155 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500156 pub args: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700157 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500158
David Tolnaya454c8f2018-01-07 01:01:10 -0800159 /// A tuple expression: `(a, b, c, d)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800160 ///
161 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay05362582017-12-26 01:33:57 -0500162 pub Tuple(ExprTuple #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500163 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500164 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500165 pub elems: Punctuated<Expr, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700166 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500167
David Tolnaya454c8f2018-01-07 01:01:10 -0800168 /// A binary operation: `a + b`, `a * b`.
David Tolnay461d98e2018-01-07 11:07:19 -0800169 ///
170 /// *This type is available if Syn is built with the `"derive"` or
171 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700172 pub Binary(ExprBinary {
David Tolnay8c91b882017-12-28 23:04:32 -0500173 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700174 pub left: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500175 pub op: BinOp,
Alex Crichton62a0a592017-05-22 13:58:53 -0700176 pub right: Box<Expr>,
177 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500178
David Tolnaya454c8f2018-01-07 01:01:10 -0800179 /// A unary operation: `!x`, `*x`.
David Tolnay461d98e2018-01-07 11:07:19 -0800180 ///
181 /// *This type is available if Syn is built with the `"derive"` or
182 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700183 pub Unary(ExprUnary {
David Tolnay8c91b882017-12-28 23:04:32 -0500184 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700185 pub op: UnOp,
186 pub expr: Box<Expr>,
187 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500188
David Tolnaya454c8f2018-01-07 01:01:10 -0800189 /// A literal in place of an expression: `1`, `"foo"`.
David Tolnay461d98e2018-01-07 11:07:19 -0800190 ///
191 /// *This type is available if Syn is built with the `"derive"` or
192 /// `"full"` feature.*
David Tolnay8c91b882017-12-28 23:04:32 -0500193 pub Lit(ExprLit {
194 pub attrs: Vec<Attribute>,
195 pub lit: Lit,
196 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500197
David Tolnaya454c8f2018-01-07 01:01:10 -0800198 /// A cast expression: `foo as f64`.
David Tolnay461d98e2018-01-07 11:07:19 -0800199 ///
200 /// *This type is available if Syn is built with the `"derive"` or
201 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700202 pub Cast(ExprCast {
David Tolnay8c91b882017-12-28 23:04:32 -0500203 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700204 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800205 pub as_token: Token![as],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800206 pub ty: Box<Type>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700207 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500208
David Tolnaya454c8f2018-01-07 01:01:10 -0800209 /// A type ascription expression: `foo: f64`.
David Tolnay461d98e2018-01-07 11:07:19 -0800210 ///
211 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay0cf94f22017-12-28 23:46:26 -0500212 pub Type(ExprType #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500213 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700214 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800215 pub colon_token: Token![:],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800216 pub ty: Box<Type>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700217 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500218
David Tolnaya454c8f2018-01-07 01:01:10 -0800219 /// An `if` expression with an optional `else` block: `if expr { ... }
220 /// else { ... }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700221 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800222 /// The `else` branch expression may only be an `If`, `IfLet`, or
223 /// `Block` expression, not any of the other types of expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800224 ///
225 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400226 pub If(ExprIf #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500227 pub attrs: Vec<Attribute>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500228 pub if_token: Token![if],
Alex Crichton62a0a592017-05-22 13:58:53 -0700229 pub cond: Box<Expr>,
David Tolnay2ccf32a2017-12-29 00:34:26 -0500230 pub then_branch: Block,
231 pub else_branch: Option<(Token![else], Box<Expr>)>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700232 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500233
David Tolnaya454c8f2018-01-07 01:01:10 -0800234 /// An `if let` expression with an optional `else` block: `if let pat =
235 /// expr { ... } else { ... }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700236 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800237 /// The `else` branch expression may only be an `If`, `IfLet`, or
238 /// `Block` expression, not any of the other types of expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800239 ///
240 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400241 pub IfLet(ExprIfLet #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500242 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800243 pub if_token: Token![if],
244 pub let_token: Token![let],
David Tolnay5b5b7d22018-03-31 21:05:00 +0200245 pub pats: Punctuated<Pat, Token![|]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800246 pub eq_token: Token![=],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500247 pub expr: Box<Expr>,
David Tolnay2ccf32a2017-12-29 00:34:26 -0500248 pub then_branch: Block,
249 pub else_branch: Option<(Token![else], Box<Expr>)>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700250 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500251
David Tolnaya454c8f2018-01-07 01:01:10 -0800252 /// A while loop: `while expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800253 ///
254 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400255 pub While(ExprWhile #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500256 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500257 pub label: Option<Label>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800258 pub while_token: Token![while],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500259 pub cond: Box<Expr>,
260 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700261 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500262
David Tolnaya454c8f2018-01-07 01:01:10 -0800263 /// A while-let loop: `while let pat = expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800264 ///
265 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400266 pub WhileLet(ExprWhileLet #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500267 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500268 pub label: Option<Label>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800269 pub while_token: Token![while],
270 pub let_token: Token![let],
David Tolnay5b5b7d22018-03-31 21:05:00 +0200271 pub pats: Punctuated<Pat, Token![|]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800272 pub eq_token: Token![=],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500273 pub expr: Box<Expr>,
274 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700275 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500276
David Tolnaya454c8f2018-01-07 01:01:10 -0800277 /// A for loop: `for pat in expr { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800278 ///
279 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400280 pub ForLoop(ExprForLoop #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500281 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500282 pub label: Option<Label>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500283 pub for_token: Token![for],
Alex Crichton62a0a592017-05-22 13:58:53 -0700284 pub pat: Box<Pat>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500285 pub in_token: Token![in],
Alex Crichton62a0a592017-05-22 13:58:53 -0700286 pub expr: Box<Expr>,
287 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700288 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500289
David Tolnaya454c8f2018-01-07 01:01:10 -0800290 /// Conditionless loop: `loop { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800291 ///
292 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400293 pub Loop(ExprLoop #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500294 pub attrs: Vec<Attribute>,
David Tolnaybcd498f2017-12-29 12:02:33 -0500295 pub label: Option<Label>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500296 pub loop_token: Token![loop],
297 pub body: Block,
Alex Crichton62a0a592017-05-22 13:58:53 -0700298 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500299
David Tolnaya454c8f2018-01-07 01:01:10 -0800300 /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800301 ///
302 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400303 pub Match(ExprMatch #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500304 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800305 pub match_token: Token![match],
Alex Crichton62a0a592017-05-22 13:58:53 -0700306 pub expr: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500307 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700308 pub arms: Vec<Arm>,
309 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500310
David Tolnaya454c8f2018-01-07 01:01:10 -0800311 /// A closure expression: `|a, b| a + b`.
David Tolnay461d98e2018-01-07 11:07:19 -0800312 ///
313 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400314 pub Closure(ExprClosure #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500315 pub attrs: Vec<Attribute>,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +0900316 pub asyncness: Option<Token![async]>,
David Tolnay13d4c0e2018-03-31 20:53:59 +0200317 pub movability: Option<Token![static]>,
David Tolnayefc96fb2017-12-29 02:03:15 -0500318 pub capture: Option<Token![move]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800319 pub or1_token: Token![|],
David Tolnayf2cfd722017-12-31 18:02:51 -0500320 pub inputs: Punctuated<FnArg, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800321 pub or2_token: Token![|],
David Tolnay7f675742017-12-27 22:43:21 -0500322 pub output: ReturnType,
323 pub body: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700324 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500325
David Tolnaya454c8f2018-01-07 01:01:10 -0800326 /// An unsafe block: `unsafe { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800327 ///
328 /// *This type is available if Syn is built with the `"full"` feature.*
Nika Layzell640832a2017-12-04 13:37:09 -0500329 pub Unsafe(ExprUnsafe #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500330 pub attrs: Vec<Attribute>,
Nika Layzell640832a2017-12-04 13:37:09 -0500331 pub unsafe_token: Token![unsafe],
332 pub block: Block,
333 }),
334
David Tolnaya454c8f2018-01-07 01:01:10 -0800335 /// A blocked scope: `{ ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800336 ///
337 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400338 pub Block(ExprBlock #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500339 pub attrs: Vec<Attribute>,
David Tolnay1d8e9962018-08-24 19:04:20 -0400340 pub label: Option<Label>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700341 pub block: Block,
342 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700343
David Tolnaya454c8f2018-01-07 01:01:10 -0800344 /// An assignment expression: `a = compute()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800345 ///
346 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400347 pub Assign(ExprAssign #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500348 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700349 pub left: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800350 pub eq_token: Token![=],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500351 pub right: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700352 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500353
David Tolnaya454c8f2018-01-07 01:01:10 -0800354 /// A compound assignment expression: `counter += 1`.
David Tolnay461d98e2018-01-07 11:07:19 -0800355 ///
356 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400357 pub AssignOp(ExprAssignOp #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500358 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700359 pub left: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500360 pub op: BinOp,
Alex Crichton62a0a592017-05-22 13:58:53 -0700361 pub right: Box<Expr>,
362 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500363
David Tolnaya454c8f2018-01-07 01:01:10 -0800364 /// Access of a named struct field (`obj.k`) or unnamed tuple struct
David Tolnay85b69a42017-12-27 20:43:10 -0500365 /// field (`obj.0`).
David Tolnay461d98e2018-01-07 11:07:19 -0800366 ///
367 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd5147742018-06-30 10:09:52 -0700368 pub Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -0500369 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -0500370 pub base: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800371 pub dot_token: Token![.],
David Tolnay85b69a42017-12-27 20:43:10 -0500372 pub member: Member,
Alex Crichton62a0a592017-05-22 13:58:53 -0700373 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500374
David Tolnay05658502018-01-07 09:56:37 -0800375 /// A square bracketed indexing expression: `vector[2]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800376 ///
377 /// *This type is available if Syn is built with the `"derive"` or
378 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700379 pub Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -0500380 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700381 pub expr: Box<Expr>,
David Tolnay32954ef2017-12-26 22:43:16 -0500382 pub bracket_token: token::Bracket,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500383 pub index: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700384 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500385
David Tolnaya454c8f2018-01-07 01:01:10 -0800386 /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800387 ///
388 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400389 pub Range(ExprRange #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500390 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700391 pub from: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700392 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500393 pub to: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700394 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700395
David Tolnaya454c8f2018-01-07 01:01:10 -0800396 /// A path like `std::mem::replace` possibly containing generic
397 /// parameters and a qualified self-type.
Alex Crichton62a0a592017-05-22 13:58:53 -0700398 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800399 /// A plain identifier like `x` is a path of length 1.
David Tolnay461d98e2018-01-07 11:07:19 -0800400 ///
401 /// *This type is available if Syn is built with the `"derive"` or
402 /// `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700403 pub Path(ExprPath {
David Tolnay8c91b882017-12-28 23:04:32 -0500404 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700405 pub qself: Option<QSelf>,
406 pub path: Path,
407 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700408
David Tolnaya454c8f2018-01-07 01:01:10 -0800409 /// A referencing operation: `&a` or `&mut a`.
David Tolnay461d98e2018-01-07 11:07:19 -0800410 ///
411 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay00674ba2018-03-31 18:14:11 +0200412 pub Reference(ExprReference #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500413 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800414 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500415 pub mutability: Option<Token![mut]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700416 pub expr: Box<Expr>,
417 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500418
David Tolnaya454c8f2018-01-07 01:01:10 -0800419 /// A `break`, with an optional label to break and an optional
420 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800421 ///
422 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400423 pub Break(ExprBreak #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500424 pub attrs: Vec<Attribute>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500425 pub break_token: Token![break],
David Tolnay63e3dee2017-06-03 20:13:17 -0700426 pub label: Option<Lifetime>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700427 pub expr: Option<Box<Expr>>,
428 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500429
David Tolnaya454c8f2018-01-07 01:01:10 -0800430 /// A `continue`, with an optional label.
David Tolnay461d98e2018-01-07 11:07:19 -0800431 ///
432 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400433 pub Continue(ExprContinue #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500434 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800435 pub continue_token: Token![continue],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500436 pub label: Option<Lifetime>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700437 }),
Clar Charrd22b5702017-03-10 15:24:56 -0500438
David Tolnaya454c8f2018-01-07 01:01:10 -0800439 /// A `return`, with an optional value to be returned.
David Tolnay461d98e2018-01-07 11:07:19 -0800440 ///
441 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayc246cd32017-12-28 23:14:32 -0500442 pub Return(ExprReturn #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500443 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800444 pub return_token: Token![return],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500445 pub expr: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700446 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700447
David Tolnaya454c8f2018-01-07 01:01:10 -0800448 /// A macro invocation expression: `format!("{}", q)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800449 ///
450 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay8c91b882017-12-28 23:04:32 -0500451 pub Macro(ExprMacro #full {
452 pub attrs: Vec<Attribute>,
453 pub mac: Macro,
454 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700455
David Tolnaya454c8f2018-01-07 01:01:10 -0800456 /// A struct literal expression: `Point { x: 1, y: 1 }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700457 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800458 /// The `rest` provides the value of the remaining fields as in `S { a:
459 /// 1, b: 1, ..rest }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800460 ///
461 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400462 pub Struct(ExprStruct #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500463 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700464 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500465 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500466 pub fields: Punctuated<FieldValue, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500467 pub dot2_token: Option<Token![..]>,
468 pub rest: Option<Box<Expr>>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700469 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700470
David Tolnaya454c8f2018-01-07 01:01:10 -0800471 /// An array literal constructed from one repeated element: `[0u8; N]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800472 ///
473 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400474 pub Repeat(ExprRepeat #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500475 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500476 pub bracket_token: token::Bracket,
Alex Crichton62a0a592017-05-22 13:58:53 -0700477 pub expr: Box<Expr>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500478 pub semi_token: Token![;],
David Tolnay84d80442018-01-07 01:03:20 -0800479 pub len: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700480 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700481
David Tolnaya454c8f2018-01-07 01:01:10 -0800482 /// A parenthesized expression: `(a + b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800483 ///
484 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay9374bc02018-01-27 18:49:36 -0800485 pub Paren(ExprParen {
David Tolnay8c91b882017-12-28 23:04:32 -0500486 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500487 pub paren_token: token::Paren,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500488 pub expr: Box<Expr>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700489 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700490
David Tolnaya454c8f2018-01-07 01:01:10 -0800491 /// An expression contained within invisible delimiters.
Michael Layzell93c36282017-06-04 20:43:14 -0400492 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800493 /// This variant is important for faithfully representing the precedence
494 /// of expressions and is related to `None`-delimited spans in a
495 /// `TokenStream`.
David Tolnay461d98e2018-01-07 11:07:19 -0800496 ///
497 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaye98775f2017-12-28 23:17:00 -0500498 pub Group(ExprGroup #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500499 pub attrs: Vec<Attribute>,
David Tolnay32954ef2017-12-26 22:43:16 -0500500 pub group_token: token::Group,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500501 pub expr: Box<Expr>,
Michael Layzell93c36282017-06-04 20:43:14 -0400502 }),
503
David Tolnaya454c8f2018-01-07 01:01:10 -0800504 /// A try-expression: `expr?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800505 ///
506 /// *This type is available if Syn is built with the `"full"` feature.*
Michael Layzell734adb42017-06-07 16:58:31 -0400507 pub Try(ExprTry #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500508 pub attrs: Vec<Attribute>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700509 pub expr: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800510 pub question_token: Token![?],
Alex Crichton62a0a592017-05-22 13:58:53 -0700511 }),
Arnavion02ef13f2017-04-25 00:54:31 -0700512
David Tolnay02a9c6f2018-08-24 18:58:45 -0400513 /// An async block: `async { ... }`.
514 ///
515 /// *This type is available if Syn is built with the `"full"` feature.*
516 pub Async(ExprAsync #full {
517 pub attrs: Vec<Attribute>,
518 pub async_token: Token![async],
519 pub capture: Option<Token![move]>,
520 pub block: Block,
521 }),
522
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400523 /// A try block: `try { ... }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800524 ///
525 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400526 pub TryBlock(ExprTryBlock #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500527 pub attrs: Vec<Attribute>,
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400528 pub try_token: Token![try],
Alex Crichton62a0a592017-05-22 13:58:53 -0700529 pub block: Block,
530 }),
Alex Crichtonfe110462017-06-01 12:49:27 -0700531
David Tolnaya454c8f2018-01-07 01:01:10 -0800532 /// A yield expression: `yield expr`.
David Tolnay461d98e2018-01-07 11:07:19 -0800533 ///
534 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonfe110462017-06-01 12:49:27 -0700535 pub Yield(ExprYield #full {
David Tolnay8c91b882017-12-28 23:04:32 -0500536 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800537 pub yield_token: Token![yield],
Alex Crichtonfe110462017-06-01 12:49:27 -0700538 pub expr: Option<Box<Expr>>,
539 }),
David Tolnay2ae520a2017-12-29 11:19:50 -0500540
David Tolnaya454c8f2018-01-07 01:01:10 -0800541 /// Tokens in expression position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800542 ///
543 /// *This type is available if Syn is built with the `"derive"` or
544 /// `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500545 pub Verbatim(ExprVerbatim #manual_extra_traits {
546 pub tts: TokenStream,
547 }),
548 }
549}
550
551#[cfg(feature = "extra-traits")]
552impl Eq for ExprVerbatim {}
553
554#[cfg(feature = "extra-traits")]
555impl PartialEq for ExprVerbatim {
556 fn eq(&self, other: &Self) -> bool {
557 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
558 }
559}
560
561#[cfg(feature = "extra-traits")]
562impl Hash for ExprVerbatim {
563 fn hash<H>(&self, state: &mut H)
564 where
565 H: Hasher,
566 {
567 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700568 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700569}
570
David Tolnay8c91b882017-12-28 23:04:32 -0500571impl Expr {
572 // Not public API.
573 #[doc(hidden)]
David Tolnay096d4982017-12-28 23:18:18 -0500574 #[cfg(feature = "full")]
David Tolnay2ae520a2017-12-29 11:19:50 -0500575 pub fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
David Tolnay8c91b882017-12-28 23:04:32 -0500576 match *self {
David Tolnay61037c62018-01-05 16:21:03 -0800577 Expr::Box(ExprBox { ref mut attrs, .. })
578 | Expr::InPlace(ExprInPlace { ref mut attrs, .. })
579 | Expr::Array(ExprArray { ref mut attrs, .. })
580 | Expr::Call(ExprCall { ref mut attrs, .. })
581 | Expr::MethodCall(ExprMethodCall { ref mut attrs, .. })
582 | Expr::Tuple(ExprTuple { ref mut attrs, .. })
583 | Expr::Binary(ExprBinary { ref mut attrs, .. })
584 | Expr::Unary(ExprUnary { ref mut attrs, .. })
585 | Expr::Lit(ExprLit { ref mut attrs, .. })
586 | Expr::Cast(ExprCast { ref mut attrs, .. })
587 | Expr::Type(ExprType { ref mut attrs, .. })
588 | Expr::If(ExprIf { ref mut attrs, .. })
589 | Expr::IfLet(ExprIfLet { ref mut attrs, .. })
590 | Expr::While(ExprWhile { ref mut attrs, .. })
591 | Expr::WhileLet(ExprWhileLet { ref mut attrs, .. })
592 | Expr::ForLoop(ExprForLoop { ref mut attrs, .. })
593 | Expr::Loop(ExprLoop { ref mut attrs, .. })
594 | Expr::Match(ExprMatch { ref mut attrs, .. })
595 | Expr::Closure(ExprClosure { ref mut attrs, .. })
596 | Expr::Unsafe(ExprUnsafe { ref mut attrs, .. })
597 | Expr::Block(ExprBlock { ref mut attrs, .. })
598 | Expr::Assign(ExprAssign { ref mut attrs, .. })
599 | Expr::AssignOp(ExprAssignOp { ref mut attrs, .. })
600 | Expr::Field(ExprField { ref mut attrs, .. })
601 | Expr::Index(ExprIndex { ref mut attrs, .. })
602 | Expr::Range(ExprRange { ref mut attrs, .. })
603 | Expr::Path(ExprPath { ref mut attrs, .. })
David Tolnay00674ba2018-03-31 18:14:11 +0200604 | Expr::Reference(ExprReference { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800605 | Expr::Break(ExprBreak { ref mut attrs, .. })
606 | Expr::Continue(ExprContinue { ref mut attrs, .. })
607 | Expr::Return(ExprReturn { ref mut attrs, .. })
608 | Expr::Macro(ExprMacro { ref mut attrs, .. })
609 | Expr::Struct(ExprStruct { ref mut attrs, .. })
610 | Expr::Repeat(ExprRepeat { ref mut attrs, .. })
611 | Expr::Paren(ExprParen { ref mut attrs, .. })
612 | Expr::Group(ExprGroup { ref mut attrs, .. })
613 | Expr::Try(ExprTry { ref mut attrs, .. })
David Tolnay02a9c6f2018-08-24 18:58:45 -0400614 | Expr::Async(ExprAsync { ref mut attrs, .. })
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400615 | Expr::TryBlock(ExprTryBlock { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800616 | Expr::Yield(ExprYield { ref mut attrs, .. }) => mem::replace(attrs, new),
David Tolnay10f464a2018-08-30 18:48:55 -0700617 Expr::Verbatim(_) => Vec::new(),
David Tolnay8c91b882017-12-28 23:04:32 -0500618 }
619 }
620}
621
David Tolnay85b69a42017-12-27 20:43:10 -0500622ast_enum! {
623 /// A struct or tuple struct field accessed in a struct literal or field
624 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800625 ///
626 /// *This type is available if Syn is built with the `"derive"` or `"full"`
627 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500628 pub enum Member {
629 /// A named field like `self.x`.
630 Named(Ident),
631 /// An unnamed field like `self.0`.
632 Unnamed(Index),
633 }
634}
635
David Tolnay85b69a42017-12-27 20:43:10 -0500636ast_struct! {
637 /// The index of an unnamed tuple struct field.
David Tolnay461d98e2018-01-07 11:07:19 -0800638 ///
639 /// *This type is available if Syn is built with the `"derive"` or `"full"`
640 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500641 pub struct Index #manual_extra_traits {
642 pub index: u32,
643 pub span: Span,
644 }
645}
646
David Tolnay14982012017-12-29 00:49:51 -0500647impl From<usize> for Index {
648 fn from(index: usize) -> Index {
David Tolnay34071ba2018-05-20 20:00:41 -0700649 assert!(index < u32::max_value() as usize);
David Tolnay14982012017-12-29 00:49:51 -0500650 Index {
651 index: index as u32,
Alex Crichton9a4dca22018-03-28 06:32:19 -0700652 span: Span::call_site(),
David Tolnay14982012017-12-29 00:49:51 -0500653 }
654 }
655}
656
657#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500658impl Eq for Index {}
659
David Tolnay14982012017-12-29 00:49:51 -0500660#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500661impl PartialEq for Index {
662 fn eq(&self, other: &Self) -> bool {
663 self.index == other.index
664 }
665}
666
David Tolnay14982012017-12-29 00:49:51 -0500667#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500668impl Hash for Index {
669 fn hash<H: Hasher>(&self, state: &mut H) {
670 self.index.hash(state);
671 }
672}
673
674#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700675ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800676 /// The `::<>` explicit type parameters passed to a method call:
677 /// `parse::<u64>()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800678 ///
679 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500680 pub struct MethodTurbofish {
681 pub colon2_token: Token![::],
682 pub lt_token: Token![<],
David Tolnayf2cfd722017-12-31 18:02:51 -0500683 pub args: Punctuated<GenericMethodArgument, Token![,]>,
David Tolnayd60cfec2017-12-29 00:21:38 -0500684 pub gt_token: Token![>],
685 }
686}
687
688#[cfg(feature = "full")]
689ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800690 /// An individual generic argument to a method, like `T`.
David Tolnay461d98e2018-01-07 11:07:19 -0800691 ///
692 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500693 pub enum GenericMethodArgument {
David Tolnaya454c8f2018-01-07 01:01:10 -0800694 /// A type argument.
David Tolnayd60cfec2017-12-29 00:21:38 -0500695 Type(Type),
David Tolnaya454c8f2018-01-07 01:01:10 -0800696 /// A const expression. Must be inside of a block.
David Tolnayd60cfec2017-12-29 00:21:38 -0500697 ///
698 /// NOTE: Identity expressions are represented as Type arguments, as
699 /// they are indistinguishable syntactically.
700 Const(Expr),
701 }
702}
703
704#[cfg(feature = "full")]
705ast_struct! {
Alex Crichton62a0a592017-05-22 13:58:53 -0700706 /// A field-value pair in a struct literal.
David Tolnay461d98e2018-01-07 11:07:19 -0800707 ///
708 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700709 pub struct FieldValue {
David Tolnay85b69a42017-12-27 20:43:10 -0500710 /// Attributes tagged on the field.
711 pub attrs: Vec<Attribute>,
712
713 /// Name or index of the field.
714 pub member: Member,
715
David Tolnay5d7098a2017-12-29 01:35:24 -0500716 /// The colon in `Struct { x: x }`. If written in shorthand like
717 /// `Struct { x }`, there is no colon.
David Tolnay85b69a42017-12-27 20:43:10 -0500718 pub colon_token: Option<Token![:]>,
Clar Charrd22b5702017-03-10 15:24:56 -0500719
Alex Crichton62a0a592017-05-22 13:58:53 -0700720 /// Value of the field.
721 pub expr: Expr,
Alex Crichton62a0a592017-05-22 13:58:53 -0700722 }
David Tolnay055a7042016-10-02 19:23:54 -0700723}
724
Michael Layzell734adb42017-06-07 16:58:31 -0400725#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700726ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800727 /// A lifetime labeling a `for`, `while`, or `loop`.
David Tolnay461d98e2018-01-07 11:07:19 -0800728 ///
729 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaybcd498f2017-12-29 12:02:33 -0500730 pub struct Label {
731 pub name: Lifetime,
732 pub colon_token: Token![:],
733 }
734}
735
736#[cfg(feature = "full")]
737ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800738 /// A braced block containing Rust statements.
David Tolnay461d98e2018-01-07 11:07:19 -0800739 ///
740 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700741 pub struct Block {
David Tolnay32954ef2017-12-26 22:43:16 -0500742 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700743 /// Statements in a block
744 pub stmts: Vec<Stmt>,
745 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700746}
747
Michael Layzell734adb42017-06-07 16:58:31 -0400748#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700749ast_enum! {
750 /// A statement, usually ending in a semicolon.
David Tolnay461d98e2018-01-07 11:07:19 -0800751 ///
752 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700753 pub enum Stmt {
754 /// A local (let) binding.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800755 Local(Local),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700756
Alex Crichton62a0a592017-05-22 13:58:53 -0700757 /// An item definition.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800758 Item(Item),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700759
Alex Crichton62a0a592017-05-22 13:58:53 -0700760 /// Expr without trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800761 Expr(Expr),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700762
David Tolnaya454c8f2018-01-07 01:01:10 -0800763 /// Expression with trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800764 Semi(Expr, Token![;]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700765 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700766}
767
Michael Layzell734adb42017-06-07 16:58:31 -0400768#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700769ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800770 /// A local `let` binding: `let x: u64 = s.parse()?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800771 ///
772 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700773 pub struct Local {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500774 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800775 pub let_token: Token![let],
David Tolnay5b5b7d22018-03-31 21:05:00 +0200776 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500777 pub ty: Option<(Token![:], Box<Type>)>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500778 pub init: Option<(Token![=], Box<Expr>)>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500779 pub semi_token: Token![;],
Alex Crichton62a0a592017-05-22 13:58:53 -0700780 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700781}
782
Michael Layzell734adb42017-06-07 16:58:31 -0400783#[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700784ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800785 /// A pattern in a local binding, function signature, match expression, or
786 /// various other places.
David Tolnay614a0142018-01-07 10:25:43 -0800787 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800788 /// *This type is available if Syn is built with the `"full"` feature.*
789 ///
David Tolnay614a0142018-01-07 10:25:43 -0800790 /// # Syntax tree enum
791 ///
792 /// This type is a [syntax tree enum].
793 ///
794 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
Alex Crichton62a0a592017-05-22 13:58:53 -0700795 // Clippy false positive
796 // https://github.com/Manishearth/rust-clippy/issues/1241
797 #[cfg_attr(feature = "cargo-clippy", allow(enum_variant_names))]
798 pub enum Pat {
David Tolnaya454c8f2018-01-07 01:01:10 -0800799 /// A pattern that matches any value: `_`.
David Tolnay461d98e2018-01-07 11:07:19 -0800800 ///
801 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700802 pub Wild(PatWild {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800803 pub underscore_token: Token![_],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700804 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700805
David Tolnaya454c8f2018-01-07 01:01:10 -0800806 /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
David Tolnay461d98e2018-01-07 11:07:19 -0800807 ///
808 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700809 pub Ident(PatIdent {
David Tolnay24237fb2017-12-29 02:15:26 -0500810 pub by_ref: Option<Token![ref]>,
811 pub mutability: Option<Token![mut]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700812 pub ident: Ident,
David Tolnay8b4d3022017-12-29 12:11:10 -0500813 pub subpat: Option<(Token![@], Box<Pat>)>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700814 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700815
David Tolnaya454c8f2018-01-07 01:01:10 -0800816 /// A struct or struct variant pattern: `Variant { x, y, .. }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800817 ///
818 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700819 pub Struct(PatStruct {
820 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500821 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500822 pub fields: Punctuated<FieldPat, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800823 pub dot2_token: Option<Token![..]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700824 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700825
David Tolnaya454c8f2018-01-07 01:01:10 -0800826 /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800827 ///
828 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700829 pub TupleStruct(PatTupleStruct {
830 pub path: Path,
831 pub pat: PatTuple,
832 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700833
David Tolnaya454c8f2018-01-07 01:01:10 -0800834 /// A path pattern like `Color::Red`, optionally qualified with a
835 /// self-type.
836 ///
837 /// Unquailfied path patterns can legally refer to variants, structs,
838 /// constants or associated constants. Quailfied path patterns like
839 /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
840 /// associated constants.
David Tolnay461d98e2018-01-07 11:07:19 -0800841 ///
842 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700843 pub Path(PatPath {
844 pub qself: Option<QSelf>,
845 pub path: Path,
846 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700847
David Tolnaya454c8f2018-01-07 01:01:10 -0800848 /// A tuple pattern: `(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800849 ///
850 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700851 pub Tuple(PatTuple {
David Tolnay32954ef2017-12-26 22:43:16 -0500852 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500853 pub front: Punctuated<Pat, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500854 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500855 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500856 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700857 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800858
859 /// A box pattern: `box v`.
David Tolnay461d98e2018-01-07 11:07:19 -0800860 ///
861 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700862 pub Box(PatBox {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800863 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500864 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700865 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800866
867 /// A reference pattern: `&mut (first, second)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800868 ///
869 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700870 pub Ref(PatRef {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800871 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500872 pub mutability: Option<Token![mut]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500873 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700874 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800875
876 /// A literal pattern: `0`.
877 ///
878 /// This holds an `Expr` rather than a `Lit` because negative numbers
879 /// are represented as an `Expr::Unary`.
David Tolnay461d98e2018-01-07 11:07:19 -0800880 ///
881 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700882 pub Lit(PatLit {
883 pub expr: Box<Expr>,
884 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800885
886 /// A range pattern: `1..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800887 ///
888 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700889 pub Range(PatRange {
890 pub lo: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700891 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500892 pub hi: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700893 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800894
895 /// A dynamically sized slice pattern: `[a, b, i.., y, z]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800896 ///
897 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700898 pub Slice(PatSlice {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500899 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500900 pub front: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700901 pub middle: Option<Box<Pat>>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500902 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500903 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500904 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700905 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800906
907 /// A macro in expression position.
David Tolnay461d98e2018-01-07 11:07:19 -0800908 ///
909 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay323279a2017-12-29 11:26:32 -0500910 pub Macro(PatMacro {
911 pub mac: Macro,
912 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800913
914 /// Tokens in pattern position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800915 ///
916 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500917 pub Verbatim(PatVerbatim #manual_extra_traits {
918 pub tts: TokenStream,
919 }),
920 }
921}
922
David Tolnayc43b44e2017-12-30 23:55:54 -0500923#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500924impl Eq for PatVerbatim {}
925
David Tolnayc43b44e2017-12-30 23:55:54 -0500926#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500927impl PartialEq for PatVerbatim {
928 fn eq(&self, other: &Self) -> bool {
929 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
930 }
931}
932
David Tolnayc43b44e2017-12-30 23:55:54 -0500933#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500934impl Hash for PatVerbatim {
935 fn hash<H>(&self, state: &mut H)
936 where
937 H: Hasher,
938 {
939 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700940 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700941}
942
Michael Layzell734adb42017-06-07 16:58:31 -0400943#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700944ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800945 /// One arm of a `match` expression: `0...10 => { return true; }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700946 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800947 /// As in:
Alex Crichton62a0a592017-05-22 13:58:53 -0700948 ///
David Tolnaybcf26022017-12-25 22:10:52 -0500949 /// ```rust
David Tolnaya454c8f2018-01-07 01:01:10 -0800950 /// # fn f() -> bool {
David Tolnaybcf26022017-12-25 22:10:52 -0500951 /// # let n = 0;
Alex Crichton62a0a592017-05-22 13:58:53 -0700952 /// match n {
David Tolnaya454c8f2018-01-07 01:01:10 -0800953 /// 0...10 => {
954 /// return true;
955 /// }
956 /// // ...
David Tolnaybcf26022017-12-25 22:10:52 -0500957 /// # _ => {}
Alex Crichton62a0a592017-05-22 13:58:53 -0700958 /// }
David Tolnaya454c8f2018-01-07 01:01:10 -0800959 /// # false
David Tolnaybcf26022017-12-25 22:10:52 -0500960 /// # }
Alex Crichton62a0a592017-05-22 13:58:53 -0700961 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800962 ///
963 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700964 pub struct Arm {
965 pub attrs: Vec<Attribute>,
David Tolnay18cc4d42018-03-31 18:47:20 +0200966 pub leading_vert: Option<Token![|]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500967 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500968 pub guard: Option<(Token![if], Box<Expr>)>,
David Tolnaydfb91432018-03-31 19:19:44 +0200969 pub fat_arrow_token: Token![=>],
Alex Crichton62a0a592017-05-22 13:58:53 -0700970 pub body: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800971 pub comma: Option<Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700972 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700973}
974
Michael Layzell734adb42017-06-07 16:58:31 -0400975#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700976ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800977 /// Limit types of a range, inclusive or exclusive.
David Tolnay461d98e2018-01-07 11:07:19 -0800978 ///
979 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton2e0229c2017-05-23 09:34:50 -0700980 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700981 pub enum RangeLimits {
David Tolnaya454c8f2018-01-07 01:01:10 -0800982 /// Inclusive at the beginning, exclusive at the end.
David Tolnayf8db7ba2017-11-11 22:52:16 -0800983 HalfOpen(Token![..]),
David Tolnaya454c8f2018-01-07 01:01:10 -0800984 /// Inclusive at the beginning and end.
David Tolnaybe55d7b2017-12-17 23:41:20 -0800985 Closed(Token![..=]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700986 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700987}
988
Michael Layzell734adb42017-06-07 16:58:31 -0400989#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700990ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800991 /// A single field in a struct pattern.
Alex Crichton62a0a592017-05-22 13:58:53 -0700992 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800993 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
994 /// the same as `x: x, y: ref y, z: ref mut z` but there is no colon token.
David Tolnay461d98e2018-01-07 11:07:19 -0800995 ///
996 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700997 pub struct FieldPat {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500998 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -0500999 pub member: Member,
David Tolnay4a3f59a2017-12-28 21:21:12 -05001000 pub colon_token: Option<Token![:]>,
Alex Crichton62a0a592017-05-22 13:58:53 -07001001 pub pat: Box<Pat>,
Alex Crichton62a0a592017-05-22 13:58:53 -07001002 }
David Tolnayf4bbbd92016-09-23 14:41:55 -07001003}
1004
Michael Layzell3936ceb2017-07-08 00:28:36 -04001005#[cfg(any(feature = "parsing", feature = "printing"))]
1006#[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -07001007fn requires_terminator(expr: &Expr) -> bool {
David Tolnay01218d12018-08-29 18:13:07 -07001008 // see https://github.com/rust-lang/rust/blob/eb8f2586e/src/libsyntax/parse/classify.rs#L17-L37
David Tolnay8c91b882017-12-28 23:04:32 -05001009 match *expr {
1010 Expr::Unsafe(..)
1011 | Expr::Block(..)
1012 | Expr::If(..)
1013 | Expr::IfLet(..)
1014 | Expr::Match(..)
1015 | Expr::While(..)
1016 | Expr::WhileLet(..)
1017 | Expr::Loop(..)
1018 | Expr::ForLoop(..)
David Tolnay02a9c6f2018-08-24 18:58:45 -04001019 | Expr::Async(..)
David Tolnayfb2dd4b2018-08-24 16:45:34 -04001020 | Expr::TryBlock(..) => false,
Alex Crichton03b30272017-08-28 09:35:24 -07001021 _ => true,
Michael Layzell3936ceb2017-07-08 00:28:36 -04001022 }
1023}
1024
David Tolnayb9c8e322016-09-23 20:48:37 -07001025#[cfg(feature = "parsing")]
1026pub mod parsing {
1027 use super::*;
David Tolnay60291082018-08-28 09:54:49 -07001028 use path;
David Tolnayb9c8e322016-09-23 20:48:37 -07001029
David Tolnay9389c382018-08-27 09:13:37 -07001030 use parse::{Parse, ParseStream, Result};
Michael Layzell734adb42017-06-07 16:58:31 -04001031 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001032 use synom::ext::IdentExt;
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001033
David Tolnaybcf26022017-12-25 22:10:52 -05001034 // When we're parsing expressions which occur before blocks, like in an if
1035 // statement's condition, we cannot parse a struct literal.
1036 //
1037 // Struct literals are ambiguous in certain positions
1038 // https://github.com/rust-lang/rfcs/pull/92
David Tolnay9389c382018-08-27 09:13:37 -07001039 #[derive(Copy, Clone)]
1040 pub struct AllowStruct(bool);
1041
David Tolnay01218d12018-08-29 18:13:07 -07001042 #[derive(Copy, Clone, PartialEq, PartialOrd)]
1043 enum Precedence {
1044 Any,
1045 Assign,
1046 Placement,
1047 Range,
1048 Or,
1049 And,
1050 Compare,
1051 BitOr,
1052 BitXor,
1053 BitAnd,
1054 Shift,
1055 Arithmetic,
1056 Term,
1057 Cast,
1058 }
1059
1060 impl Precedence {
1061 fn of(op: &BinOp) -> Self {
1062 match *op {
1063 BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic,
1064 BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term,
1065 BinOp::And(_) => Precedence::And,
1066 BinOp::Or(_) => Precedence::Or,
1067 BinOp::BitXor(_) => Precedence::BitXor,
1068 BinOp::BitAnd(_) => Precedence::BitAnd,
1069 BinOp::BitOr(_) => Precedence::BitOr,
1070 BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
1071 BinOp::Eq(_) | BinOp::Lt(_) | BinOp::Le(_) | BinOp::Ne(_) | BinOp::Ge(_) | BinOp::Gt(_) => Precedence::Compare,
1072 BinOp::AddEq(_) | BinOp::SubEq(_) | BinOp::MulEq(_) | BinOp::DivEq(_) | BinOp::RemEq(_) | BinOp::BitXorEq(_) | BinOp::BitAndEq(_) | BinOp::BitOrEq(_) | BinOp::ShlEq(_) | BinOp::ShrEq(_) => Precedence::Assign,
1073 }
1074 }
1075 }
1076
David Tolnay9389c382018-08-27 09:13:37 -07001077 impl Parse for Expr {
1078 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001079 ambiguous_expr(input, AllowStruct(true))
Alex Crichton954046c2017-05-30 21:49:42 -07001080 }
1081 }
1082
Michael Layzell734adb42017-06-07 16:58:31 -04001083 #[cfg(feature = "full")]
David Tolnay9fb0aed2018-08-27 10:23:12 -07001084 fn expr_no_struct(input: ParseStream) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001085 ambiguous_expr(input, AllowStruct(false))
David Tolnay9fb0aed2018-08-27 10:23:12 -07001086 }
David Tolnayaf2557e2016-10-24 11:52:21 -07001087
David Tolnay01218d12018-08-29 18:13:07 -07001088 #[cfg(feature = "full")]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001089 fn parse_expr(input: ParseStream, mut lhs: Expr, allow_struct: AllowStruct, base: Precedence) -> Result<Expr> {
David Tolnay01218d12018-08-29 18:13:07 -07001090 loop {
1091 if input.fork().parse::<BinOp>().ok().map_or(false, |op| Precedence::of(&op) >= base) {
1092 let op: BinOp = input.parse()?;
1093 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001094 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001095 loop {
1096 let next = peek_precedence(input);
1097 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001098 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001099 } else {
1100 break;
1101 }
1102 }
1103 lhs = Expr::Binary(ExprBinary {
1104 attrs: Vec::new(),
1105 left: Box::new(lhs),
1106 op: op,
1107 right: Box::new(rhs),
1108 });
1109 } else if Precedence::Assign >= base && input.peek(Token![=]) && !input.peek(Token![==]) && !input.peek(Token![=>]) {
1110 let eq_token: Token![=] = input.parse()?;
David Tolnay7d2e1db2018-08-30 11:49:04 -07001111 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001112 loop {
1113 let next = peek_precedence(input);
1114 if next >= Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001115 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001116 } else {
1117 break;
1118 }
1119 }
1120 lhs = Expr::Assign(ExprAssign {
1121 attrs: Vec::new(),
1122 left: Box::new(lhs),
1123 eq_token: eq_token,
1124 right: Box::new(rhs),
1125 });
1126 } else if Precedence::Placement >= base && input.peek(Token![<-]) {
1127 let arrow_token: Token![<-] = input.parse()?;
David Tolnay7d2e1db2018-08-30 11:49:04 -07001128 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001129 loop {
1130 let next = peek_precedence(input);
1131 if next > Precedence::Placement {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001132 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001133 } else {
1134 break;
1135 }
1136 }
1137 lhs = Expr::InPlace(ExprInPlace {
1138 attrs: Vec::new(),
1139 place: Box::new(lhs),
1140 arrow_token: arrow_token,
1141 value: Box::new(rhs),
1142 });
1143 } else if Precedence::Range >= base && input.peek(Token![..]) {
1144 let limits: RangeLimits = input.parse()?;
1145 let rhs = if input.is_empty()
1146 || input.peek(Token![,])
1147 || input.peek(Token![;])
1148 || !allow_struct.0 && input.peek(token::Brace)
1149 {
1150 None
1151 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001152 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001153 loop {
1154 let next = peek_precedence(input);
1155 if next > Precedence::Range {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001156 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001157 } else {
1158 break;
1159 }
1160 }
1161 Some(rhs)
1162 };
1163 lhs = Expr::Range(ExprRange {
1164 attrs: Vec::new(),
1165 from: Some(Box::new(lhs)),
1166 limits: limits,
1167 to: rhs.map(Box::new),
1168 });
1169 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1170 let as_token: Token![as] = input.parse()?;
1171 let ty = input.call(Type::without_plus)?;
1172 lhs = Expr::Cast(ExprCast {
1173 attrs: Vec::new(),
1174 expr: Box::new(lhs),
1175 as_token: as_token,
1176 ty: Box::new(ty),
1177 });
1178 } else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) {
1179 let colon_token: Token![:] = input.parse()?;
1180 let ty = input.call(Type::without_plus)?;
1181 lhs = Expr::Type(ExprType {
1182 attrs: Vec::new(),
1183 expr: Box::new(lhs),
1184 colon_token: colon_token,
1185 ty: Box::new(ty),
1186 });
1187 } else {
1188 break;
1189 }
1190 }
1191 Ok(lhs)
1192 }
1193
David Tolnay3e541292018-08-30 11:42:15 -07001194 #[cfg(not(feature = "full"))]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001195 fn parse_expr(input: ParseStream, mut lhs: Expr, allow_struct: AllowStruct, base: Precedence) -> Result<Expr> {
David Tolnay3e541292018-08-30 11:42:15 -07001196 loop {
1197 if input.fork().parse::<BinOp>().ok().map_or(false, |op| Precedence::of(&op) >= base) {
1198 let op: BinOp = input.parse()?;
1199 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001200 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay3e541292018-08-30 11:42:15 -07001201 loop {
1202 let next = peek_precedence(input);
1203 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001204 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay3e541292018-08-30 11:42:15 -07001205 } else {
1206 break;
1207 }
1208 }
1209 lhs = Expr::Binary(ExprBinary {
1210 attrs: Vec::new(),
1211 left: Box::new(lhs),
1212 op: op,
1213 right: Box::new(rhs),
1214 });
1215 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1216 let as_token: Token![as] = input.parse()?;
1217 let ty = input.call(Type::without_plus)?;
1218 lhs = Expr::Cast(ExprCast {
1219 attrs: Vec::new(),
1220 expr: Box::new(lhs),
1221 as_token: as_token,
1222 ty: Box::new(ty),
1223 });
1224 } else {
1225 break;
1226 }
1227 }
1228 Ok(lhs)
1229 }
1230
David Tolnay01218d12018-08-29 18:13:07 -07001231 fn peek_precedence(input: ParseStream) -> Precedence {
1232 if let Ok(op) = input.fork().parse() {
1233 Precedence::of(&op)
David Tolnay3e541292018-08-30 11:42:15 -07001234 } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
David Tolnay01218d12018-08-29 18:13:07 -07001235 Precedence::Assign
1236 } else if input.peek(Token![<-]) {
1237 Precedence::Placement
1238 } else if input.peek(Token![..]) {
1239 Precedence::Range
1240 } else if input.peek(Token![as]) || input.peek(Token![:]) && !input.peek(Token![::]) {
1241 Precedence::Cast
1242 } else {
1243 Precedence::Any
1244 }
1245 }
1246
David Tolnaybcf26022017-12-25 22:10:52 -05001247 // Parse an arbitrary expression.
David Tolnay60291082018-08-28 09:54:49 -07001248 fn ambiguous_expr(
1249 input: ParseStream,
1250 allow_struct: AllowStruct,
David Tolnay60291082018-08-28 09:54:49 -07001251 ) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001252 let lhs = unary_expr(input, allow_struct)?;
1253 parse_expr(input, lhs, allow_struct, Precedence::Any)
Michael Layzellb78f3b52017-06-04 19:03:03 -04001254 }
1255
David Tolnaybcf26022017-12-25 22:10:52 -05001256 // <UnOp> <trailer>
1257 // & <trailer>
1258 // &mut <trailer>
1259 // box <trailer>
Michael Layzell734adb42017-06-07 16:58:31 -04001260 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001261 fn unary_expr(
1262 input: ParseStream,
1263 allow_struct: AllowStruct,
David Tolnay60291082018-08-28 09:54:49 -07001264 ) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001265 let ahead = input.fork();
1266 ahead.call(Attribute::parse_outer)?;
1267 if ahead.peek(Token![&])
1268 || ahead.peek(Token![box])
1269 || ahead.peek(Token![*])
1270 || ahead.peek(Token![!])
1271 || ahead.peek(Token![-])
1272 {
1273 let attrs = input.call(Attribute::parse_outer)?;
1274 if input.peek(Token![&]) {
1275 Ok(Expr::Reference(ExprReference {
1276 attrs: attrs,
1277 and_token: input.parse()?,
1278 mutability: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001279 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001280 }))
1281 } else if input.peek(Token![box]) {
1282 Ok(Expr::Box(ExprBox {
1283 attrs: attrs,
1284 box_token: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001285 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001286 }))
1287 } else {
1288 Ok(Expr::Unary(ExprUnary {
1289 attrs: attrs,
1290 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001291 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001292 }))
1293 }
1294 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001295 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001296 }
1297 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001298
Michael Layzell734adb42017-06-07 16:58:31 -04001299 // XXX: This duplication is ugly
1300 #[cfg(not(feature = "full"))]
David Tolnay60291082018-08-28 09:54:49 -07001301 fn unary_expr(
1302 input: ParseStream,
1303 allow_struct: AllowStruct,
David Tolnay60291082018-08-28 09:54:49 -07001304 ) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001305 let ahead = input.fork();
1306 ahead.call(Attribute::parse_outer)?;
1307 if ahead.peek(Token![*]) || ahead.peek(Token![!]) || ahead.peek(Token![-]) {
1308 Ok(Expr::Unary(ExprUnary {
1309 attrs: input.call(Attribute::parse_outer)?,
1310 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001311 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001312 }))
1313 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001314 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001315 }
1316 }
Michael Layzell734adb42017-06-07 16:58:31 -04001317
David Tolnayd997aef2018-07-21 18:42:31 -07001318 #[cfg(feature = "full")]
David Tolnay5d314dc2018-07-21 16:40:01 -07001319 fn take_outer(attrs: &mut Vec<Attribute>) -> Vec<Attribute> {
1320 let mut outer = Vec::new();
1321 let mut inner = Vec::new();
1322 for attr in mem::replace(attrs, Vec::new()) {
1323 match attr.style {
1324 AttrStyle::Outer => outer.push(attr),
1325 AttrStyle::Inner(_) => inner.push(attr),
1326 }
1327 }
1328 *attrs = inner;
1329 outer
1330 }
1331
David Tolnaybcf26022017-12-25 22:10:52 -05001332 // <atom> (..<args>) ...
1333 // <atom> . <ident> (..<args>) ...
1334 // <atom> . <ident> ...
1335 // <atom> . <lit> ...
1336 // <atom> [ <expr> ] ...
1337 // <atom> ? ...
Michael Layzell734adb42017-06-07 16:58:31 -04001338 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001339 fn trailer_expr(
1340 input: ParseStream,
1341 allow_struct: AllowStruct,
David Tolnay60291082018-08-28 09:54:49 -07001342 ) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001343 let mut e = atom_expr(input, allow_struct)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001344
1345 let mut attrs = e.replace_attrs(Vec::new());
1346 let outer_attrs = take_outer(&mut attrs);
1347 e.replace_attrs(attrs);
1348
David Tolnay01218d12018-08-29 18:13:07 -07001349 e = trailer_helper(input, e)?;
1350
1351 let mut attrs = outer_attrs;
1352 attrs.extend(e.replace_attrs(Vec::new()));
1353 e.replace_attrs(attrs);
1354 Ok(e)
1355 }
1356
1357 #[cfg(feature = "full")]
1358 fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
David Tolnay1501f7e2018-08-27 14:21:03 -07001359 loop {
1360 if input.peek(token::Paren) {
1361 let content;
1362 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001363 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001364 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001365 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001366 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001367 });
1368 } else if input.peek(Token![.]) && !input.peek(Token![..]) {
1369 let dot_token: Token![.] = input.parse()?;
1370 let member: Member = input.parse()?;
1371 let turbofish = if member.is_named() && input.peek(Token![::]) {
1372 Some(MethodTurbofish {
1373 colon2_token: input.parse()?,
1374 lt_token: input.parse()?,
1375 args: {
1376 let mut args = Punctuated::new();
1377 loop {
1378 if input.peek(Token![>]) {
1379 break;
1380 }
David Tolnay310b3262018-08-30 15:33:00 -07001381 let value = input.call(generic_method_argument)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001382 args.push_value(value);
1383 if input.peek(Token![>]) {
1384 break;
1385 }
1386 let punct = input.parse()?;
1387 args.push_punct(punct);
1388 }
1389 args
1390 },
1391 gt_token: input.parse()?,
1392 })
1393 } else {
1394 None
1395 };
1396
1397 if turbofish.is_some() || input.peek(token::Paren) {
1398 if let Member::Named(method) = member {
1399 let content;
1400 e = Expr::MethodCall(ExprMethodCall {
1401 attrs: Vec::new(),
1402 receiver: Box::new(e),
1403 dot_token: dot_token,
1404 method: method,
1405 turbofish: turbofish,
1406 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001407 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001408 });
1409 continue;
1410 }
1411 }
1412
1413 e = Expr::Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -05001414 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001415 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001416 dot_token: dot_token,
David Tolnay85b69a42017-12-27 20:43:10 -05001417 member: member,
David Tolnay1501f7e2018-08-27 14:21:03 -07001418 });
1419 } else if input.peek(token::Bracket) {
1420 let content;
1421 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001422 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001423 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001424 bracket_token: bracketed!(content in input),
1425 index: content.parse()?,
1426 });
1427 } else if input.peek(Token![?]) {
1428 e = Expr::Try(ExprTry {
David Tolnay8c91b882017-12-28 23:04:32 -05001429 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001430 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001431 question_token: input.parse()?,
1432 });
1433 } else {
1434 break;
1435 }
1436 }
David Tolnay1501f7e2018-08-27 14:21:03 -07001437 Ok(e)
1438 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001439
Michael Layzell734adb42017-06-07 16:58:31 -04001440 // XXX: Duplication == ugly
1441 #[cfg(not(feature = "full"))]
David Tolnay60291082018-08-28 09:54:49 -07001442 fn trailer_expr(
1443 input: ParseStream,
1444 allow_struct: AllowStruct,
David Tolnay60291082018-08-28 09:54:49 -07001445 ) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001446 let mut e = atom_expr(input, allow_struct)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001447
1448 loop {
1449 if input.peek(token::Paren) {
1450 let content;
1451 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001452 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001453 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001454 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001455 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001456 });
1457 } else if input.peek(Token![.]) {
1458 e = Expr::Field(ExprField {
David Tolnayd5147742018-06-30 10:09:52 -07001459 attrs: Vec::new(),
1460 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001461 dot_token: input.parse()?,
1462 member: input.parse()?,
1463 });
1464 } else if input.peek(token::Bracket) {
1465 let content;
1466 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001467 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001468 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001469 bracket_token: bracketed!(content in input),
1470 index: content.parse()?,
1471 });
1472 } else {
1473 break;
1474 }
1475 }
1476
1477 Ok(e)
1478 }
Michael Layzell734adb42017-06-07 16:58:31 -04001479
David Tolnaya454c8f2018-01-07 01:01:10 -08001480 // Parse all atomic expressions which don't have to worry about precedence
David Tolnaybcf26022017-12-25 22:10:52 -05001481 // interactions, as they are fully contained.
Michael Layzell734adb42017-06-07 16:58:31 -04001482 #[cfg(feature = "full")]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001483 fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001484 if input.peek(token::Group) {
David Tolnay310b3262018-08-30 15:33:00 -07001485 return input.call(expr_group).map(Expr::Group);
David Tolnay6e1e5052018-08-30 10:21:48 -07001486 }
1487
1488 let mut attrs = input.call(Attribute::parse_outer)?;
1489
1490 let mut expr = if input.peek(token::Group) {
David Tolnay310b3262018-08-30 15:33:00 -07001491 Expr::Group(input.call(expr_group)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001492 } else if input.peek(Lit) {
David Tolnay310b3262018-08-30 15:33:00 -07001493 Expr::Lit(input.call(expr_lit)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001494 } else if input.peek(Token![async])
1495 && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
1496 {
David Tolnay310b3262018-08-30 15:33:00 -07001497 Expr::Async(input.call(expr_async)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001498 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001499 Expr::TryBlock(input.call(expr_try_block)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001500 } else if input.peek(Token![|])
1501 || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1502 || input.peek(Token![static])
1503 || input.peek(Token![move])
1504 {
1505 Expr::Closure(expr_closure(input, allow_struct)?)
1506 } else if input.peek(Ident)
1507 || input.peek(Token![::])
1508 || input.peek(Token![<])
1509 || input.peek(Token![self])
1510 || input.peek(Token![Self])
1511 || input.peek(Token![super])
1512 || input.peek(Token![extern])
1513 || input.peek(Token![crate])
1514 {
1515 path_or_macro_or_struct(input, allow_struct)?
1516 } else if input.peek(token::Paren) {
1517 paren_or_tuple(input)?
1518 } else if input.peek(Token![break]) {
1519 Expr::Break(expr_break(input, allow_struct)?)
1520 } else if input.peek(Token![continue]) {
David Tolnay310b3262018-08-30 15:33:00 -07001521 Expr::Continue(input.call(expr_continue)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001522 } else if input.peek(Token![return]) {
1523 Expr::Return(expr_ret(input, allow_struct)?)
1524 } else if input.peek(token::Bracket) {
1525 array_or_repeat(input)?
1526 } else if input.peek(Token![if]) {
1527 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001528 Expr::IfLet(input.call(expr_if_let)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001529 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001530 Expr::If(input.call(expr_if)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001531 }
1532 } else if input.peek(Token![while]) {
1533 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001534 Expr::WhileLet(input.call(expr_while_let)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001535 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001536 Expr::While(input.call(expr_while)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001537 }
1538 } else if input.peek(Token![for]) {
David Tolnay310b3262018-08-30 15:33:00 -07001539 Expr::ForLoop(input.call(expr_for_loop)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001540 } else if input.peek(Token![loop]) {
David Tolnay310b3262018-08-30 15:33:00 -07001541 Expr::Loop(input.call(expr_loop)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001542 } else if input.peek(Token![match]) {
David Tolnay310b3262018-08-30 15:33:00 -07001543 Expr::Match(input.call(expr_match)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001544 } else if input.peek(Token![yield]) {
David Tolnay310b3262018-08-30 15:33:00 -07001545 Expr::Yield(input.call(expr_yield)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001546 } else if input.peek(Token![unsafe]) {
David Tolnay310b3262018-08-30 15:33:00 -07001547 Expr::Unsafe(input.call(expr_unsafe)?)
David Tolnay7d2e1db2018-08-30 11:49:04 -07001548 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001549 Expr::Block(input.call(expr_block)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001550 } else if input.peek(Token![..]) {
1551 Expr::Range(expr_range(input, allow_struct)?)
1552 } else if input.peek(Lifetime) {
1553 let the_label: Label = input.parse()?;
1554 let mut expr = if input.peek(Token![while]) {
1555 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001556 Expr::WhileLet(input.call(expr_while_let)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001557 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001558 Expr::While(input.call(expr_while)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001559 }
1560 } else if input.peek(Token![for]) {
David Tolnay310b3262018-08-30 15:33:00 -07001561 Expr::ForLoop(input.call(expr_for_loop)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001562 } else if input.peek(Token![loop]) {
David Tolnay310b3262018-08-30 15:33:00 -07001563 Expr::Loop(input.call(expr_loop)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001564 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001565 Expr::Block(input.call(expr_block)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001566 } else {
1567 return Err(input.error("expected loop or block expression"));
1568 };
1569 match expr {
1570 Expr::WhileLet(ExprWhileLet { ref mut label, .. }) |
1571 Expr::While(ExprWhile { ref mut label, .. }) |
1572 Expr::ForLoop(ExprForLoop { ref mut label, .. }) |
1573 Expr::Loop(ExprLoop { ref mut label, .. }) |
1574 Expr::Block(ExprBlock { ref mut label, .. }) => *label = Some(the_label),
1575 _ => unreachable!(),
1576 }
1577 expr
1578 } else {
1579 return Err(input.error("expected expression"));
1580 };
1581
1582 attrs.extend(expr.replace_attrs(Vec::new()));
1583 expr.replace_attrs(attrs);
1584 Ok(expr)
1585 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001586
Michael Layzell734adb42017-06-07 16:58:31 -04001587 #[cfg(not(feature = "full"))]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001588 fn atom_expr(input: ParseStream, _allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001589 if input.peek(Lit) {
David Tolnay310b3262018-08-30 15:33:00 -07001590 input.call(expr_lit).map(Expr::Lit)
David Tolnay6e1e5052018-08-30 10:21:48 -07001591 } else if input.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07001592 input.call(expr_paren).map(Expr::Paren)
David Tolnay6e1e5052018-08-30 10:21:48 -07001593 } else if input.peek(Ident)
1594 || input.peek(Token![::])
1595 || input.peek(Token![<])
1596 || input.peek(Token![self])
1597 || input.peek(Token![Self])
1598 || input.peek(Token![super])
1599 || input.peek(Token![extern])
1600 || input.peek(Token![crate])
1601 {
1602 input.parse().map(Expr::Path)
1603 } else {
1604 Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
1605 }
1606 }
1607
1608 #[cfg(feature = "full")]
1609 fn path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1610 let expr: ExprPath = input.parse()?;
1611 if expr.qself.is_some() {
1612 return Ok(Expr::Path(expr));
1613 }
1614
1615 if input.peek(Token![!]) && !input.peek(Token![!=]) {
1616 let mut contains_arguments = false;
1617 for segment in &expr.path.segments {
1618 match segment.arguments {
1619 PathArguments::None => {}
1620 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
1621 contains_arguments = true;
1622 }
1623 }
1624 }
1625
1626 if !contains_arguments {
1627 let bang_token: Token![!] = input.parse()?;
1628 let (delimiter, tts) = mac::parse_delimiter(input)?;
1629 return Ok(Expr::Macro(ExprMacro {
1630 attrs: Vec::new(),
1631 mac: Macro {
1632 path: expr.path,
1633 bang_token: bang_token,
1634 delimiter: delimiter,
1635 tts: tts,
1636 },
1637 }));
1638 }
1639 }
1640
1641 if allow_struct.0 && input.peek(token::Brace) {
1642 let outer_attrs = Vec::new();
1643 expr_struct_helper(input, outer_attrs, expr.path).map(Expr::Struct)
1644 } else {
1645 Ok(Expr::Path(expr))
1646 }
1647 }
1648
1649 #[cfg(feature = "full")]
1650 fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
1651 let content;
1652 let paren_token = parenthesized!(content in input);
1653 let inner_attrs = content.call(Attribute::parse_inner)?;
1654 if content.is_empty() {
1655 return Ok(Expr::Tuple(ExprTuple {
1656 attrs: inner_attrs,
1657 paren_token: paren_token,
1658 elems: Punctuated::new(),
1659 }));
1660 }
1661
1662 let first: Expr = content.parse()?;
1663 if content.is_empty() {
1664 return Ok(Expr::Paren(ExprParen {
1665 attrs: inner_attrs,
1666 paren_token: paren_token,
1667 expr: Box::new(first),
1668 }));
1669 }
1670
1671 let mut elems = Punctuated::new();
1672 elems.push_value(first);
1673 while !content.is_empty() {
1674 let punct = content.parse()?;
1675 elems.push_punct(punct);
1676 if content.is_empty() {
1677 break;
1678 }
1679 let value = content.parse()?;
1680 elems.push_value(value);
1681 }
1682 Ok(Expr::Tuple(ExprTuple {
1683 attrs: inner_attrs,
1684 paren_token: paren_token,
1685 elems: elems,
1686 }))
1687 }
1688
1689 #[cfg(feature = "full")]
1690 fn array_or_repeat(input: ParseStream) -> Result<Expr> {
1691 let content;
1692 let bracket_token = bracketed!(content in input);
1693 let inner_attrs = content.call(Attribute::parse_inner)?;
1694 if content.is_empty() {
1695 return Ok(Expr::Array(ExprArray {
1696 attrs: inner_attrs,
1697 bracket_token: bracket_token,
1698 elems: Punctuated::new(),
1699 }));
1700 }
1701
1702 let first: Expr = content.parse()?;
1703 if content.is_empty() || content.peek(Token![,]) {
1704 let mut elems = Punctuated::new();
1705 elems.push_value(first);
1706 while !content.is_empty() {
1707 let punct = content.parse()?;
1708 elems.push_punct(punct);
1709 if content.is_empty() {
1710 break;
1711 }
1712 let value = content.parse()?;
1713 elems.push_value(value);
1714 }
1715 Ok(Expr::Array(ExprArray {
1716 attrs: inner_attrs,
1717 bracket_token: bracket_token,
1718 elems: elems,
1719 }))
1720 } else if content.peek(Token![;]) {
1721 let semi_token: Token![;] = content.parse()?;
1722 let len: Expr = content.parse()?;
1723 Ok(Expr::Repeat(ExprRepeat {
1724 attrs: inner_attrs,
1725 bracket_token: bracket_token,
1726 expr: Box::new(first),
1727 semi_token: semi_token,
1728 len: Box::new(len),
1729 }))
1730 } else {
1731 Err(content.error("expected `,` or `;`"))
1732 }
1733 }
Michael Layzell734adb42017-06-07 16:58:31 -04001734
Michael Layzell734adb42017-06-07 16:58:31 -04001735 #[cfg(feature = "full")]
David Tolnay01218d12018-08-29 18:13:07 -07001736 fn expr_early(input: ParseStream) -> Result<Expr> {
1737 let mut attrs = input.call(Attribute::parse_outer)?;
1738 let mut expr = if input.peek(Token![if]) {
1739 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001740 Expr::IfLet(input.call(expr_if_let)?)
David Tolnay01218d12018-08-29 18:13:07 -07001741 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001742 Expr::If(input.call(expr_if)?)
David Tolnay01218d12018-08-29 18:13:07 -07001743 }
1744 } else if input.peek(Token![while]) {
1745 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001746 Expr::WhileLet(input.call(expr_while_let)?)
David Tolnay01218d12018-08-29 18:13:07 -07001747 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001748 Expr::While(input.call(expr_while)?)
David Tolnay01218d12018-08-29 18:13:07 -07001749 }
1750 } else if input.peek(Token![for]) {
David Tolnay310b3262018-08-30 15:33:00 -07001751 Expr::ForLoop(input.call(expr_for_loop)?)
David Tolnay01218d12018-08-29 18:13:07 -07001752 } else if input.peek(Token![loop]) {
David Tolnay310b3262018-08-30 15:33:00 -07001753 Expr::Loop(input.call(expr_loop)?)
David Tolnay01218d12018-08-29 18:13:07 -07001754 } else if input.peek(Token![match]) {
David Tolnay310b3262018-08-30 15:33:00 -07001755 Expr::Match(input.call(expr_match)?)
David Tolnay01218d12018-08-29 18:13:07 -07001756 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001757 Expr::TryBlock(input.call(expr_try_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001758 } else if input.peek(Token![unsafe]) {
David Tolnay310b3262018-08-30 15:33:00 -07001759 Expr::Unsafe(input.call(expr_unsafe)?)
David Tolnay01218d12018-08-29 18:13:07 -07001760 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001761 Expr::Block(input.call(expr_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001762 } else {
1763 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001764 let mut expr = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001765
1766 attrs.extend(expr.replace_attrs(Vec::new()));
1767 expr.replace_attrs(attrs);
1768
David Tolnay7d2e1db2018-08-30 11:49:04 -07001769 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001770 };
1771
1772 if input.peek(Token![.]) || input.peek(Token![?]) {
1773 expr = trailer_helper(input, expr)?;
1774
1775 attrs.extend(expr.replace_attrs(Vec::new()));
1776 expr.replace_attrs(attrs);
1777
1778 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001779 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001780 }
1781
1782 attrs.extend(expr.replace_attrs(Vec::new()));
1783 expr.replace_attrs(attrs);
1784 Ok(expr)
1785 }
Michael Layzell35418782017-06-07 09:20:25 -04001786
David Tolnay310b3262018-08-30 15:33:00 -07001787 pub fn expr_lit(input: ParseStream) -> Result<ExprLit> {
1788 Ok(ExprLit {
1789 attrs: Vec::new(),
1790 lit: input.parse()?,
1791 })
David Tolnay8c91b882017-12-28 23:04:32 -05001792 }
1793
1794 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001795 fn expr_group(input: ParseStream) -> Result<ExprGroup> {
1796 let content;
1797 Ok(ExprGroup {
1798 attrs: Vec::new(),
1799 group_token: grouped!(content in input),
1800 expr: content.parse()?,
1801 })
1802 }
1803
1804 #[cfg(not(feature = "full"))]
1805 fn expr_paren(input: ParseStream) -> Result<ExprParen> {
1806 let content;
1807 Ok(ExprParen {
1808 attrs: Vec::new(),
1809 paren_token: parenthesized!(content in input),
1810 expr: content.parse()?,
1811 })
David Tolnay8c91b882017-12-28 23:04:32 -05001812 }
1813
David Tolnaye98775f2017-12-28 23:17:00 -05001814 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001815 fn generic_method_argument(input: ParseStream) -> Result<GenericMethodArgument> {
David Tolnayd60cfec2017-12-29 00:21:38 -05001816 // TODO parse const generics as well
David Tolnay8db2d662018-08-30 17:40:59 -07001817 input.parse().map(GenericMethodArgument::Type)
David Tolnayd60cfec2017-12-29 00:21:38 -05001818 }
1819
1820 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001821 fn expr_if_let(input: ParseStream) -> Result<ExprIfLet> {
1822 Ok(ExprIfLet {
1823 attrs: Vec::new(),
1824 if_token: input.parse()?,
1825 let_token: input.parse()?,
1826 pats: {
1827 let mut pats = Punctuated::new();
1828 let value: Pat = input.parse()?;
1829 pats.push_value(value);
1830 while input.peek(Token![|])
1831 && !input.peek(Token![||])
1832 && !input.peek(Token![|=])
1833 {
1834 let punct = input.parse()?;
1835 pats.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07001836 let value: Pat = input.parse()?;
1837 pats.push_value(value);
David Tolnay310b3262018-08-30 15:33:00 -07001838 }
1839 pats
1840 },
1841 eq_token: input.parse()?,
1842 expr: Box::new(input.call(expr_no_struct)?),
1843 then_branch: input.parse()?,
1844 else_branch: {
1845 if input.peek(Token![else]) {
1846 Some(input.call(else_block)?)
1847 } else {
1848 None
1849 }
1850 },
1851 })
David Tolnay29f9ce12016-10-02 20:58:40 -07001852 }
1853
Michael Layzell734adb42017-06-07 16:58:31 -04001854 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001855 fn expr_if(input: ParseStream) -> Result<ExprIf> {
1856 Ok(ExprIf {
1857 attrs: Vec::new(),
1858 if_token: input.parse()?,
1859 cond: Box::new(input.call(expr_no_struct)?),
1860 then_branch: input.parse()?,
1861 else_branch: {
1862 if input.peek(Token![else]) {
1863 Some(input.call(else_block)?)
1864 } else {
1865 None
1866 }
1867 },
1868 })
Alex Crichton954046c2017-05-30 21:49:42 -07001869 }
David Tolnaybb6feae2016-10-02 21:25:20 -07001870
Michael Layzell734adb42017-06-07 16:58:31 -04001871 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001872 fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
1873 let else_token: Token![else] = input.parse()?;
1874
1875 let lookahead = input.lookahead1();
1876 let else_branch = if input.peek(Token![if]) {
1877 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001878 input.call(expr_if_let).map(Expr::IfLet)?
David Tolnay60291082018-08-28 09:54:49 -07001879 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001880 input.call(expr_if).map(Expr::If)?
David Tolnay60291082018-08-28 09:54:49 -07001881 }
1882 } else if input.peek(token::Brace) {
1883 Expr::Block(ExprBlock {
1884 attrs: Vec::new(),
1885 label: None,
1886 block: input.parse()?,
1887 })
1888 } else {
1889 return Err(lookahead.error());
1890 };
1891
1892 Ok((else_token, Box::new(else_branch)))
1893 }
David Tolnay939766a2016-09-23 23:48:12 -07001894
Michael Layzell734adb42017-06-07 16:58:31 -04001895 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001896 fn expr_for_loop(input: ParseStream) -> Result<ExprForLoop> {
1897 let label: Option<Label> = input.parse()?;
1898 let for_token: Token![for] = input.parse()?;
1899 let pat: Pat = input.parse()?;
1900 let in_token: Token![in] = input.parse()?;
1901 let expr: Expr = input.call(expr_no_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07001902
David Tolnay310b3262018-08-30 15:33:00 -07001903 let content;
1904 let brace_token = braced!(content in input);
1905 let inner_attrs = content.call(Attribute::parse_inner)?;
1906 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07001907
David Tolnay310b3262018-08-30 15:33:00 -07001908 Ok(ExprForLoop {
1909 attrs: inner_attrs,
1910 label: label,
1911 for_token: for_token,
1912 pat: Box::new(pat),
1913 in_token: in_token,
1914 expr: Box::new(expr),
1915 body: Block {
David Tolnay60291082018-08-28 09:54:49 -07001916 brace_token: brace_token,
David Tolnay310b3262018-08-30 15:33:00 -07001917 stmts: stmts,
1918 },
1919 })
Alex Crichton954046c2017-05-30 21:49:42 -07001920 }
David Tolnay1978c672016-10-27 22:05:52 -07001921
Michael Layzell734adb42017-06-07 16:58:31 -04001922 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001923 fn expr_loop(input: ParseStream) -> Result<ExprLoop> {
1924 let label: Option<Label> = input.parse()?;
1925 let loop_token: Token![loop] = input.parse()?;
1926
1927 let content;
1928 let brace_token = braced!(content in input);
1929 let inner_attrs = content.call(Attribute::parse_inner)?;
1930 let stmts = content.call(Block::parse_within)?;
1931
1932 Ok(ExprLoop {
1933 attrs: inner_attrs,
1934 label: label,
1935 loop_token: loop_token,
1936 body: Block {
1937 brace_token: brace_token,
1938 stmts: stmts,
1939 },
1940 })
Alex Crichton954046c2017-05-30 21:49:42 -07001941 }
Arnavion02ef13f2017-04-25 00:54:31 -07001942
Michael Layzell734adb42017-06-07 16:58:31 -04001943 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001944 fn expr_match(input: ParseStream) -> Result<ExprMatch> {
1945 let match_token: Token![match] = input.parse()?;
1946 let expr = expr_no_struct(input)?;
1947
1948 let content;
1949 let brace_token = braced!(content in input);
1950 let inner_attrs = content.call(Attribute::parse_inner)?;
1951
1952 let mut arms = Vec::new();
1953 while !content.is_empty() {
1954 arms.push(content.call(match_arm)?);
1955 }
1956
1957 Ok(ExprMatch {
1958 attrs: inner_attrs,
1959 match_token: match_token,
1960 expr: Box::new(expr),
1961 brace_token: brace_token,
1962 arms: arms,
1963 })
1964 }
1965
1966 #[cfg(feature = "full")]
1967 fn expr_try_block(input: ParseStream) -> Result<ExprTryBlock> {
1968 Ok(ExprTryBlock {
1969 attrs: Vec::new(),
1970 try_token: input.parse()?,
1971 block: input.parse()?,
1972 })
1973 }
1974
1975 #[cfg(feature = "full")]
1976 fn expr_yield(input: ParseStream) -> Result<ExprYield> {
1977 Ok(ExprYield {
1978 attrs: Vec::new(),
1979 yield_token: input.parse()?,
1980 expr: {
1981 if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
1982 Some(input.parse()?)
1983 } else {
1984 None
1985 }
1986 },
1987 })
1988 }
1989
1990 #[cfg(feature = "full")]
1991 fn match_arm(input: ParseStream) -> Result<Arm> {
1992 let requires_comma;
1993 Ok(Arm {
1994 attrs: input.call(Attribute::parse_outer)?,
1995 leading_vert: input.parse()?,
1996 pats: {
1997 let mut pats = Punctuated::new();
1998 let value: Pat = input.parse()?;
1999 pats.push_value(value);
2000 loop {
2001 if !input.peek(Token![|]) {
2002 break;
David Tolnay60291082018-08-28 09:54:49 -07002003 }
David Tolnay310b3262018-08-30 15:33:00 -07002004 let punct = input.parse()?;
2005 pats.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002006 let value: Pat = input.parse()?;
2007 pats.push_value(value);
David Tolnay310b3262018-08-30 15:33:00 -07002008 }
2009 pats
2010 },
2011 guard: {
2012 if input.peek(Token![if]) {
2013 let if_token: Token![if] = input.parse()?;
2014 let guard: Expr = input.parse()?;
2015 Some((if_token, Box::new(guard)))
2016 } else {
2017 None
2018 }
2019 },
2020 fat_arrow_token: input.parse()?,
2021 body: {
2022 let body = input.call(expr_early)?;
David Tolnaye532d6b2018-08-30 16:55:01 -07002023 requires_comma = requires_terminator(&body);
David Tolnay310b3262018-08-30 15:33:00 -07002024 Box::new(body)
2025 },
2026 comma: {
2027 if requires_comma && !input.is_empty() {
2028 Some(input.parse()?)
2029 } else {
2030 input.parse()?
2031 }
2032 },
2033 })
Alex Crichton954046c2017-05-30 21:49:42 -07002034 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07002035
Michael Layzell734adb42017-06-07 16:58:31 -04002036 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002037 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
David Tolnay60291082018-08-28 09:54:49 -07002038 let asyncness: Option<Token![async]> = input.parse()?;
2039 let movability: Option<Token![static]> = if asyncness.is_none() {
2040 input.parse()?
2041 } else {
2042 None
2043 };
2044 let capture: Option<Token![move]> = input.parse()?;
2045 let or1_token: Token![|] = input.parse()?;
2046
2047 let mut inputs = Punctuated::new();
2048 loop {
2049 if input.peek(Token![|]) {
2050 break;
2051 }
2052 let value = fn_arg(input)?;
2053 inputs.push_value(value);
2054 if input.peek(Token![|]) {
2055 break;
2056 }
2057 let punct: Token![,] = input.parse()?;
2058 inputs.push_punct(punct);
2059 }
2060
2061 let or2_token: Token![|] = input.parse()?;
2062
2063 let (output, body) = if input.peek(Token![->]) {
2064 let arrow_token: Token![->] = input.parse()?;
2065 let ty: Type = input.parse()?;
2066 let body: Block = input.parse()?;
2067 let output = ReturnType::Type(arrow_token, Box::new(ty));
2068 let block = Expr::Block(ExprBlock {
2069 attrs: Vec::new(),
2070 label: None,
2071 block: body,
2072 });
2073 (output, block)
2074 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002075 let body = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002076 (ReturnType::Default, body)
2077 };
2078
2079 Ok(ExprClosure {
David Tolnay310b3262018-08-30 15:33:00 -07002080 attrs: Vec::new(),
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002081 asyncness: asyncness,
2082 movability: movability,
2083 capture: capture,
David Tolnay60291082018-08-28 09:54:49 -07002084 or1_token: or1_token,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002085 inputs: inputs,
David Tolnay60291082018-08-28 09:54:49 -07002086 or2_token: or2_token,
2087 output: output,
2088 body: Box::new(body),
2089 })
David Tolnay02a9c6f2018-08-24 18:58:45 -04002090 }
Yusuke Sasaki851062f2018-08-01 06:28:28 +09002091
2092 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002093 fn expr_async(input: ParseStream) -> Result<ExprAsync> {
2094 Ok(ExprAsync {
2095 attrs: Vec::new(),
2096 async_token: input.parse()?,
2097 capture: input.parse()?,
2098 block: input.parse()?,
2099 })
David Tolnay60291082018-08-28 09:54:49 -07002100 }
Gregory Katz3e562cc2016-09-28 18:33:02 -04002101
Michael Layzell734adb42017-06-07 16:58:31 -04002102 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002103 fn fn_arg(input: ParseStream) -> Result<FnArg> {
2104 let pat: Pat = input.parse()?;
2105
2106 if input.peek(Token![:]) {
2107 Ok(FnArg::Captured(ArgCaptured {
2108 pat: pat,
2109 colon_token: input.parse()?,
2110 ty: input.parse()?,
2111 }))
2112 } else {
2113 Ok(FnArg::Inferred(pat))
2114 }
2115 }
2116
2117 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002118 fn expr_while(input: ParseStream) -> Result<ExprWhile> {
2119 let label: Option<Label> = input.parse()?;
2120 let while_token: Token![while] = input.parse()?;
2121 let cond = expr_no_struct(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002122
David Tolnay310b3262018-08-30 15:33:00 -07002123 let content;
2124 let brace_token = braced!(content in input);
2125 let inner_attrs = content.call(Attribute::parse_inner)?;
2126 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002127
David Tolnay310b3262018-08-30 15:33:00 -07002128 Ok(ExprWhile {
2129 attrs: inner_attrs,
2130 label: label,
2131 while_token: while_token,
2132 cond: Box::new(cond),
2133 body: Block {
2134 brace_token: brace_token,
2135 stmts: stmts,
2136 },
2137 })
Alex Crichton954046c2017-05-30 21:49:42 -07002138 }
2139
Michael Layzell734adb42017-06-07 16:58:31 -04002140 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002141 fn expr_while_let(input: ParseStream) -> Result<ExprWhileLet> {
2142 let label: Option<Label> = input.parse()?;
2143 let while_token: Token![while] = input.parse()?;
2144 let let_token: Token![let] = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002145
David Tolnay310b3262018-08-30 15:33:00 -07002146 let mut pats = Punctuated::new();
2147 let value: Pat = input.parse()?;
2148 pats.push_value(value);
2149 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2150 let punct = input.parse()?;
2151 pats.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002152 let value: Pat = input.parse()?;
2153 pats.push_value(value);
David Tolnay60291082018-08-28 09:54:49 -07002154 }
David Tolnay310b3262018-08-30 15:33:00 -07002155
2156 let eq_token: Token![=] = input.parse()?;
2157 let expr = expr_no_struct(input)?;
2158
2159 let content;
2160 let brace_token = braced!(content in input);
2161 let inner_attrs = content.call(Attribute::parse_inner)?;
2162 let stmts = content.call(Block::parse_within)?;
2163
2164 Ok(ExprWhileLet {
2165 attrs: inner_attrs,
2166 label: label,
2167 while_token: while_token,
2168 let_token: let_token,
2169 pats: pats,
2170 eq_token: eq_token,
2171 expr: Box::new(expr),
2172 body: Block {
2173 brace_token: brace_token,
2174 stmts: stmts,
2175 },
2176 })
David Tolnaybcd498f2017-12-29 12:02:33 -05002177 }
2178
2179 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002180 impl Parse for Label {
2181 fn parse(input: ParseStream) -> Result<Self> {
2182 Ok(Label {
2183 name: input.parse()?,
2184 colon_token: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04002185 })
David Tolnay60291082018-08-28 09:54:49 -07002186 }
Alex Crichton954046c2017-05-30 21:49:42 -07002187 }
2188
Michael Layzell734adb42017-06-07 16:58:31 -04002189 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002190 impl Parse for Option<Label> {
2191 fn parse(input: ParseStream) -> Result<Self> {
2192 if input.peek(Lifetime) {
2193 input.parse().map(Some)
2194 } else {
2195 Ok(None)
2196 }
2197 }
2198 }
2199
2200 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002201 fn expr_continue(input: ParseStream) -> Result<ExprContinue> {
2202 Ok(ExprContinue {
2203 attrs: Vec::new(),
2204 continue_token: input.parse()?,
2205 label: input.parse()?,
2206 })
Alex Crichton954046c2017-05-30 21:49:42 -07002207 }
Gregory Katzfd6935d2016-09-30 22:51:25 -04002208
Michael Layzell734adb42017-06-07 16:58:31 -04002209 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002210 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2211 Ok(ExprBreak {
David Tolnay310b3262018-08-30 15:33:00 -07002212 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002213 break_token: input.parse()?,
2214 label: input.parse()?,
2215 expr: {
2216 if input.is_empty()
2217 || input.peek(Token![,])
2218 || input.peek(Token![;])
2219 || !allow_struct.0 && input.peek(token::Brace)
2220 {
2221 None
2222 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002223 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002224 Some(Box::new(expr))
Michael Layzell92639a52017-06-01 00:07:44 -04002225 }
David Tolnay60291082018-08-28 09:54:49 -07002226 },
2227 })
Alex Crichton954046c2017-05-30 21:49:42 -07002228 }
2229
Michael Layzell734adb42017-06-07 16:58:31 -04002230 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002231 fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
2232 Ok(ExprReturn {
David Tolnay310b3262018-08-30 15:33:00 -07002233 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002234 return_token: input.parse()?,
2235 expr: {
2236 if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
2237 None
2238 } else {
2239 // NOTE: return is greedy and eats blocks after it even when in a
2240 // position where structs are not allowed, such as in if statement
2241 // conditions. For example:
2242 //
2243 // if return { println!("A") } {} // Prints "A"
David Tolnay7d2e1db2018-08-30 11:49:04 -07002244 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002245 Some(Box::new(expr))
2246 }
2247 },
2248 })
2249 }
2250
2251 #[cfg(feature = "full")]
David Tolnay6e1e5052018-08-30 10:21:48 -07002252 fn expr_struct_helper(input: ParseStream, outer_attrs: Vec<Attribute>, path: Path) -> Result<ExprStruct> {
2253 let content;
2254 let brace_token = braced!(content in input);
2255 let inner_attrs = content.call(Attribute::parse_inner)?;
David Tolnay60291082018-08-28 09:54:49 -07002256
David Tolnay6e1e5052018-08-30 10:21:48 -07002257 let mut fields = Punctuated::new();
2258 loop {
2259 let attrs = content.call(Attribute::parse_outer)?;
2260 if content.fork().parse::<Member>().is_err() {
2261 if attrs.is_empty() {
David Tolnay60291082018-08-28 09:54:49 -07002262 break;
David Tolnay6e1e5052018-08-30 10:21:48 -07002263 } else {
2264 return Err(content.error("expected struct field"));
David Tolnay60291082018-08-28 09:54:49 -07002265 }
David Tolnay60291082018-08-28 09:54:49 -07002266 }
2267
David Tolnay6e1e5052018-08-30 10:21:48 -07002268 let member: Member = content.parse()?;
2269 let (colon_token, value) = if content.peek(Token![:]) || !member.is_named() {
2270 let colon_token: Token![:] = content.parse()?;
2271 let value: Expr = content.parse()?;
2272 (Some(colon_token), value)
2273 } else if let Member::Named(ref ident) = member {
2274 let value = Expr::Path(ExprPath {
2275 attrs: Vec::new(),
2276 qself: None,
2277 path: Path::from(ident.clone()),
2278 });
2279 (None, value)
David Tolnay60291082018-08-28 09:54:49 -07002280 } else {
David Tolnay6e1e5052018-08-30 10:21:48 -07002281 unreachable!()
David Tolnay60291082018-08-28 09:54:49 -07002282 };
2283
David Tolnay6e1e5052018-08-30 10:21:48 -07002284 fields.push(FieldValue {
2285 attrs: attrs,
2286 member: member,
2287 colon_token: colon_token,
2288 expr: value,
2289 });
2290
2291 if !content.peek(Token![,]) {
2292 break;
2293 }
2294 let punct: Token![,] = content.parse()?;
2295 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002296 }
David Tolnay6e1e5052018-08-30 10:21:48 -07002297
2298 let (dot2_token, rest) = if fields.empty_or_trailing() && content.peek(Token![..]) {
2299 let dot2_token: Token![..] = content.parse()?;
2300 let rest: Expr = content.parse()?;
2301 (Some(dot2_token), Some(Box::new(rest)))
2302 } else {
2303 (None, None)
2304 };
2305
2306 Ok(ExprStruct {
2307 attrs: {
2308 let mut attrs = outer_attrs;
2309 attrs.extend(inner_attrs);
2310 attrs
2311 },
2312 brace_token: brace_token,
2313 path: path,
2314 fields: fields,
2315 dot2_token: dot2_token,
2316 rest: rest,
2317 })
Alex Crichton954046c2017-05-30 21:49:42 -07002318 }
David Tolnay055a7042016-10-02 19:23:54 -07002319
Michael Layzell734adb42017-06-07 16:58:31 -04002320 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002321 fn expr_unsafe(input: ParseStream) -> Result<ExprUnsafe> {
2322 let unsafe_token: Token![unsafe] = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002323
David Tolnay310b3262018-08-30 15:33:00 -07002324 let content;
2325 let brace_token = braced!(content in input);
2326 let inner_attrs = content.call(Attribute::parse_inner)?;
2327 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002328
David Tolnay310b3262018-08-30 15:33:00 -07002329 Ok(ExprUnsafe {
2330 attrs: inner_attrs,
2331 unsafe_token: unsafe_token,
2332 block: Block {
2333 brace_token: brace_token,
2334 stmts: stmts,
2335 },
2336 })
Alex Crichton954046c2017-05-30 21:49:42 -07002337 }
David Tolnay055a7042016-10-02 19:23:54 -07002338
Michael Layzell734adb42017-06-07 16:58:31 -04002339 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002340 pub fn expr_block(input: ParseStream) -> Result<ExprBlock> {
2341 let label: Option<Label> = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002342
David Tolnay310b3262018-08-30 15:33:00 -07002343 let content;
2344 let brace_token = braced!(content in input);
2345 let inner_attrs = content.call(Attribute::parse_inner)?;
2346 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002347
David Tolnay310b3262018-08-30 15:33:00 -07002348 Ok(ExprBlock {
2349 attrs: inner_attrs,
2350 label: label,
2351 block: Block {
2352 brace_token: brace_token,
2353 stmts: stmts,
2354 },
2355 })
Alex Crichton954046c2017-05-30 21:49:42 -07002356 }
David Tolnay89e05672016-10-02 14:39:42 -07002357
Michael Layzell734adb42017-06-07 16:58:31 -04002358 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002359 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2360 Ok(ExprRange {
David Tolnay8c91b882017-12-28 23:04:32 -05002361 attrs: Vec::new(),
2362 from: None,
David Tolnay60291082018-08-28 09:54:49 -07002363 limits: input.parse()?,
2364 to: {
2365 if input.is_empty()
2366 || input.peek(Token![,])
2367 || input.peek(Token![;])
2368 || !allow_struct.0 && input.peek(token::Brace)
2369 {
2370 None
2371 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002372 let to = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002373 Some(Box::new(to))
2374 }
2375 },
2376 })
2377 }
David Tolnay438c9052016-10-07 23:24:48 -07002378
Michael Layzell734adb42017-06-07 16:58:31 -04002379 #[cfg(feature = "full")]
David Tolnayc4c631e2018-08-27 10:44:37 -07002380 impl Parse for RangeLimits {
2381 fn parse(input: ParseStream) -> Result<Self> {
2382 let lookahead = input.lookahead1();
2383 if lookahead.peek(Token![..=]) {
2384 input.parse().map(RangeLimits::Closed)
2385 } else if lookahead.peek(Token![...]) {
2386 let dot3: Token![...] = input.parse()?;
2387 Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2388 } else if lookahead.peek(Token![..]) {
2389 input.parse().map(RangeLimits::HalfOpen)
2390 } else {
2391 Err(lookahead.error())
2392 }
2393 }
Alex Crichton954046c2017-05-30 21:49:42 -07002394 }
David Tolnay438c9052016-10-07 23:24:48 -07002395
David Tolnay60291082018-08-28 09:54:49 -07002396 impl Parse for ExprPath {
2397 fn parse(input: ParseStream) -> Result<Self> {
2398 #[cfg(not(feature = "full"))]
2399 let attrs = Vec::new();
2400 #[cfg(feature = "full")]
2401 let attrs = input.call(Attribute::parse_outer)?;
David Tolnayeb981bb2018-07-21 19:31:38 -07002402
David Tolnay60291082018-08-28 09:54:49 -07002403 let (qself, path) = path::parsing::qpath(input, true)?;
2404
2405 Ok(ExprPath {
David Tolnay73c9b522018-07-21 15:58:40 -07002406 attrs: attrs,
David Tolnay60291082018-08-28 09:54:49 -07002407 qself: qself,
2408 path: path,
Michael Layzell92639a52017-06-01 00:07:44 -04002409 })
David Tolnay60291082018-08-28 09:54:49 -07002410 }
Alex Crichton954046c2017-05-30 21:49:42 -07002411 }
David Tolnay42602292016-10-01 22:25:45 -07002412
Michael Layzell734adb42017-06-07 16:58:31 -04002413 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002414 impl Parse for Block {
2415 fn parse(input: ParseStream) -> Result<Self> {
2416 let content;
2417 Ok(Block {
2418 brace_token: braced!(content in input),
2419 stmts: content.call(Block::parse_within)?,
Michael Layzell92639a52017-06-01 00:07:44 -04002420 })
David Tolnay60291082018-08-28 09:54:49 -07002421 }
Alex Crichton954046c2017-05-30 21:49:42 -07002422 }
David Tolnay939766a2016-09-23 23:48:12 -07002423
Michael Layzell734adb42017-06-07 16:58:31 -04002424 #[cfg(feature = "full")]
Alex Crichton954046c2017-05-30 21:49:42 -07002425 impl Block {
David Tolnay9389c382018-08-27 09:13:37 -07002426 pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002427 let mut stmts = Vec::new();
David Tolnay7158c5f2018-08-30 17:28:34 -07002428 loop {
2429 while input.peek(Token![;]) {
2430 input.parse::<Token![;]>()?;
Michael Layzell92639a52017-06-01 00:07:44 -04002431 }
David Tolnay7158c5f2018-08-30 17:28:34 -07002432 if input.is_empty() {
2433 break;
2434 }
2435 let s = parse_stmt(input, true)?;
2436 let requires_semicolon = if let Stmt::Expr(ref s) = s {
2437 requires_terminator(s)
2438 } else {
2439 false
2440 };
David Tolnaye532d6b2018-08-30 16:55:01 -07002441 stmts.push(s);
David Tolnay7158c5f2018-08-30 17:28:34 -07002442 if input.is_empty() {
2443 break;
2444 } else if requires_semicolon {
2445 return Err(input.error("unexpected token"));
2446 }
David Tolnaye532d6b2018-08-30 16:55:01 -07002447 }
2448 Ok(stmts)
2449 }
Alex Crichton954046c2017-05-30 21:49:42 -07002450 }
2451
Michael Layzell734adb42017-06-07 16:58:31 -04002452 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002453 impl Parse for Stmt {
2454 fn parse(input: ParseStream) -> Result<Self> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002455 parse_stmt(input, false)
2456 }
2457 }
David Tolnay939766a2016-09-23 23:48:12 -07002458
David Tolnaye532d6b2018-08-30 16:55:01 -07002459 #[cfg(feature = "full")]
2460 fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
2461 let ahead = input.fork();
2462 ahead.call(Attribute::parse_outer)?;
2463
2464 // TODO: better error messages
2465 if {
2466 let ahead = ahead.fork();
2467 // Only parse braces here; paren and bracket will get parsed as
2468 // expression statements
2469 ahead.call(Path::parse_mod_style).is_ok()
2470 && ahead.parse::<Token![!]>().is_ok()
2471 && (ahead.peek(token::Brace) || ahead.peek(Ident))
2472 } {
2473 stmt_mac(input)
2474 } else if ahead.peek(Token![let]) {
2475 stmt_local(input).map(Stmt::Local)
2476 } else if ahead.peek(Token![pub])
2477 || ahead.peek(Token![crate]) && !ahead.peek2(Token![::])
2478 || ahead.peek(Token![extern]) && !ahead.peek2(Token![::])
2479 || ahead.peek(Token![use])
2480 || ahead.peek(Token![static]) && (ahead.peek2(Token![mut]) || ahead.peek2(Ident))
2481 || ahead.peek(Token![const])
2482 || ahead.peek(Token![unsafe]) && !ahead.peek2(token::Brace)
2483 || ahead.peek(Token![async]) && (ahead.peek2(Token![extern]) || ahead.peek2(Token![fn]))
2484 || ahead.peek(Token![fn])
2485 || ahead.peek(Token![mod])
2486 || ahead.peek(Token![type])
2487 || ahead.peek(Token![existential]) && ahead.peek2(Token![type])
2488 || ahead.peek(Token![struct])
2489 || ahead.peek(Token![enum])
2490 || ahead.peek(Token![union]) && ahead.peek2(Ident)
2491 || ahead.peek(Token![auto]) && ahead.peek2(Token![trait])
2492 || ahead.peek(Token![trait])
2493 || ahead.peek(Token![default]) && (ahead.peek2(Token![unsafe]) || ahead.peek2(Token![impl]))
2494 || ahead.peek(Token![impl])
2495 || ahead.peek(Token![macro])
2496 {
2497 input.parse().map(Stmt::Item)
2498 } else {
2499 stmt_expr(input, allow_nosemi)
David Tolnay60291082018-08-28 09:54:49 -07002500 }
Alex Crichton954046c2017-05-30 21:49:42 -07002501 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07002502
Michael Layzell734adb42017-06-07 16:58:31 -04002503 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002504 fn stmt_mac(input: ParseStream) -> Result<Stmt> {
2505 let attrs = input.call(Attribute::parse_outer)?;
2506 let path = input.call(Path::parse_mod_style)?;
2507 let bang_token: Token![!] = input.parse()?;
2508 let ident: Option<Ident> = input.parse()?;
2509 let (delimiter, tts) = mac::parse_delimiter(input)?;
2510 let semi_token: Option<Token![;]> = input.parse()?;
2511
2512 Ok(Stmt::Item(Item::Macro(ItemMacro {
2513 attrs: attrs,
2514 ident: ident,
2515 mac: Macro {
2516 path: path,
2517 bang_token: bang_token,
2518 delimiter: delimiter,
2519 tts: tts,
2520 },
2521 semi_token: semi_token,
2522 })))
Alex Crichton954046c2017-05-30 21:49:42 -07002523 }
David Tolnay84aa0752016-10-02 23:01:13 -07002524
Michael Layzell734adb42017-06-07 16:58:31 -04002525 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002526 fn stmt_local(input: ParseStream) -> Result<Local> {
2527 Ok(Local {
2528 attrs: input.call(Attribute::parse_outer)?,
2529 let_token: input.parse()?,
2530 pats: {
2531 let mut pats = Punctuated::new();
2532 let value: Pat = input.parse()?;
2533 pats.push_value(value);
2534 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2535 let punct = input.parse()?;
2536 pats.push_punct(punct);
2537 let value: Pat = input.parse()?;
2538 pats.push_value(value);
2539 }
2540 pats
2541 },
2542 ty: {
2543 if input.peek(Token![:]) {
2544 let colon_token: Token![:] = input.parse()?;
2545 let ty: Type = input.parse()?;
2546 Some((colon_token, Box::new(ty)))
2547 } else {
2548 None
2549 }
2550 },
2551 init: {
2552 if input.peek(Token![=]) {
2553 let eq_token: Token![=] = input.parse()?;
2554 let init: Expr = input.parse()?;
2555 Some((eq_token, Box::new(init)))
2556 } else {
2557 None
2558 }
2559 },
2560 semi_token: input.parse()?,
2561 })
2562 }
2563
2564 #[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -07002565 fn stmt_expr(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
David Tolnay60291082018-08-28 09:54:49 -07002566 let mut attrs = input.call(Attribute::parse_outer)?;
David Tolnay01218d12018-08-29 18:13:07 -07002567 let mut e = expr_early(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002568
2569 attrs.extend(e.replace_attrs(Vec::new()));
2570 e.replace_attrs(attrs);
2571
2572 if input.peek(Token![;]) {
David Tolnay01218d12018-08-29 18:13:07 -07002573 return Ok(Stmt::Semi(e, input.parse()?));
David Tolnay60291082018-08-28 09:54:49 -07002574 }
David Tolnay60291082018-08-28 09:54:49 -07002575
David Tolnayf00a2762018-08-30 17:22:22 -07002576 if allow_nosemi || !requires_terminator(&e) {
David Tolnaye532d6b2018-08-30 16:55:01 -07002577 Ok(Stmt::Expr(e))
2578 } else {
2579 Err(input.error("expected semicolon"))
David Tolnay01218d12018-08-29 18:13:07 -07002580 }
David Tolnay60291082018-08-28 09:54:49 -07002581 }
2582
2583 #[cfg(feature = "full")]
2584 impl Parse for Pat {
2585 fn parse(input: ParseStream) -> Result<Self> {
2586 // TODO: better error messages
2587 let lookahead = input.lookahead1();
2588 if lookahead.peek(Token![_]) {
David Tolnay310b3262018-08-30 15:33:00 -07002589 input.call(pat_wild).map(Pat::Wild)
David Tolnay60291082018-08-28 09:54:49 -07002590 } else if lookahead.peek(Token![box]) {
David Tolnay310b3262018-08-30 15:33:00 -07002591 input.call(pat_box).map(Pat::Box)
2592 } else if input.fork().call(pat_range).is_ok() {
David Tolnay60291082018-08-28 09:54:49 -07002593 // must be before Pat::Lit
David Tolnay310b3262018-08-30 15:33:00 -07002594 input.call(pat_range).map(Pat::Range)
2595 } else if input.fork().call(pat_tuple_struct).is_ok() {
David Tolnay60291082018-08-28 09:54:49 -07002596 // must be before Pat::Ident
David Tolnay310b3262018-08-30 15:33:00 -07002597 input.call(pat_tuple_struct).map(Pat::TupleStruct)
2598 } else if input.fork().call(pat_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_struct).map(Pat::Struct)
2601 } else if input.fork().call(pat_macro).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_macro).map(Pat::Macro)
2604 } else if input.fork().call(pat_lit).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_lit).map(Pat::Lit)
2607 } else if input.fork().call(pat_ident).is_ok() {
2608 input.call(pat_ident).map(Pat::Ident)
2609 } else if input.fork().call(pat_path).is_ok() {
2610 input.call(pat_path).map(Pat::Path)
David Tolnay60291082018-08-28 09:54:49 -07002611 } else if lookahead.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07002612 input.call(pat_tuple).map(Pat::Tuple)
David Tolnay60291082018-08-28 09:54:49 -07002613 } else if lookahead.peek(Token![&]) {
David Tolnay310b3262018-08-30 15:33:00 -07002614 input.call(pat_ref).map(Pat::Ref)
David Tolnay60291082018-08-28 09:54:49 -07002615 } else if lookahead.peek(token::Bracket) {
David Tolnay310b3262018-08-30 15:33:00 -07002616 input.call(pat_slice).map(Pat::Slice)
David Tolnay60291082018-08-28 09:54:49 -07002617 } else {
2618 Err(lookahead.error())
2619 }
2620 }
2621 }
2622
2623 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002624 fn pat_wild(input: ParseStream) -> Result<PatWild> {
2625 Ok(PatWild {
2626 underscore_token: input.parse()?,
2627 })
Alex Crichton954046c2017-05-30 21:49:42 -07002628 }
2629
Michael Layzell734adb42017-06-07 16:58:31 -04002630 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002631 fn pat_box(input: ParseStream) -> Result<PatBox> {
2632 Ok(PatBox {
2633 box_token: input.parse()?,
2634 pat: input.parse()?,
2635 })
David Tolnay60291082018-08-28 09:54:49 -07002636 }
2637
2638 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002639 fn pat_ident(input: ParseStream) -> Result<PatIdent> {
2640 Ok(PatIdent {
2641 by_ref: input.parse()?,
2642 mutability: input.parse()?,
2643 ident: {
2644 let ident = if input.peek(Ident) || input.peek(Token![self]) {
David Tolnay0dea1b92018-08-30 17:47:29 -07002645 input.call(Ident::parse_any)?
David Tolnay310b3262018-08-30 15:33:00 -07002646 } else {
2647 return Err(input.error("expected identifier or `self`"));
2648 };
2649 if input.peek(Token![<]) || input.peek(Token![::]) {
2650 return Err(input.error("unexpected token"));
David Tolnay60291082018-08-28 09:54:49 -07002651 }
David Tolnay310b3262018-08-30 15:33:00 -07002652 ident
2653 },
2654 subpat: {
2655 if input.peek(Token![@]) {
2656 let at_token: Token![@] = input.parse()?;
2657 let subpat: Pat = input.parse()?;
2658 Some((at_token, Box::new(subpat)))
2659 } else {
2660 None
2661 }
2662 },
2663 })
David Tolnay60291082018-08-28 09:54:49 -07002664 }
2665
2666 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002667 fn pat_tuple_struct(input: ParseStream) -> Result<PatTupleStruct> {
2668 Ok(PatTupleStruct {
2669 path: input.parse()?,
2670 pat: input.call(pat_tuple)?,
2671 })
2672 }
David Tolnay60291082018-08-28 09:54:49 -07002673
David Tolnay310b3262018-08-30 15:33:00 -07002674 #[cfg(feature = "full")]
2675 fn pat_struct(input: ParseStream) -> Result<PatStruct> {
2676 let path: Path = input.parse()?;
2677
2678 let content;
2679 let brace_token = braced!(content in input);
2680
2681 let mut fields = Punctuated::new();
2682 while !content.is_empty() && !content.peek(Token![..]) {
2683 let value = content.call(field_pat)?;
2684 fields.push_value(value);
2685 if !content.peek(Token![,]) {
2686 break;
David Tolnay60291082018-08-28 09:54:49 -07002687 }
David Tolnay310b3262018-08-30 15:33:00 -07002688 let punct: Token![,] = content.parse()?;
2689 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002690 }
David Tolnay310b3262018-08-30 15:33:00 -07002691
2692 let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) {
2693 Some(content.parse()?)
2694 } else {
2695 None
2696 };
2697
2698 Ok(PatStruct {
2699 path: path,
2700 brace_token: brace_token,
2701 fields: fields,
2702 dot2_token: dot2_token,
2703 })
2704 }
2705
2706 #[cfg(feature = "full")]
2707 fn field_pat(input: ParseStream) -> Result<FieldPat> {
2708 let boxed: Option<Token![box]> = input.parse()?;
2709 let by_ref: Option<Token![ref]> = input.parse()?;
2710 let mutability: Option<Token![mut]> = input.parse()?;
2711 let member: Member = input.parse()?;
2712
2713 if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
2714 || member.is_unnamed()
2715 {
2716 return Ok(FieldPat {
2717 attrs: Vec::new(),
2718 member: member,
2719 colon_token: input.parse()?,
2720 pat: input.parse()?,
2721 });
2722 }
2723
2724 let ident = match member {
2725 Member::Named(ident) => ident,
2726 Member::Unnamed(_) => unreachable!(),
2727 };
2728
2729 let mut pat = Pat::Ident(PatIdent {
2730 by_ref: by_ref,
2731 mutability: mutability,
2732 ident: ident.clone(),
2733 subpat: None,
2734 });
2735
2736 if let Some(boxed) = boxed {
2737 pat = Pat::Box(PatBox {
2738 pat: Box::new(pat),
2739 box_token: boxed,
2740 });
2741 }
2742
2743 Ok(FieldPat {
2744 member: Member::Named(ident),
2745 pat: Box::new(pat),
2746 attrs: Vec::new(),
2747 colon_token: None,
2748 })
Alex Crichton954046c2017-05-30 21:49:42 -07002749 }
2750
David Tolnay1501f7e2018-08-27 14:21:03 -07002751 impl Parse for Member {
2752 fn parse(input: ParseStream) -> Result<Self> {
2753 if input.peek(Ident) {
2754 input.parse().map(Member::Named)
2755 } else if input.peek(LitInt) {
2756 input.parse().map(Member::Unnamed)
2757 } else {
2758 Err(input.error("expected identifier or integer"))
2759 }
2760 }
David Tolnay85b69a42017-12-27 20:43:10 -05002761 }
2762
David Tolnay1501f7e2018-08-27 14:21:03 -07002763 impl Parse for Index {
2764 fn parse(input: ParseStream) -> Result<Self> {
2765 let lit: LitInt = input.parse()?;
2766 if let IntSuffix::None = lit.suffix() {
2767 Ok(Index {
2768 index: lit.value() as u32,
2769 span: lit.span(),
2770 })
2771 } else {
2772 Err(input.error("expected unsuffixed integer"))
2773 }
2774 }
David Tolnay85b69a42017-12-27 20:43:10 -05002775 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07002776
Michael Layzell734adb42017-06-07 16:58:31 -04002777 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002778 fn pat_path(input: ParseStream) -> Result<PatPath> {
2779 let p: ExprPath = input.parse()?;
2780 Ok(PatPath {
2781 qself: p.qself,
2782 path: p.path,
2783 })
Alex Crichton954046c2017-05-30 21:49:42 -07002784 }
David Tolnay9636c052016-10-02 17:11:17 -07002785
Michael Layzell734adb42017-06-07 16:58:31 -04002786 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002787 fn pat_tuple(input: ParseStream) -> Result<PatTuple> {
2788 let content;
2789 let paren_token = parenthesized!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002790
David Tolnay310b3262018-08-30 15:33:00 -07002791 let mut front = Punctuated::new();
2792 let mut dot2_token = None::<Token![..]>;
2793 let mut comma_token = None::<Token![,]>;
2794 loop {
2795 if content.is_empty() {
2796 break;
David Tolnay60291082018-08-28 09:54:49 -07002797 }
David Tolnay310b3262018-08-30 15:33:00 -07002798 if content.peek(Token![..]) {
2799 dot2_token = Some(content.parse()?);
2800 comma_token = content.parse()?;
2801 break;
David Tolnay60291082018-08-28 09:54:49 -07002802 }
David Tolnay310b3262018-08-30 15:33:00 -07002803 let value: Pat = content.parse()?;
2804 front.push_value(value);
2805 if content.is_empty() {
2806 break;
2807 }
2808 let punct = content.parse()?;
2809 front.push_punct(punct);
2810 }
2811
David Tolnayf5ebc192018-08-30 18:23:46 -07002812 let mut back = Punctuated::new();
2813 while !content.is_empty() {
2814 let value: Pat = content.parse()?;
2815 back.push_value(value);
2816 if content.is_empty() {
2817 break;
2818 }
2819 let punct = content.parse()?;
2820 back.push_punct(punct);
2821 }
David Tolnay310b3262018-08-30 15:33:00 -07002822
2823 Ok(PatTuple {
2824 paren_token: paren_token,
2825 front: front,
2826 dot2_token: dot2_token,
2827 comma_token: comma_token,
2828 back: back,
2829 })
2830 }
2831
2832 #[cfg(feature = "full")]
2833 fn pat_ref(input: ParseStream) -> Result<PatRef> {
2834 Ok(PatRef {
2835 and_token: input.parse()?,
2836 mutability: input.parse()?,
2837 pat: input.parse()?,
2838 })
2839 }
2840
2841 #[cfg(feature = "full")]
2842 fn pat_lit(input: ParseStream) -> Result<PatLit> {
2843 if input.peek(Lit) || input.peek(Token![-]) && input.peek2(Lit) {
2844 Ok(PatLit {
2845 expr: input.call(pat_lit_expr)?,
2846 })
2847 } else {
2848 Err(input.error("expected literal pattern"))
David Tolnay60291082018-08-28 09:54:49 -07002849 }
2850 }
2851
2852 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002853 fn pat_range(input: ParseStream) -> Result<PatRange> {
2854 Ok(PatRange {
2855 lo: input.call(pat_lit_expr)?,
2856 limits: input.parse()?,
2857 hi: input.call(pat_lit_expr)?,
2858 })
David Tolnay60291082018-08-28 09:54:49 -07002859 }
2860
2861 #[cfg(feature = "full")]
2862 fn pat_lit_expr(input: ParseStream) -> Result<Box<Expr>> {
2863 let neg: Option<Token![-]> = input.parse()?;
2864
2865 let lookahead = input.lookahead1();
2866 let expr = if lookahead.peek(Lit) {
David Tolnay310b3262018-08-30 15:33:00 -07002867 Expr::Lit(input.call(expr_lit)?)
David Tolnay60291082018-08-28 09:54:49 -07002868 } else if lookahead.peek(Ident)
2869 || lookahead.peek(Token![::])
2870 || lookahead.peek(Token![<])
2871 || lookahead.peek(Token![self])
2872 || lookahead.peek(Token![Self])
2873 || lookahead.peek(Token![super])
2874 || lookahead.peek(Token![extern])
2875 || lookahead.peek(Token![crate])
2876 {
2877 Expr::Path(input.parse()?)
2878 } else {
2879 return Err(lookahead.error());
2880 };
2881
2882 Ok(Box::new(if let Some(neg) = neg {
David Tolnay8c91b882017-12-28 23:04:32 -05002883 Expr::Unary(ExprUnary {
2884 attrs: Vec::new(),
David Tolnayc29b9892017-12-27 22:58:14 -05002885 op: UnOp::Neg(neg),
David Tolnay60291082018-08-28 09:54:49 -07002886 expr: Box::new(expr),
David Tolnay3bc597f2017-12-31 02:31:11 -05002887 })
David Tolnay0ad9e9f2016-10-29 22:20:02 -07002888 } else {
David Tolnay60291082018-08-28 09:54:49 -07002889 expr
2890 }))
Alex Crichton954046c2017-05-30 21:49:42 -07002891 }
David Tolnay323279a2017-12-29 11:26:32 -05002892
2893 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002894 fn pat_slice(input: ParseStream) -> Result<PatSlice> {
2895 let content;
2896 let bracket_token = bracketed!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002897
David Tolnay310b3262018-08-30 15:33:00 -07002898 let mut front = Punctuated::new();
2899 let mut middle = None;
2900 loop {
2901 if content.is_empty() || content.peek(Token![..]) {
2902 break;
David Tolnay60291082018-08-28 09:54:49 -07002903 }
David Tolnay310b3262018-08-30 15:33:00 -07002904 let value: Pat = content.parse()?;
2905 if content.peek(Token![..]) {
2906 middle = Some(Box::new(value));
2907 break;
David Tolnay60291082018-08-28 09:54:49 -07002908 }
David Tolnay310b3262018-08-30 15:33:00 -07002909 front.push_value(value);
2910 if content.is_empty() {
2911 break;
2912 }
2913 let punct = content.parse()?;
2914 front.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002915 }
David Tolnay310b3262018-08-30 15:33:00 -07002916
2917 let dot2_token: Option<Token![..]> = content.parse()?;
2918 let mut comma_token = None::<Token![,]>;
2919 let mut back = Punctuated::new();
2920 if dot2_token.is_some() {
2921 comma_token = content.parse()?;
2922 if comma_token.is_some() {
2923 loop {
2924 if content.is_empty() {
2925 break;
2926 }
2927 let value: Pat = content.parse()?;
2928 back.push_value(value);
2929 if content.is_empty() {
2930 break;
2931 }
2932 let punct = content.parse()?;
2933 back.push_punct(punct);
2934 }
2935 }
2936 }
2937
2938 Ok(PatSlice {
2939 bracket_token: bracket_token,
2940 front: front,
2941 middle: middle,
2942 dot2_token: dot2_token,
2943 comma_token: comma_token,
2944 back: back,
2945 })
David Tolnay60291082018-08-28 09:54:49 -07002946 }
2947
2948 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002949 fn pat_macro(input: ParseStream) -> Result<PatMacro> {
2950 Ok(PatMacro {
2951 mac: input.parse()?,
2952 })
David Tolnay323279a2017-12-29 11:26:32 -05002953 }
David Tolnay1501f7e2018-08-27 14:21:03 -07002954
2955 #[cfg(feature = "full")]
2956 impl Member {
2957 fn is_named(&self) -> bool {
2958 match *self {
2959 Member::Named(_) => true,
2960 Member::Unnamed(_) => false,
2961 }
2962 }
David Tolnay60291082018-08-28 09:54:49 -07002963
2964 fn is_unnamed(&self) -> bool {
2965 match *self {
2966 Member::Named(_) => false,
2967 Member::Unnamed(_) => true,
2968 }
2969 }
David Tolnay1501f7e2018-08-27 14:21:03 -07002970 }
David Tolnayb9c8e322016-09-23 20:48:37 -07002971}
2972
David Tolnayf4bbbd92016-09-23 14:41:55 -07002973#[cfg(feature = "printing")]
2974mod printing {
2975 use super::*;
Michael Layzell734adb42017-06-07 16:58:31 -04002976 #[cfg(feature = "full")]
David Tolnay13b3d352016-10-03 00:31:15 -07002977 use attr::FilterAttrs;
Alex Crichtona74a1c82018-05-16 10:20:44 -07002978 use proc_macro2::{Literal, TokenStream};
2979 use quote::{ToTokens, TokenStreamExt};
David Tolnayf4bbbd92016-09-23 14:41:55 -07002980
David Tolnaybcf26022017-12-25 22:10:52 -05002981 // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
David Tolnayb6a0e7d2018-05-20 22:06:47 -07002982 // before appending it to `TokenStream`.
Michael Layzell3936ceb2017-07-08 00:28:36 -04002983 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07002984 fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) {
David Tolnay8c91b882017-12-28 23:04:32 -05002985 if let Expr::Struct(_) = *e {
David Tolnay32954ef2017-12-26 22:43:16 -05002986 token::Paren::default().surround(tokens, |tokens| {
Michael Layzell3936ceb2017-07-08 00:28:36 -04002987 e.to_tokens(tokens);
2988 });
2989 } else {
2990 e.to_tokens(tokens);
2991 }
2992 }
2993
David Tolnay8c91b882017-12-28 23:04:32 -05002994 #[cfg(feature = "full")]
David Tolnayd997aef2018-07-21 18:42:31 -07002995 fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
David Tolnay8c91b882017-12-28 23:04:32 -05002996 tokens.append_all(attrs.outer());
2997 }
Michael Layzell734adb42017-06-07 16:58:31 -04002998
David Tolnayd997aef2018-07-21 18:42:31 -07002999 #[cfg(feature = "full")]
3000 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3001 tokens.append_all(attrs.inner());
3002 }
3003
David Tolnay8c91b882017-12-28 23:04:32 -05003004 #[cfg(not(feature = "full"))]
David Tolnayd997aef2018-07-21 18:42:31 -07003005 fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3006
3007 #[cfg(not(feature = "full"))]
3008 fn inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
Alex Crichton62a0a592017-05-22 13:58:53 -07003009
Michael Layzell734adb42017-06-07 16:58:31 -04003010 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003011 impl ToTokens for ExprBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003012 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003013 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003014 self.box_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003015 self.expr.to_tokens(tokens);
3016 }
3017 }
3018
Michael Layzell734adb42017-06-07 16:58:31 -04003019 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003020 impl ToTokens for ExprInPlace {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003021 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003022 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8701a5c2017-12-28 23:31:10 -05003023 self.place.to_tokens(tokens);
3024 self.arrow_token.to_tokens(tokens);
3025 self.value.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003026 }
3027 }
3028
Michael Layzell734adb42017-06-07 16:58:31 -04003029 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003030 impl ToTokens for ExprArray {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003031 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003032 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003033 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003034 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003035 self.elems.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003036 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003037 }
3038 }
3039
3040 impl ToTokens for ExprCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003041 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003042 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003043 self.func.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003044 self.paren_token.surround(tokens, |tokens| {
3045 self.args.to_tokens(tokens);
3046 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003047 }
3048 }
3049
Michael Layzell734adb42017-06-07 16:58:31 -04003050 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003051 impl ToTokens for ExprMethodCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003052 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003053 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay76418512017-12-28 23:47:47 -05003054 self.receiver.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003055 self.dot_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003056 self.method.to_tokens(tokens);
David Tolnayd60cfec2017-12-29 00:21:38 -05003057 self.turbofish.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003058 self.paren_token.surround(tokens, |tokens| {
3059 self.args.to_tokens(tokens);
3060 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003061 }
3062 }
3063
Michael Layzell734adb42017-06-07 16:58:31 -04003064 #[cfg(feature = "full")]
David Tolnayd60cfec2017-12-29 00:21:38 -05003065 impl ToTokens for MethodTurbofish {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003066 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003067 self.colon2_token.to_tokens(tokens);
3068 self.lt_token.to_tokens(tokens);
3069 self.args.to_tokens(tokens);
3070 self.gt_token.to_tokens(tokens);
3071 }
3072 }
3073
3074 #[cfg(feature = "full")]
3075 impl ToTokens for GenericMethodArgument {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003076 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003077 match *self {
3078 GenericMethodArgument::Type(ref t) => t.to_tokens(tokens),
3079 GenericMethodArgument::Const(ref c) => c.to_tokens(tokens),
3080 }
3081 }
3082 }
3083
3084 #[cfg(feature = "full")]
David Tolnay05362582017-12-26 01:33:57 -05003085 impl ToTokens for ExprTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003086 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003087 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003088 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003089 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003090 self.elems.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003091 // If we only have one argument, we need a trailing comma to
David Tolnay05362582017-12-26 01:33:57 -05003092 // distinguish ExprTuple from ExprParen.
David Tolnaya0834b42018-01-01 21:30:02 -08003093 if self.elems.len() == 1 && !self.elems.trailing_punct() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003094 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003095 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003096 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003097 }
3098 }
3099
3100 impl ToTokens for ExprBinary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003101 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003102 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003103 self.left.to_tokens(tokens);
3104 self.op.to_tokens(tokens);
3105 self.right.to_tokens(tokens);
3106 }
3107 }
3108
3109 impl ToTokens for ExprUnary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003110 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003111 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003112 self.op.to_tokens(tokens);
3113 self.expr.to_tokens(tokens);
3114 }
3115 }
3116
David Tolnay8c91b882017-12-28 23:04:32 -05003117 impl ToTokens for ExprLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003118 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003119 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003120 self.lit.to_tokens(tokens);
3121 }
3122 }
3123
Alex Crichton62a0a592017-05-22 13:58:53 -07003124 impl ToTokens for ExprCast {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003125 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003126 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003127 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003128 self.as_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003129 self.ty.to_tokens(tokens);
3130 }
3131 }
3132
David Tolnay0cf94f22017-12-28 23:46:26 -05003133 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003134 impl ToTokens for ExprType {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003135 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003136 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003137 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003138 self.colon_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003139 self.ty.to_tokens(tokens);
3140 }
3141 }
3142
Michael Layzell734adb42017-06-07 16:58:31 -04003143 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003144 fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>) {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003145 if let Some((ref else_token, ref else_)) = *else_ {
3146 else_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003147
3148 // If we are not one of the valid expressions to exist in an else
3149 // clause, wrap ourselves in a block.
David Tolnay2ccf32a2017-12-29 00:34:26 -05003150 match **else_ {
David Tolnay8c91b882017-12-28 23:04:32 -05003151 Expr::If(_) | Expr::IfLet(_) | Expr::Block(_) => {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003152 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003153 }
3154 _ => {
David Tolnay32954ef2017-12-26 22:43:16 -05003155 token::Brace::default().surround(tokens, |tokens| {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003156 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003157 });
3158 }
3159 }
3160 }
3161 }
3162
3163 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003164 impl ToTokens for ExprIf {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003165 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003166 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003167 self.if_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003168 wrap_bare_struct(tokens, &self.cond);
David Tolnay2ccf32a2017-12-29 00:34:26 -05003169 self.then_branch.to_tokens(tokens);
3170 maybe_wrap_else(tokens, &self.else_branch);
Alex Crichton62a0a592017-05-22 13:58:53 -07003171 }
3172 }
3173
Michael Layzell734adb42017-06-07 16:58:31 -04003174 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003175 impl ToTokens for ExprIfLet {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003176 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003177 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003178 self.if_token.to_tokens(tokens);
3179 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003180 self.pats.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003181 self.eq_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003182 wrap_bare_struct(tokens, &self.expr);
David Tolnay2ccf32a2017-12-29 00:34:26 -05003183 self.then_branch.to_tokens(tokens);
3184 maybe_wrap_else(tokens, &self.else_branch);
Alex Crichton62a0a592017-05-22 13:58:53 -07003185 }
3186 }
3187
Michael Layzell734adb42017-06-07 16:58:31 -04003188 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003189 impl ToTokens for ExprWhile {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003190 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003191 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003192 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003193 self.while_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003194 wrap_bare_struct(tokens, &self.cond);
David Tolnay5d314dc2018-07-21 16:40:01 -07003195 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003196 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003197 tokens.append_all(&self.body.stmts);
3198 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003199 }
3200 }
3201
Michael Layzell734adb42017-06-07 16:58:31 -04003202 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003203 impl ToTokens for ExprWhileLet {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003204 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003205 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003206 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003207 self.while_token.to_tokens(tokens);
3208 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003209 self.pats.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003210 self.eq_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003211 wrap_bare_struct(tokens, &self.expr);
David Tolnay5d314dc2018-07-21 16:40:01 -07003212 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003213 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003214 tokens.append_all(&self.body.stmts);
3215 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003216 }
3217 }
3218
Michael Layzell734adb42017-06-07 16:58:31 -04003219 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003220 impl ToTokens for ExprForLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003221 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003222 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003223 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003224 self.for_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003225 self.pat.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003226 self.in_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003227 wrap_bare_struct(tokens, &self.expr);
David Tolnay5d314dc2018-07-21 16:40:01 -07003228 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003229 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003230 tokens.append_all(&self.body.stmts);
3231 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003232 }
3233 }
3234
Michael Layzell734adb42017-06-07 16:58:31 -04003235 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003236 impl ToTokens for ExprLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003237 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003238 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003239 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003240 self.loop_token.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003241 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003242 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003243 tokens.append_all(&self.body.stmts);
3244 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003245 }
3246 }
3247
Michael Layzell734adb42017-06-07 16:58:31 -04003248 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003249 impl ToTokens for ExprMatch {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003250 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003251 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003252 self.match_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003253 wrap_bare_struct(tokens, &self.expr);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003254 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003255 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay51382052017-12-27 13:46:21 -05003256 for (i, arm) in self.arms.iter().enumerate() {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003257 arm.to_tokens(tokens);
3258 // Ensure that we have a comma after a non-block arm, except
3259 // for the last one.
3260 let is_last = i == self.arms.len() - 1;
David Tolnaye532d6b2018-08-30 16:55:01 -07003261 if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003262 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003263 }
3264 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003265 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003266 }
3267 }
3268
Michael Layzell734adb42017-06-07 16:58:31 -04003269 #[cfg(feature = "full")]
David Tolnay02a9c6f2018-08-24 18:58:45 -04003270 impl ToTokens for ExprAsync {
3271 fn to_tokens(&self, tokens: &mut TokenStream) {
3272 outer_attrs_to_tokens(&self.attrs, tokens);
3273 self.async_token.to_tokens(tokens);
3274 self.capture.to_tokens(tokens);
3275 self.block.to_tokens(tokens);
3276 }
3277 }
3278
3279 #[cfg(feature = "full")]
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003280 impl ToTokens for ExprTryBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003281 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003282 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003283 self.try_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003284 self.block.to_tokens(tokens);
3285 }
3286 }
3287
Michael Layzell734adb42017-06-07 16:58:31 -04003288 #[cfg(feature = "full")]
Alex Crichtonfe110462017-06-01 12:49:27 -07003289 impl ToTokens for ExprYield {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003290 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003291 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonfe110462017-06-01 12:49:27 -07003292 self.yield_token.to_tokens(tokens);
3293 self.expr.to_tokens(tokens);
3294 }
3295 }
3296
3297 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003298 impl ToTokens for ExprClosure {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003299 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003300 outer_attrs_to_tokens(&self.attrs, tokens);
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09003301 self.asyncness.to_tokens(tokens);
David Tolnay13d4c0e2018-03-31 20:53:59 +02003302 self.movability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003303 self.capture.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003304 self.or1_token.to_tokens(tokens);
David Tolnay56080682018-01-06 14:01:52 -08003305 for input in self.inputs.pairs() {
3306 match **input.value() {
David Tolnay51382052017-12-27 13:46:21 -05003307 FnArg::Captured(ArgCaptured {
3308 ref pat,
3309 ty: Type::Infer(_),
3310 ..
3311 }) => {
Alex Crichton62a0a592017-05-22 13:58:53 -07003312 pat.to_tokens(tokens);
David Tolnay9636c052016-10-02 17:11:17 -07003313 }
David Tolnay56080682018-01-06 14:01:52 -08003314 _ => input.value().to_tokens(tokens),
David Tolnay3c2467c2016-10-02 17:55:08 -07003315 }
David Tolnayf2cfd722017-12-31 18:02:51 -05003316 input.punct().to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003317 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003318 self.or2_token.to_tokens(tokens);
David Tolnay7f675742017-12-27 22:43:21 -05003319 self.output.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003320 self.body.to_tokens(tokens);
3321 }
3322 }
3323
Michael Layzell734adb42017-06-07 16:58:31 -04003324 #[cfg(feature = "full")]
Nika Layzell640832a2017-12-04 13:37:09 -05003325 impl ToTokens for ExprUnsafe {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003326 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003327 outer_attrs_to_tokens(&self.attrs, tokens);
Nika Layzell640832a2017-12-04 13:37:09 -05003328 self.unsafe_token.to_tokens(tokens);
David Tolnayc4be3512018-08-27 06:25:44 -07003329 self.block.brace_token.surround(tokens, |tokens| {
3330 inner_attrs_to_tokens(&self.attrs, tokens);
3331 tokens.append_all(&self.block.stmts);
3332 });
Nika Layzell640832a2017-12-04 13:37:09 -05003333 }
3334 }
3335
3336 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003337 impl ToTokens for ExprBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003338 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003339 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay1d8e9962018-08-24 19:04:20 -04003340 self.label.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003341 self.block.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003342 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003343 tokens.append_all(&self.block.stmts);
3344 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003345 }
3346 }
3347
Michael Layzell734adb42017-06-07 16:58:31 -04003348 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003349 impl ToTokens for ExprAssign {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003350 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003351 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003352 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003353 self.eq_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003354 self.right.to_tokens(tokens);
3355 }
3356 }
3357
Michael Layzell734adb42017-06-07 16:58:31 -04003358 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003359 impl ToTokens for ExprAssignOp {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003360 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003361 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003362 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003363 self.op.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003364 self.right.to_tokens(tokens);
3365 }
3366 }
3367
3368 impl ToTokens for ExprField {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003369 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003370 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003371 self.base.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003372 self.dot_token.to_tokens(tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003373 self.member.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003374 }
3375 }
3376
David Tolnay85b69a42017-12-27 20:43:10 -05003377 impl ToTokens for Member {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003378 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay85b69a42017-12-27 20:43:10 -05003379 match *self {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003380 Member::Named(ref ident) => ident.to_tokens(tokens),
David Tolnay85b69a42017-12-27 20:43:10 -05003381 Member::Unnamed(ref index) => index.to_tokens(tokens),
3382 }
3383 }
3384 }
3385
David Tolnay85b69a42017-12-27 20:43:10 -05003386 impl ToTokens for Index {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003387 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichton9a4dca22018-03-28 06:32:19 -07003388 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
3389 lit.set_span(self.span);
3390 tokens.append(lit);
Alex Crichton62a0a592017-05-22 13:58:53 -07003391 }
3392 }
3393
3394 impl ToTokens for ExprIndex {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003395 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003396 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003397 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003398 self.bracket_token.surround(tokens, |tokens| {
3399 self.index.to_tokens(tokens);
3400 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003401 }
3402 }
3403
Michael Layzell734adb42017-06-07 16:58:31 -04003404 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003405 impl ToTokens for ExprRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003406 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003407 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003408 self.from.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003409 match self.limits {
3410 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
3411 RangeLimits::Closed(ref t) => t.to_tokens(tokens),
3412 }
Alex Crichton62a0a592017-05-22 13:58:53 -07003413 self.to.to_tokens(tokens);
3414 }
3415 }
3416
3417 impl ToTokens for ExprPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003418 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003419 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003420 ::PathTokens(&self.qself, &self.path).to_tokens(tokens)
Alex Crichton62a0a592017-05-22 13:58:53 -07003421 }
3422 }
3423
Michael Layzell734adb42017-06-07 16:58:31 -04003424 #[cfg(feature = "full")]
David Tolnay00674ba2018-03-31 18:14:11 +02003425 impl ToTokens for ExprReference {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003426 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003427 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003428 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003429 self.mutability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003430 self.expr.to_tokens(tokens);
3431 }
3432 }
3433
Michael Layzell734adb42017-06-07 16:58:31 -04003434 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003435 impl ToTokens for ExprBreak {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003436 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003437 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003438 self.break_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003439 self.label.to_tokens(tokens);
3440 self.expr.to_tokens(tokens);
3441 }
3442 }
3443
Michael Layzell734adb42017-06-07 16:58:31 -04003444 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003445 impl ToTokens for ExprContinue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003446 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003447 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003448 self.continue_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003449 self.label.to_tokens(tokens);
3450 }
3451 }
3452
Michael Layzell734adb42017-06-07 16:58:31 -04003453 #[cfg(feature = "full")]
David Tolnayc246cd32017-12-28 23:14:32 -05003454 impl ToTokens for ExprReturn {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003455 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003456 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003457 self.return_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003458 self.expr.to_tokens(tokens);
3459 }
3460 }
3461
Michael Layzell734adb42017-06-07 16:58:31 -04003462 #[cfg(feature = "full")]
David Tolnay8c91b882017-12-28 23:04:32 -05003463 impl ToTokens for ExprMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003464 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003465 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003466 self.mac.to_tokens(tokens);
3467 }
3468 }
3469
3470 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003471 impl ToTokens for ExprStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003472 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003473 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003474 self.path.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003475 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003476 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003477 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003478 if self.rest.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -07003479 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003480 self.rest.to_tokens(tokens);
3481 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003482 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003483 }
3484 }
3485
Michael Layzell734adb42017-06-07 16:58:31 -04003486 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003487 impl ToTokens for ExprRepeat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003488 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003489 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003490 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003491 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003492 self.expr.to_tokens(tokens);
3493 self.semi_token.to_tokens(tokens);
David Tolnay84d80442018-01-07 01:03:20 -08003494 self.len.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003495 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003496 }
3497 }
3498
David Tolnaye98775f2017-12-28 23:17:00 -05003499 #[cfg(feature = "full")]
Michael Layzell93c36282017-06-04 20:43:14 -04003500 impl ToTokens for ExprGroup {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003501 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003502 outer_attrs_to_tokens(&self.attrs, tokens);
Michael Layzell93c36282017-06-04 20:43:14 -04003503 self.group_token.surround(tokens, |tokens| {
3504 self.expr.to_tokens(tokens);
3505 });
3506 }
3507 }
3508
Alex Crichton62a0a592017-05-22 13:58:53 -07003509 impl ToTokens for ExprParen {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003510 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003511 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003512 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003513 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003514 self.expr.to_tokens(tokens);
3515 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003516 }
3517 }
3518
Michael Layzell734adb42017-06-07 16:58:31 -04003519 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003520 impl ToTokens for ExprTry {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003521 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003522 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003523 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003524 self.question_token.to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003525 }
3526 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07003527
David Tolnay2ae520a2017-12-29 11:19:50 -05003528 impl ToTokens for ExprVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003529 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003530 self.tts.to_tokens(tokens);
3531 }
3532 }
3533
Michael Layzell734adb42017-06-07 16:58:31 -04003534 #[cfg(feature = "full")]
David Tolnaybcd498f2017-12-29 12:02:33 -05003535 impl ToTokens for Label {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003536 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaybcd498f2017-12-29 12:02:33 -05003537 self.name.to_tokens(tokens);
3538 self.colon_token.to_tokens(tokens);
3539 }
3540 }
3541
3542 #[cfg(feature = "full")]
David Tolnay055a7042016-10-02 19:23:54 -07003543 impl ToTokens for FieldValue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003544 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003545 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003546 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003547 if let Some(ref colon_token) = self.colon_token {
3548 colon_token.to_tokens(tokens);
David Tolnay276690f2016-10-30 12:06:59 -07003549 self.expr.to_tokens(tokens);
3550 }
David Tolnay055a7042016-10-02 19:23:54 -07003551 }
3552 }
3553
Michael Layzell734adb42017-06-07 16:58:31 -04003554 #[cfg(feature = "full")]
David Tolnayb4ad3b52016-10-01 21:58:13 -07003555 impl ToTokens for Arm {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003556 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003557 tokens.append_all(&self.attrs);
David Tolnay18cc4d42018-03-31 18:47:20 +02003558 self.leading_vert.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003559 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003560 if let Some((ref if_token, ref guard)) = self.guard {
3561 if_token.to_tokens(tokens);
3562 guard.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003563 }
David Tolnaydfb91432018-03-31 19:19:44 +02003564 self.fat_arrow_token.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003565 self.body.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003566 self.comma.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003567 }
3568 }
3569
Michael Layzell734adb42017-06-07 16:58:31 -04003570 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003571 impl ToTokens for PatWild {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003572 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003573 self.underscore_token.to_tokens(tokens);
3574 }
3575 }
3576
Michael Layzell734adb42017-06-07 16:58:31 -04003577 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003578 impl ToTokens for PatIdent {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003579 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay24237fb2017-12-29 02:15:26 -05003580 self.by_ref.to_tokens(tokens);
David Tolnayefc96fb2017-12-29 02:03:15 -05003581 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003582 self.ident.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003583 if let Some((ref at_token, ref subpat)) = self.subpat {
3584 at_token.to_tokens(tokens);
3585 subpat.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003586 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003587 }
3588 }
3589
Michael Layzell734adb42017-06-07 16:58:31 -04003590 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003591 impl ToTokens for PatStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003592 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003593 self.path.to_tokens(tokens);
3594 self.brace_token.surround(tokens, |tokens| {
3595 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003596 // NOTE: We need a comma before the dot2 token if it is present.
3597 if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003598 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003599 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003600 self.dot2_token.to_tokens(tokens);
3601 });
3602 }
3603 }
3604
Michael Layzell734adb42017-06-07 16:58:31 -04003605 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003606 impl ToTokens for PatTupleStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003607 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003608 self.path.to_tokens(tokens);
3609 self.pat.to_tokens(tokens);
3610 }
3611 }
3612
Michael Layzell734adb42017-06-07 16:58:31 -04003613 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003614 impl ToTokens for PatPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003615 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003616 ::PathTokens(&self.qself, &self.path).to_tokens(tokens);
3617 }
3618 }
3619
Michael Layzell734adb42017-06-07 16:58:31 -04003620 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003621 impl ToTokens for PatTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003622 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003623 self.paren_token.surround(tokens, |tokens| {
David Tolnay41871922017-12-29 01:53:45 -05003624 self.front.to_tokens(tokens);
3625 if let Some(ref dot2_token) = self.dot2_token {
3626 if !self.front.empty_or_trailing() {
3627 // Ensure there is a comma before the .. token.
David Tolnayf8db7ba2017-11-11 22:52:16 -08003628 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003629 }
David Tolnay41871922017-12-29 01:53:45 -05003630 dot2_token.to_tokens(tokens);
3631 self.comma_token.to_tokens(tokens);
3632 if self.comma_token.is_none() && !self.back.is_empty() {
3633 // Ensure there is a comma after the .. token.
3634 <Token![,]>::default().to_tokens(tokens);
3635 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07003636 }
David Tolnay41871922017-12-29 01:53:45 -05003637 self.back.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003638 });
3639 }
3640 }
3641
Michael Layzell734adb42017-06-07 16:58:31 -04003642 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003643 impl ToTokens for PatBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003644 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003645 self.box_token.to_tokens(tokens);
3646 self.pat.to_tokens(tokens);
3647 }
3648 }
3649
Michael Layzell734adb42017-06-07 16:58:31 -04003650 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003651 impl ToTokens for PatRef {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003652 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003653 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003654 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003655 self.pat.to_tokens(tokens);
3656 }
3657 }
3658
Michael Layzell734adb42017-06-07 16:58:31 -04003659 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003660 impl ToTokens for PatLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003661 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003662 self.expr.to_tokens(tokens);
3663 }
3664 }
3665
Michael Layzell734adb42017-06-07 16:58:31 -04003666 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003667 impl ToTokens for PatRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003668 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003669 self.lo.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003670 match self.limits {
3671 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
David Tolnay7ac699c2018-08-24 14:00:58 -04003672 RangeLimits::Closed(ref t) => Token![...](t.spans).to_tokens(tokens),
David Tolnay475288a2017-12-19 22:59:44 -08003673 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003674 self.hi.to_tokens(tokens);
3675 }
3676 }
3677
Michael Layzell734adb42017-06-07 16:58:31 -04003678 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003679 impl ToTokens for PatSlice {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003680 fn to_tokens(&self, tokens: &mut TokenStream) {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003681 // XXX: This is a mess, and it will be so easy to screw it up. How
3682 // do we make this correct itself better?
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003683 self.bracket_token.surround(tokens, |tokens| {
3684 self.front.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003685
3686 // If we need a comma before the middle or standalone .. token,
3687 // then make sure it's present.
David Tolnay51382052017-12-27 13:46:21 -05003688 if !self.front.empty_or_trailing()
3689 && (self.middle.is_some() || self.dot2_token.is_some())
Michael Layzell3936ceb2017-07-08 00:28:36 -04003690 {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003691 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003692 }
3693
3694 // If we have an identifier, we always need a .. token.
3695 if self.middle.is_some() {
3696 self.middle.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -07003697 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003698 } else if self.dot2_token.is_some() {
3699 self.dot2_token.to_tokens(tokens);
3700 }
3701
3702 // Make sure we have a comma before the back half.
3703 if !self.back.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07003704 TokensOrDefault(&self.comma_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003705 self.back.to_tokens(tokens);
3706 } else {
3707 self.comma_token.to_tokens(tokens);
3708 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003709 })
David Tolnayb4ad3b52016-10-01 21:58:13 -07003710 }
3711 }
3712
Michael Layzell734adb42017-06-07 16:58:31 -04003713 #[cfg(feature = "full")]
David Tolnay323279a2017-12-29 11:26:32 -05003714 impl ToTokens for PatMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003715 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay323279a2017-12-29 11:26:32 -05003716 self.mac.to_tokens(tokens);
3717 }
3718 }
3719
3720 #[cfg(feature = "full")]
David Tolnay2ae520a2017-12-29 11:19:50 -05003721 impl ToTokens for PatVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003722 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003723 self.tts.to_tokens(tokens);
3724 }
3725 }
3726
3727 #[cfg(feature = "full")]
David Tolnay8d9e81a2016-10-03 22:36:32 -07003728 impl ToTokens for FieldPat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003729 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay5d7098a2017-12-29 01:35:24 -05003730 if let Some(ref colon_token) = self.colon_token {
David Tolnay85b69a42017-12-27 20:43:10 -05003731 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003732 colon_token.to_tokens(tokens);
David Tolnay8d9e81a2016-10-03 22:36:32 -07003733 }
3734 self.pat.to_tokens(tokens);
3735 }
3736 }
3737
Michael Layzell734adb42017-06-07 16:58:31 -04003738 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003739 impl ToTokens for Block {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003740 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003741 self.brace_token.surround(tokens, |tokens| {
3742 tokens.append_all(&self.stmts);
3743 });
David Tolnay42602292016-10-01 22:25:45 -07003744 }
3745 }
3746
Michael Layzell734adb42017-06-07 16:58:31 -04003747 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003748 impl ToTokens for Stmt {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003749 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay42602292016-10-01 22:25:45 -07003750 match *self {
David Tolnay191e0582016-10-02 18:31:09 -07003751 Stmt::Local(ref local) => local.to_tokens(tokens),
David Tolnay42602292016-10-01 22:25:45 -07003752 Stmt::Item(ref item) => item.to_tokens(tokens),
3753 Stmt::Expr(ref expr) => expr.to_tokens(tokens),
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003754 Stmt::Semi(ref expr, ref semi) => {
David Tolnay42602292016-10-01 22:25:45 -07003755 expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003756 semi.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -07003757 }
David Tolnay42602292016-10-01 22:25:45 -07003758 }
3759 }
3760 }
David Tolnay191e0582016-10-02 18:31:09 -07003761
Michael Layzell734adb42017-06-07 16:58:31 -04003762 #[cfg(feature = "full")]
David Tolnay191e0582016-10-02 18:31:09 -07003763 impl ToTokens for Local {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003764 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003765 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003766 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003767 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003768 if let Some((ref colon_token, ref ty)) = self.ty {
3769 colon_token.to_tokens(tokens);
3770 ty.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003771 }
David Tolnay8b4d3022017-12-29 12:11:10 -05003772 if let Some((ref eq_token, ref init)) = self.init {
3773 eq_token.to_tokens(tokens);
3774 init.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003775 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003776 self.semi_token.to_tokens(tokens);
David Tolnay191e0582016-10-02 18:31:09 -07003777 }
3778 }
David Tolnayf4bbbd92016-09-23 14:41:55 -07003779}