blob: 809463aff78b1c201b603102ec1c4947405efe6c [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 Tolnay631dca62018-09-01 02:46:25 -070014#[cfg(all(feature = "parsing", feature = "full"))]
David Tolnay2ae520a2017-12-29 11:19:50 -050015use 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 {
David Tolnay631dca62018-09-01 02:46:25 -0700572 #[cfg(all(feature = "parsing", feature = "full"))]
David Tolnay94f06632018-08-31 10:17:17 -0700573 fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
David Tolnay8c91b882017-12-28 23:04:32 -0500574 match *self {
David Tolnay61037c62018-01-05 16:21:03 -0800575 Expr::Box(ExprBox { ref mut attrs, .. })
576 | Expr::InPlace(ExprInPlace { ref mut attrs, .. })
577 | Expr::Array(ExprArray { ref mut attrs, .. })
578 | Expr::Call(ExprCall { ref mut attrs, .. })
579 | Expr::MethodCall(ExprMethodCall { ref mut attrs, .. })
580 | Expr::Tuple(ExprTuple { ref mut attrs, .. })
581 | Expr::Binary(ExprBinary { ref mut attrs, .. })
582 | Expr::Unary(ExprUnary { ref mut attrs, .. })
583 | Expr::Lit(ExprLit { ref mut attrs, .. })
584 | Expr::Cast(ExprCast { ref mut attrs, .. })
585 | Expr::Type(ExprType { ref mut attrs, .. })
586 | Expr::If(ExprIf { ref mut attrs, .. })
587 | Expr::IfLet(ExprIfLet { ref mut attrs, .. })
588 | Expr::While(ExprWhile { ref mut attrs, .. })
589 | Expr::WhileLet(ExprWhileLet { ref mut attrs, .. })
590 | Expr::ForLoop(ExprForLoop { ref mut attrs, .. })
591 | Expr::Loop(ExprLoop { ref mut attrs, .. })
592 | Expr::Match(ExprMatch { ref mut attrs, .. })
593 | Expr::Closure(ExprClosure { ref mut attrs, .. })
594 | Expr::Unsafe(ExprUnsafe { ref mut attrs, .. })
595 | Expr::Block(ExprBlock { ref mut attrs, .. })
596 | Expr::Assign(ExprAssign { ref mut attrs, .. })
597 | Expr::AssignOp(ExprAssignOp { ref mut attrs, .. })
598 | Expr::Field(ExprField { ref mut attrs, .. })
599 | Expr::Index(ExprIndex { ref mut attrs, .. })
600 | Expr::Range(ExprRange { ref mut attrs, .. })
601 | Expr::Path(ExprPath { ref mut attrs, .. })
David Tolnay00674ba2018-03-31 18:14:11 +0200602 | Expr::Reference(ExprReference { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800603 | Expr::Break(ExprBreak { ref mut attrs, .. })
604 | Expr::Continue(ExprContinue { ref mut attrs, .. })
605 | Expr::Return(ExprReturn { ref mut attrs, .. })
606 | Expr::Macro(ExprMacro { ref mut attrs, .. })
607 | Expr::Struct(ExprStruct { ref mut attrs, .. })
608 | Expr::Repeat(ExprRepeat { ref mut attrs, .. })
609 | Expr::Paren(ExprParen { ref mut attrs, .. })
610 | Expr::Group(ExprGroup { ref mut attrs, .. })
611 | Expr::Try(ExprTry { ref mut attrs, .. })
David Tolnay02a9c6f2018-08-24 18:58:45 -0400612 | Expr::Async(ExprAsync { ref mut attrs, .. })
David Tolnayfb2dd4b2018-08-24 16:45:34 -0400613 | Expr::TryBlock(ExprTryBlock { ref mut attrs, .. })
David Tolnay61037c62018-01-05 16:21:03 -0800614 | Expr::Yield(ExprYield { ref mut attrs, .. }) => mem::replace(attrs, new),
David Tolnay10f464a2018-08-30 18:48:55 -0700615 Expr::Verbatim(_) => Vec::new(),
David Tolnay8c91b882017-12-28 23:04:32 -0500616 }
617 }
618}
619
David Tolnay85b69a42017-12-27 20:43:10 -0500620ast_enum! {
621 /// A struct or tuple struct field accessed in a struct literal or field
622 /// expression.
David Tolnay461d98e2018-01-07 11:07:19 -0800623 ///
624 /// *This type is available if Syn is built with the `"derive"` or `"full"`
625 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500626 pub enum Member {
627 /// A named field like `self.x`.
628 Named(Ident),
629 /// An unnamed field like `self.0`.
630 Unnamed(Index),
631 }
632}
633
David Tolnay85b69a42017-12-27 20:43:10 -0500634ast_struct! {
635 /// The index of an unnamed tuple struct field.
David Tolnay461d98e2018-01-07 11:07:19 -0800636 ///
637 /// *This type is available if Syn is built with the `"derive"` or `"full"`
638 /// feature.*
David Tolnay85b69a42017-12-27 20:43:10 -0500639 pub struct Index #manual_extra_traits {
640 pub index: u32,
641 pub span: Span,
642 }
643}
644
David Tolnay14982012017-12-29 00:49:51 -0500645impl From<usize> for Index {
646 fn from(index: usize) -> Index {
David Tolnay34071ba2018-05-20 20:00:41 -0700647 assert!(index < u32::max_value() as usize);
David Tolnay14982012017-12-29 00:49:51 -0500648 Index {
649 index: index as u32,
Alex Crichton9a4dca22018-03-28 06:32:19 -0700650 span: Span::call_site(),
David Tolnay14982012017-12-29 00:49:51 -0500651 }
652 }
653}
654
655#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500656impl Eq for Index {}
657
David Tolnay14982012017-12-29 00:49:51 -0500658#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500659impl PartialEq for Index {
660 fn eq(&self, other: &Self) -> bool {
661 self.index == other.index
662 }
663}
664
David Tolnay14982012017-12-29 00:49:51 -0500665#[cfg(feature = "extra-traits")]
David Tolnay85b69a42017-12-27 20:43:10 -0500666impl Hash for Index {
667 fn hash<H: Hasher>(&self, state: &mut H) {
668 self.index.hash(state);
669 }
670}
671
672#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700673ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800674 /// The `::<>` explicit type parameters passed to a method call:
675 /// `parse::<u64>()`.
David Tolnay461d98e2018-01-07 11:07:19 -0800676 ///
677 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500678 pub struct MethodTurbofish {
679 pub colon2_token: Token![::],
680 pub lt_token: Token![<],
David Tolnayf2cfd722017-12-31 18:02:51 -0500681 pub args: Punctuated<GenericMethodArgument, Token![,]>,
David Tolnayd60cfec2017-12-29 00:21:38 -0500682 pub gt_token: Token![>],
683 }
684}
685
686#[cfg(feature = "full")]
687ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800688 /// An individual generic argument to a method, like `T`.
David Tolnay461d98e2018-01-07 11:07:19 -0800689 ///
690 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnayd60cfec2017-12-29 00:21:38 -0500691 pub enum GenericMethodArgument {
David Tolnaya454c8f2018-01-07 01:01:10 -0800692 /// A type argument.
David Tolnayd60cfec2017-12-29 00:21:38 -0500693 Type(Type),
David Tolnaya454c8f2018-01-07 01:01:10 -0800694 /// A const expression. Must be inside of a block.
David Tolnayd60cfec2017-12-29 00:21:38 -0500695 ///
696 /// NOTE: Identity expressions are represented as Type arguments, as
697 /// they are indistinguishable syntactically.
698 Const(Expr),
699 }
700}
701
702#[cfg(feature = "full")]
703ast_struct! {
Alex Crichton62a0a592017-05-22 13:58:53 -0700704 /// A field-value pair in a struct literal.
David Tolnay461d98e2018-01-07 11:07:19 -0800705 ///
706 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700707 pub struct FieldValue {
David Tolnay85b69a42017-12-27 20:43:10 -0500708 /// Attributes tagged on the field.
709 pub attrs: Vec<Attribute>,
710
711 /// Name or index of the field.
712 pub member: Member,
713
David Tolnay5d7098a2017-12-29 01:35:24 -0500714 /// The colon in `Struct { x: x }`. If written in shorthand like
715 /// `Struct { x }`, there is no colon.
David Tolnay85b69a42017-12-27 20:43:10 -0500716 pub colon_token: Option<Token![:]>,
Clar Charrd22b5702017-03-10 15:24:56 -0500717
Alex Crichton62a0a592017-05-22 13:58:53 -0700718 /// Value of the field.
719 pub expr: Expr,
Alex Crichton62a0a592017-05-22 13:58:53 -0700720 }
David Tolnay055a7042016-10-02 19:23:54 -0700721}
722
Michael Layzell734adb42017-06-07 16:58:31 -0400723#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700724ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800725 /// A lifetime labeling a `for`, `while`, or `loop`.
David Tolnay461d98e2018-01-07 11:07:19 -0800726 ///
727 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnaybcd498f2017-12-29 12:02:33 -0500728 pub struct Label {
729 pub name: Lifetime,
730 pub colon_token: Token![:],
731 }
732}
733
734#[cfg(feature = "full")]
735ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800736 /// A braced block containing Rust statements.
David Tolnay461d98e2018-01-07 11:07:19 -0800737 ///
738 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700739 pub struct Block {
David Tolnay32954ef2017-12-26 22:43:16 -0500740 pub brace_token: token::Brace,
Alex Crichton62a0a592017-05-22 13:58:53 -0700741 /// Statements in a block
742 pub stmts: Vec<Stmt>,
743 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700744}
745
Michael Layzell734adb42017-06-07 16:58:31 -0400746#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700747ast_enum! {
748 /// A statement, usually ending in a semicolon.
David Tolnay461d98e2018-01-07 11:07:19 -0800749 ///
750 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700751 pub enum Stmt {
752 /// A local (let) binding.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800753 Local(Local),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700754
Alex Crichton62a0a592017-05-22 13:58:53 -0700755 /// An item definition.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800756 Item(Item),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700757
Alex Crichton62a0a592017-05-22 13:58:53 -0700758 /// Expr without trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800759 Expr(Expr),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700760
David Tolnaya454c8f2018-01-07 01:01:10 -0800761 /// Expression with trailing semicolon.
David Tolnay1f0b7b82018-01-06 16:07:14 -0800762 Semi(Expr, Token![;]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700763 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700764}
765
Michael Layzell734adb42017-06-07 16:58:31 -0400766#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700767ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800768 /// A local `let` binding: `let x: u64 = s.parse()?`.
David Tolnay461d98e2018-01-07 11:07:19 -0800769 ///
770 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700771 pub struct Local {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500772 pub attrs: Vec<Attribute>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800773 pub let_token: Token![let],
David Tolnay5b5b7d22018-03-31 21:05:00 +0200774 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500775 pub ty: Option<(Token![:], Box<Type>)>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500776 pub init: Option<(Token![=], Box<Expr>)>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500777 pub semi_token: Token![;],
Alex Crichton62a0a592017-05-22 13:58:53 -0700778 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700779}
780
Michael Layzell734adb42017-06-07 16:58:31 -0400781#[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700782ast_enum_of_structs! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800783 /// A pattern in a local binding, function signature, match expression, or
784 /// various other places.
David Tolnay614a0142018-01-07 10:25:43 -0800785 ///
David Tolnay461d98e2018-01-07 11:07:19 -0800786 /// *This type is available if Syn is built with the `"full"` feature.*
787 ///
David Tolnay614a0142018-01-07 10:25:43 -0800788 /// # Syntax tree enum
789 ///
790 /// This type is a [syntax tree enum].
791 ///
792 /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
Alex Crichton62a0a592017-05-22 13:58:53 -0700793 // Clippy false positive
794 // https://github.com/Manishearth/rust-clippy/issues/1241
795 #[cfg_attr(feature = "cargo-clippy", allow(enum_variant_names))]
796 pub enum Pat {
David Tolnaya454c8f2018-01-07 01:01:10 -0800797 /// A pattern that matches any value: `_`.
David Tolnay461d98e2018-01-07 11:07:19 -0800798 ///
799 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700800 pub Wild(PatWild {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800801 pub underscore_token: Token![_],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700802 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700803
David Tolnaya454c8f2018-01-07 01:01:10 -0800804 /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
David Tolnay461d98e2018-01-07 11:07:19 -0800805 ///
806 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700807 pub Ident(PatIdent {
David Tolnay24237fb2017-12-29 02:15:26 -0500808 pub by_ref: Option<Token![ref]>,
809 pub mutability: Option<Token![mut]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700810 pub ident: Ident,
David Tolnay8b4d3022017-12-29 12:11:10 -0500811 pub subpat: Option<(Token![@], Box<Pat>)>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700812 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700813
David Tolnaya454c8f2018-01-07 01:01:10 -0800814 /// A struct or struct variant pattern: `Variant { x, y, .. }`.
David Tolnay461d98e2018-01-07 11:07:19 -0800815 ///
816 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700817 pub Struct(PatStruct {
818 pub path: Path,
David Tolnay32954ef2017-12-26 22:43:16 -0500819 pub brace_token: token::Brace,
David Tolnayf2cfd722017-12-31 18:02:51 -0500820 pub fields: Punctuated<FieldPat, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800821 pub dot2_token: Option<Token![..]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700822 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700823
David Tolnaya454c8f2018-01-07 01:01:10 -0800824 /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800825 ///
826 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700827 pub TupleStruct(PatTupleStruct {
828 pub path: Path,
829 pub pat: PatTuple,
830 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700831
David Tolnaya454c8f2018-01-07 01:01:10 -0800832 /// A path pattern like `Color::Red`, optionally qualified with a
833 /// self-type.
834 ///
835 /// Unquailfied path patterns can legally refer to variants, structs,
836 /// constants or associated constants. Quailfied path patterns like
837 /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
838 /// associated constants.
David Tolnay461d98e2018-01-07 11:07:19 -0800839 ///
840 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700841 pub Path(PatPath {
842 pub qself: Option<QSelf>,
843 pub path: Path,
844 }),
David Tolnayf4bbbd92016-09-23 14:41:55 -0700845
David Tolnaya454c8f2018-01-07 01:01:10 -0800846 /// A tuple pattern: `(a, b)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800847 ///
848 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700849 pub Tuple(PatTuple {
David Tolnay32954ef2017-12-26 22:43:16 -0500850 pub paren_token: token::Paren,
David Tolnayf2cfd722017-12-31 18:02:51 -0500851 pub front: Punctuated<Pat, Token![,]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500852 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500853 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500854 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700855 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800856
857 /// A box pattern: `box v`.
David Tolnay461d98e2018-01-07 11:07:19 -0800858 ///
859 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700860 pub Box(PatBox {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800861 pub box_token: Token![box],
David Tolnay4a3f59a2017-12-28 21:21:12 -0500862 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700863 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800864
865 /// A reference pattern: `&mut (first, second)`.
David Tolnay461d98e2018-01-07 11:07:19 -0800866 ///
867 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700868 pub Ref(PatRef {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800869 pub and_token: Token![&],
David Tolnay24237fb2017-12-29 02:15:26 -0500870 pub mutability: Option<Token![mut]>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500871 pub pat: Box<Pat>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700872 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800873
874 /// A literal pattern: `0`.
875 ///
876 /// This holds an `Expr` rather than a `Lit` because negative numbers
877 /// are represented as an `Expr::Unary`.
David Tolnay461d98e2018-01-07 11:07:19 -0800878 ///
879 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700880 pub Lit(PatLit {
881 pub expr: Box<Expr>,
882 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800883
884 /// A range pattern: `1..=2`.
David Tolnay461d98e2018-01-07 11:07:19 -0800885 ///
886 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700887 pub Range(PatRange {
888 pub lo: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700889 pub limits: RangeLimits,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500890 pub hi: Box<Expr>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700891 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800892
893 /// A dynamically sized slice pattern: `[a, b, i.., y, z]`.
David Tolnay461d98e2018-01-07 11:07:19 -0800894 ///
895 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700896 pub Slice(PatSlice {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500897 pub bracket_token: token::Bracket,
David Tolnayf2cfd722017-12-31 18:02:51 -0500898 pub front: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700899 pub middle: Option<Box<Pat>>,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500900 pub dot2_token: Option<Token![..]>,
David Tolnay41871922017-12-29 01:53:45 -0500901 pub comma_token: Option<Token![,]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500902 pub back: Punctuated<Pat, Token![,]>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700903 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800904
905 /// A macro in expression position.
David Tolnay461d98e2018-01-07 11:07:19 -0800906 ///
907 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay323279a2017-12-29 11:26:32 -0500908 pub Macro(PatMacro {
909 pub mac: Macro,
910 }),
David Tolnaya454c8f2018-01-07 01:01:10 -0800911
912 /// Tokens in pattern position not interpreted by Syn.
David Tolnay461d98e2018-01-07 11:07:19 -0800913 ///
914 /// *This type is available if Syn is built with the `"full"` feature.*
David Tolnay2ae520a2017-12-29 11:19:50 -0500915 pub Verbatim(PatVerbatim #manual_extra_traits {
916 pub tts: TokenStream,
917 }),
918 }
919}
920
David Tolnayc43b44e2017-12-30 23:55:54 -0500921#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500922impl Eq for PatVerbatim {}
923
David Tolnayc43b44e2017-12-30 23:55:54 -0500924#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500925impl PartialEq for PatVerbatim {
926 fn eq(&self, other: &Self) -> bool {
927 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
928 }
929}
930
David Tolnayc43b44e2017-12-30 23:55:54 -0500931#[cfg(all(feature = "full", feature = "extra-traits"))]
David Tolnay2ae520a2017-12-29 11:19:50 -0500932impl Hash for PatVerbatim {
933 fn hash<H>(&self, state: &mut H)
934 where
935 H: Hasher,
936 {
937 TokenStreamHelper(&self.tts).hash(state);
Alex Crichton62a0a592017-05-22 13:58:53 -0700938 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700939}
940
Michael Layzell734adb42017-06-07 16:58:31 -0400941#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700942ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800943 /// One arm of a `match` expression: `0...10 => { return true; }`.
Alex Crichton62a0a592017-05-22 13:58:53 -0700944 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800945 /// As in:
Alex Crichton62a0a592017-05-22 13:58:53 -0700946 ///
David Tolnaybcf26022017-12-25 22:10:52 -0500947 /// ```rust
David Tolnaya454c8f2018-01-07 01:01:10 -0800948 /// # fn f() -> bool {
David Tolnaybcf26022017-12-25 22:10:52 -0500949 /// # let n = 0;
Alex Crichton62a0a592017-05-22 13:58:53 -0700950 /// match n {
David Tolnaya454c8f2018-01-07 01:01:10 -0800951 /// 0...10 => {
952 /// return true;
953 /// }
954 /// // ...
David Tolnaybcf26022017-12-25 22:10:52 -0500955 /// # _ => {}
Alex Crichton62a0a592017-05-22 13:58:53 -0700956 /// }
David Tolnaya454c8f2018-01-07 01:01:10 -0800957 /// # false
David Tolnaybcf26022017-12-25 22:10:52 -0500958 /// # }
Alex Crichton62a0a592017-05-22 13:58:53 -0700959 /// ```
David Tolnay461d98e2018-01-07 11:07:19 -0800960 ///
961 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700962 pub struct Arm {
963 pub attrs: Vec<Attribute>,
David Tolnay18cc4d42018-03-31 18:47:20 +0200964 pub leading_vert: Option<Token![|]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500965 pub pats: Punctuated<Pat, Token![|]>,
David Tolnay8b4d3022017-12-29 12:11:10 -0500966 pub guard: Option<(Token![if], Box<Expr>)>,
David Tolnaydfb91432018-03-31 19:19:44 +0200967 pub fat_arrow_token: Token![=>],
Alex Crichton62a0a592017-05-22 13:58:53 -0700968 pub body: Box<Expr>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800969 pub comma: Option<Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700970 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700971}
972
Michael Layzell734adb42017-06-07 16:58:31 -0400973#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700974ast_enum! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800975 /// Limit types of a range, inclusive or exclusive.
David Tolnay461d98e2018-01-07 11:07:19 -0800976 ///
977 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton2e0229c2017-05-23 09:34:50 -0700978 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700979 pub enum RangeLimits {
David Tolnaya454c8f2018-01-07 01:01:10 -0800980 /// Inclusive at the beginning, exclusive at the end.
David Tolnayf8db7ba2017-11-11 22:52:16 -0800981 HalfOpen(Token![..]),
David Tolnaya454c8f2018-01-07 01:01:10 -0800982 /// Inclusive at the beginning and end.
David Tolnaybe55d7b2017-12-17 23:41:20 -0800983 Closed(Token![..=]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700984 }
David Tolnayf4bbbd92016-09-23 14:41:55 -0700985}
986
Michael Layzell734adb42017-06-07 16:58:31 -0400987#[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -0700988ast_struct! {
David Tolnaya454c8f2018-01-07 01:01:10 -0800989 /// A single field in a struct pattern.
Alex Crichton62a0a592017-05-22 13:58:53 -0700990 ///
David Tolnaya454c8f2018-01-07 01:01:10 -0800991 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
992 /// 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 -0800993 ///
994 /// *This type is available if Syn is built with the `"full"` feature.*
Alex Crichton62a0a592017-05-22 13:58:53 -0700995 pub struct FieldPat {
David Tolnay4a3f59a2017-12-28 21:21:12 -0500996 pub attrs: Vec<Attribute>,
David Tolnay85b69a42017-12-27 20:43:10 -0500997 pub member: Member,
David Tolnay4a3f59a2017-12-28 21:21:12 -0500998 pub colon_token: Option<Token![:]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700999 pub pat: Box<Pat>,
Alex Crichton62a0a592017-05-22 13:58:53 -07001000 }
David Tolnayf4bbbd92016-09-23 14:41:55 -07001001}
1002
Michael Layzell3936ceb2017-07-08 00:28:36 -04001003#[cfg(any(feature = "parsing", feature = "printing"))]
1004#[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -07001005fn requires_terminator(expr: &Expr) -> bool {
David Tolnay01218d12018-08-29 18:13:07 -07001006 // see https://github.com/rust-lang/rust/blob/eb8f2586e/src/libsyntax/parse/classify.rs#L17-L37
David Tolnay8c91b882017-12-28 23:04:32 -05001007 match *expr {
1008 Expr::Unsafe(..)
1009 | Expr::Block(..)
1010 | Expr::If(..)
1011 | Expr::IfLet(..)
1012 | Expr::Match(..)
1013 | Expr::While(..)
1014 | Expr::WhileLet(..)
1015 | Expr::Loop(..)
1016 | Expr::ForLoop(..)
David Tolnay02a9c6f2018-08-24 18:58:45 -04001017 | Expr::Async(..)
David Tolnayfb2dd4b2018-08-24 16:45:34 -04001018 | Expr::TryBlock(..) => false,
Alex Crichton03b30272017-08-28 09:35:24 -07001019 _ => true,
Michael Layzell3936ceb2017-07-08 00:28:36 -04001020 }
1021}
1022
David Tolnayb9c8e322016-09-23 20:48:37 -07001023#[cfg(feature = "parsing")]
1024pub mod parsing {
1025 use super::*;
David Tolnayb9c8e322016-09-23 20:48:37 -07001026
Michael Layzell734adb42017-06-07 16:58:31 -04001027 #[cfg(feature = "full")]
David Tolnay94d304f2018-08-30 23:43:53 -07001028 use ext::IdentExt;
David Tolnay10951d52018-08-31 10:27:39 -07001029 use parse::{Parse, ParseStream, Result};
David Tolnay94d304f2018-08-30 23:43:53 -07001030 use path;
Alex Crichtonccbb45d2017-05-23 10:58:24 -07001031
David Tolnaybcf26022017-12-25 22:10:52 -05001032 // When we're parsing expressions which occur before blocks, like in an if
1033 // statement's condition, we cannot parse a struct literal.
1034 //
1035 // Struct literals are ambiguous in certain positions
1036 // https://github.com/rust-lang/rfcs/pull/92
David Tolnay9389c382018-08-27 09:13:37 -07001037 #[derive(Copy, Clone)]
1038 pub struct AllowStruct(bool);
1039
David Tolnay01218d12018-08-29 18:13:07 -07001040 #[derive(Copy, Clone, PartialEq, PartialOrd)]
1041 enum Precedence {
1042 Any,
1043 Assign,
1044 Placement,
1045 Range,
1046 Or,
1047 And,
1048 Compare,
1049 BitOr,
1050 BitXor,
1051 BitAnd,
1052 Shift,
1053 Arithmetic,
1054 Term,
1055 Cast,
1056 }
1057
1058 impl Precedence {
1059 fn of(op: &BinOp) -> Self {
1060 match *op {
1061 BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic,
1062 BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term,
1063 BinOp::And(_) => Precedence::And,
1064 BinOp::Or(_) => Precedence::Or,
1065 BinOp::BitXor(_) => Precedence::BitXor,
1066 BinOp::BitAnd(_) => Precedence::BitAnd,
1067 BinOp::BitOr(_) => Precedence::BitOr,
1068 BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
David Tolnay73b7ca12018-08-30 21:05:13 -07001069 BinOp::Eq(_)
1070 | BinOp::Lt(_)
1071 | BinOp::Le(_)
1072 | BinOp::Ne(_)
1073 | BinOp::Ge(_)
1074 | BinOp::Gt(_) => Precedence::Compare,
1075 BinOp::AddEq(_)
1076 | BinOp::SubEq(_)
1077 | BinOp::MulEq(_)
1078 | BinOp::DivEq(_)
1079 | BinOp::RemEq(_)
1080 | BinOp::BitXorEq(_)
1081 | BinOp::BitAndEq(_)
1082 | BinOp::BitOrEq(_)
1083 | BinOp::ShlEq(_)
1084 | BinOp::ShrEq(_) => Precedence::Assign,
David Tolnay01218d12018-08-29 18:13:07 -07001085 }
1086 }
1087 }
1088
David Tolnay9389c382018-08-27 09:13:37 -07001089 impl Parse for Expr {
1090 fn parse(input: ParseStream) -> Result<Self> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001091 ambiguous_expr(input, AllowStruct(true))
Alex Crichton954046c2017-05-30 21:49:42 -07001092 }
1093 }
1094
Michael Layzell734adb42017-06-07 16:58:31 -04001095 #[cfg(feature = "full")]
David Tolnay9fb0aed2018-08-27 10:23:12 -07001096 fn expr_no_struct(input: ParseStream) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001097 ambiguous_expr(input, AllowStruct(false))
David Tolnay9fb0aed2018-08-27 10:23:12 -07001098 }
David Tolnayaf2557e2016-10-24 11:52:21 -07001099
David Tolnay01218d12018-08-29 18:13:07 -07001100 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001101 fn parse_expr(
1102 input: ParseStream,
1103 mut lhs: Expr,
1104 allow_struct: AllowStruct,
1105 base: Precedence,
1106 ) -> Result<Expr> {
David Tolnay01218d12018-08-29 18:13:07 -07001107 loop {
David Tolnay73b7ca12018-08-30 21:05:13 -07001108 if input
1109 .fork()
1110 .parse::<BinOp>()
1111 .ok()
1112 .map_or(false, |op| Precedence::of(&op) >= base)
1113 {
David Tolnay01218d12018-08-29 18:13:07 -07001114 let op: BinOp = input.parse()?;
1115 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001116 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001117 loop {
1118 let next = peek_precedence(input);
1119 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001120 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001121 } else {
1122 break;
1123 }
1124 }
David Tolnay90276252018-08-31 10:50:08 -07001125 lhs = if precedence == Precedence::Assign {
1126 Expr::AssignOp(ExprAssignOp {
1127 attrs: Vec::new(),
1128 left: Box::new(lhs),
1129 op: op,
1130 right: Box::new(rhs),
1131 })
1132 } else {
1133 Expr::Binary(ExprBinary {
1134 attrs: Vec::new(),
1135 left: Box::new(lhs),
1136 op: op,
1137 right: Box::new(rhs),
1138 })
1139 };
David Tolnay73b7ca12018-08-30 21:05:13 -07001140 } else if Precedence::Assign >= base
1141 && input.peek(Token![=])
1142 && !input.peek(Token![==])
1143 && !input.peek(Token![=>])
1144 {
David Tolnay01218d12018-08-29 18:13:07 -07001145 let eq_token: Token![=] = input.parse()?;
David Tolnay7d2e1db2018-08-30 11:49:04 -07001146 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001147 loop {
1148 let next = peek_precedence(input);
1149 if next >= Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001150 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001151 } else {
1152 break;
1153 }
1154 }
1155 lhs = Expr::Assign(ExprAssign {
1156 attrs: Vec::new(),
1157 left: Box::new(lhs),
1158 eq_token: eq_token,
1159 right: Box::new(rhs),
1160 });
1161 } else if Precedence::Placement >= base && input.peek(Token![<-]) {
1162 let arrow_token: Token![<-] = input.parse()?;
David Tolnay7d2e1db2018-08-30 11:49:04 -07001163 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001164 loop {
1165 let next = peek_precedence(input);
1166 if next > Precedence::Placement {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001167 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001168 } else {
1169 break;
1170 }
1171 }
1172 lhs = Expr::InPlace(ExprInPlace {
1173 attrs: Vec::new(),
1174 place: Box::new(lhs),
1175 arrow_token: arrow_token,
1176 value: Box::new(rhs),
1177 });
1178 } else if Precedence::Range >= base && input.peek(Token![..]) {
1179 let limits: RangeLimits = input.parse()?;
1180 let rhs = if input.is_empty()
1181 || input.peek(Token![,])
1182 || input.peek(Token![;])
1183 || !allow_struct.0 && input.peek(token::Brace)
1184 {
1185 None
1186 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001187 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001188 loop {
1189 let next = peek_precedence(input);
1190 if next > Precedence::Range {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001191 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay01218d12018-08-29 18:13:07 -07001192 } else {
1193 break;
1194 }
1195 }
1196 Some(rhs)
1197 };
1198 lhs = Expr::Range(ExprRange {
1199 attrs: Vec::new(),
1200 from: Some(Box::new(lhs)),
1201 limits: limits,
1202 to: rhs.map(Box::new),
1203 });
1204 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1205 let as_token: Token![as] = input.parse()?;
1206 let ty = input.call(Type::without_plus)?;
1207 lhs = Expr::Cast(ExprCast {
1208 attrs: Vec::new(),
1209 expr: Box::new(lhs),
1210 as_token: as_token,
1211 ty: Box::new(ty),
1212 });
1213 } else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) {
1214 let colon_token: Token![:] = input.parse()?;
1215 let ty = input.call(Type::without_plus)?;
1216 lhs = Expr::Type(ExprType {
1217 attrs: Vec::new(),
1218 expr: Box::new(lhs),
1219 colon_token: colon_token,
1220 ty: Box::new(ty),
1221 });
1222 } else {
1223 break;
1224 }
1225 }
1226 Ok(lhs)
1227 }
1228
David Tolnay3e541292018-08-30 11:42:15 -07001229 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001230 fn parse_expr(
1231 input: ParseStream,
1232 mut lhs: Expr,
1233 allow_struct: AllowStruct,
1234 base: Precedence,
1235 ) -> Result<Expr> {
David Tolnay3e541292018-08-30 11:42:15 -07001236 loop {
David Tolnay73b7ca12018-08-30 21:05:13 -07001237 if input
1238 .fork()
1239 .parse::<BinOp>()
1240 .ok()
1241 .map_or(false, |op| Precedence::of(&op) >= base)
1242 {
David Tolnay3e541292018-08-30 11:42:15 -07001243 let op: BinOp = input.parse()?;
1244 let precedence = Precedence::of(&op);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001245 let mut rhs = unary_expr(input, allow_struct)?;
David Tolnay3e541292018-08-30 11:42:15 -07001246 loop {
1247 let next = peek_precedence(input);
1248 if next > precedence || next == precedence && precedence == Precedence::Assign {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001249 rhs = parse_expr(input, rhs, allow_struct, next)?;
David Tolnay3e541292018-08-30 11:42:15 -07001250 } else {
1251 break;
1252 }
1253 }
1254 lhs = Expr::Binary(ExprBinary {
1255 attrs: Vec::new(),
1256 left: Box::new(lhs),
1257 op: op,
1258 right: Box::new(rhs),
1259 });
1260 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1261 let as_token: Token![as] = input.parse()?;
1262 let ty = input.call(Type::without_plus)?;
1263 lhs = Expr::Cast(ExprCast {
1264 attrs: Vec::new(),
1265 expr: Box::new(lhs),
1266 as_token: as_token,
1267 ty: Box::new(ty),
1268 });
1269 } else {
1270 break;
1271 }
1272 }
1273 Ok(lhs)
1274 }
1275
David Tolnay01218d12018-08-29 18:13:07 -07001276 fn peek_precedence(input: ParseStream) -> Precedence {
1277 if let Ok(op) = input.fork().parse() {
1278 Precedence::of(&op)
David Tolnay3e541292018-08-30 11:42:15 -07001279 } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
David Tolnay01218d12018-08-29 18:13:07 -07001280 Precedence::Assign
1281 } else if input.peek(Token![<-]) {
1282 Precedence::Placement
1283 } else if input.peek(Token![..]) {
1284 Precedence::Range
1285 } else if input.peek(Token![as]) || input.peek(Token![:]) && !input.peek(Token![::]) {
1286 Precedence::Cast
1287 } else {
1288 Precedence::Any
1289 }
1290 }
1291
David Tolnaybcf26022017-12-25 22:10:52 -05001292 // Parse an arbitrary expression.
David Tolnay73b7ca12018-08-30 21:05:13 -07001293 fn ambiguous_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001294 let lhs = unary_expr(input, allow_struct)?;
1295 parse_expr(input, lhs, allow_struct, Precedence::Any)
Michael Layzellb78f3b52017-06-04 19:03:03 -04001296 }
1297
David Tolnaybcf26022017-12-25 22:10:52 -05001298 // <UnOp> <trailer>
1299 // & <trailer>
1300 // &mut <trailer>
1301 // box <trailer>
Michael Layzell734adb42017-06-07 16:58:31 -04001302 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001303 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001304 let ahead = input.fork();
1305 ahead.call(Attribute::parse_outer)?;
1306 if ahead.peek(Token![&])
1307 || ahead.peek(Token![box])
1308 || ahead.peek(Token![*])
1309 || ahead.peek(Token![!])
1310 || ahead.peek(Token![-])
1311 {
1312 let attrs = input.call(Attribute::parse_outer)?;
1313 if input.peek(Token![&]) {
1314 Ok(Expr::Reference(ExprReference {
1315 attrs: attrs,
1316 and_token: input.parse()?,
1317 mutability: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001318 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001319 }))
1320 } else if input.peek(Token![box]) {
1321 Ok(Expr::Box(ExprBox {
1322 attrs: attrs,
1323 box_token: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001324 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001325 }))
1326 } else {
1327 Ok(Expr::Unary(ExprUnary {
1328 attrs: attrs,
1329 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001330 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001331 }))
1332 }
1333 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001334 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001335 }
1336 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001337
Michael Layzell734adb42017-06-07 16:58:31 -04001338 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001339 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay377263f2018-08-27 13:48:30 -07001340 let ahead = input.fork();
1341 ahead.call(Attribute::parse_outer)?;
1342 if ahead.peek(Token![*]) || ahead.peek(Token![!]) || ahead.peek(Token![-]) {
1343 Ok(Expr::Unary(ExprUnary {
1344 attrs: input.call(Attribute::parse_outer)?,
1345 op: input.parse()?,
David Tolnay7d2e1db2018-08-30 11:49:04 -07001346 expr: Box::new(unary_expr(input, allow_struct)?),
David Tolnay377263f2018-08-27 13:48:30 -07001347 }))
1348 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001349 trailer_expr(input, allow_struct)
David Tolnay377263f2018-08-27 13:48:30 -07001350 }
1351 }
Michael Layzell734adb42017-06-07 16:58:31 -04001352
David Tolnaybcf26022017-12-25 22:10:52 -05001353 // <atom> (..<args>) ...
1354 // <atom> . <ident> (..<args>) ...
1355 // <atom> . <ident> ...
1356 // <atom> . <lit> ...
1357 // <atom> [ <expr> ] ...
1358 // <atom> ? ...
Michael Layzell734adb42017-06-07 16:58:31 -04001359 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07001360 fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay577fd312018-09-01 02:26:40 -07001361 if input.peek(token::Group) {
1362 return input.call(expr_group).map(Expr::Group);
1363 }
David Tolnay1501f7e2018-08-27 14:21:03 -07001364
David Tolnay577fd312018-09-01 02:26:40 -07001365 let outer_attrs = input.call(Attribute::parse_outer)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001366
David Tolnay577fd312018-09-01 02:26:40 -07001367 let atom = atom_expr(input, allow_struct)?;
1368 let mut e = trailer_helper(input, atom)?;
David Tolnay01218d12018-08-29 18:13:07 -07001369
David Tolnay577fd312018-09-01 02:26:40 -07001370 let inner_attrs = e.replace_attrs(Vec::new());
1371 let attrs = private::attrs(outer_attrs, inner_attrs);
David Tolnay01218d12018-08-29 18:13:07 -07001372 e.replace_attrs(attrs);
1373 Ok(e)
1374 }
1375
1376 #[cfg(feature = "full")]
1377 fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
David Tolnay1501f7e2018-08-27 14:21:03 -07001378 loop {
1379 if input.peek(token::Paren) {
1380 let content;
1381 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001382 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001383 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001384 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001385 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001386 });
1387 } else if input.peek(Token![.]) && !input.peek(Token![..]) {
1388 let dot_token: Token![.] = input.parse()?;
1389 let member: Member = input.parse()?;
1390 let turbofish = if member.is_named() && input.peek(Token![::]) {
1391 Some(MethodTurbofish {
1392 colon2_token: input.parse()?,
1393 lt_token: input.parse()?,
1394 args: {
1395 let mut args = Punctuated::new();
1396 loop {
1397 if input.peek(Token![>]) {
1398 break;
1399 }
David Tolnay310b3262018-08-30 15:33:00 -07001400 let value = input.call(generic_method_argument)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001401 args.push_value(value);
1402 if input.peek(Token![>]) {
1403 break;
1404 }
1405 let punct = input.parse()?;
1406 args.push_punct(punct);
1407 }
1408 args
1409 },
1410 gt_token: input.parse()?,
1411 })
1412 } else {
1413 None
1414 };
1415
1416 if turbofish.is_some() || input.peek(token::Paren) {
1417 if let Member::Named(method) = member {
1418 let content;
1419 e = Expr::MethodCall(ExprMethodCall {
1420 attrs: Vec::new(),
1421 receiver: Box::new(e),
1422 dot_token: dot_token,
1423 method: method,
1424 turbofish: turbofish,
1425 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001426 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001427 });
1428 continue;
1429 }
1430 }
1431
1432 e = Expr::Field(ExprField {
David Tolnay8c91b882017-12-28 23:04:32 -05001433 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001434 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001435 dot_token: dot_token,
David Tolnay85b69a42017-12-27 20:43:10 -05001436 member: member,
David Tolnay1501f7e2018-08-27 14:21:03 -07001437 });
1438 } else if input.peek(token::Bracket) {
1439 let content;
1440 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001441 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001442 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001443 bracket_token: bracketed!(content in input),
1444 index: content.parse()?,
1445 });
1446 } else if input.peek(Token![?]) {
1447 e = Expr::Try(ExprTry {
David Tolnay8c91b882017-12-28 23:04:32 -05001448 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001449 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001450 question_token: input.parse()?,
1451 });
1452 } else {
1453 break;
1454 }
1455 }
David Tolnay1501f7e2018-08-27 14:21:03 -07001456 Ok(e)
1457 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001458
Michael Layzell734adb42017-06-07 16:58:31 -04001459 #[cfg(not(feature = "full"))]
David Tolnay73b7ca12018-08-30 21:05:13 -07001460 fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay7d2e1db2018-08-30 11:49:04 -07001461 let mut e = atom_expr(input, allow_struct)?;
David Tolnay1501f7e2018-08-27 14:21:03 -07001462
1463 loop {
1464 if input.peek(token::Paren) {
1465 let content;
1466 e = Expr::Call(ExprCall {
David Tolnay8c91b882017-12-28 23:04:32 -05001467 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001468 func: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001469 paren_token: parenthesized!(content in input),
David Tolnay60484fe2018-08-30 18:43:04 -07001470 args: content.parse_terminated(Expr::parse)?,
David Tolnay1501f7e2018-08-27 14:21:03 -07001471 });
1472 } else if input.peek(Token![.]) {
1473 e = Expr::Field(ExprField {
David Tolnayd5147742018-06-30 10:09:52 -07001474 attrs: Vec::new(),
1475 base: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001476 dot_token: input.parse()?,
1477 member: input.parse()?,
1478 });
1479 } else if input.peek(token::Bracket) {
1480 let content;
1481 e = Expr::Index(ExprIndex {
David Tolnay8c91b882017-12-28 23:04:32 -05001482 attrs: Vec::new(),
David Tolnay3bc597f2017-12-31 02:31:11 -05001483 expr: Box::new(e),
David Tolnay1501f7e2018-08-27 14:21:03 -07001484 bracket_token: bracketed!(content in input),
1485 index: content.parse()?,
1486 });
1487 } else {
1488 break;
1489 }
1490 }
1491
1492 Ok(e)
1493 }
Michael Layzell734adb42017-06-07 16:58:31 -04001494
David Tolnaya454c8f2018-01-07 01:01:10 -08001495 // Parse all atomic expressions which don't have to worry about precedence
David Tolnaybcf26022017-12-25 22:10:52 -05001496 // interactions, as they are fully contained.
Michael Layzell734adb42017-06-07 16:58:31 -04001497 #[cfg(feature = "full")]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001498 fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001499 if input.peek(token::Group) {
David Tolnay577fd312018-09-01 02:26:40 -07001500 input.call(expr_group).map(Expr::Group)
David Tolnay6e1e5052018-08-30 10:21:48 -07001501 } else if input.peek(Lit) {
David Tolnay577fd312018-09-01 02:26:40 -07001502 input.call(expr_lit).map(Expr::Lit)
David Tolnay6e1e5052018-08-30 10:21:48 -07001503 } else if input.peek(Token![async])
1504 && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
1505 {
David Tolnay577fd312018-09-01 02:26:40 -07001506 input.call(expr_async).map(Expr::Async)
David Tolnay6e1e5052018-08-30 10:21:48 -07001507 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay577fd312018-09-01 02:26:40 -07001508 input.call(expr_try_block).map(Expr::TryBlock)
David Tolnay6e1e5052018-08-30 10:21:48 -07001509 } else if input.peek(Token![|])
1510 || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1511 || input.peek(Token![static])
1512 || input.peek(Token![move])
1513 {
David Tolnay577fd312018-09-01 02:26:40 -07001514 expr_closure(input, allow_struct).map(Expr::Closure)
David Tolnay6e1e5052018-08-30 10:21:48 -07001515 } else if input.peek(Ident)
1516 || input.peek(Token![::])
1517 || input.peek(Token![<])
1518 || input.peek(Token![self])
1519 || input.peek(Token![Self])
1520 || input.peek(Token![super])
1521 || input.peek(Token![extern])
1522 || input.peek(Token![crate])
1523 {
David Tolnay577fd312018-09-01 02:26:40 -07001524 path_or_macro_or_struct(input, allow_struct)
David Tolnay6e1e5052018-08-30 10:21:48 -07001525 } else if input.peek(token::Paren) {
David Tolnay577fd312018-09-01 02:26:40 -07001526 paren_or_tuple(input)
David Tolnay6e1e5052018-08-30 10:21:48 -07001527 } else if input.peek(Token![break]) {
David Tolnay577fd312018-09-01 02:26:40 -07001528 expr_break(input, allow_struct).map(Expr::Break)
David Tolnay6e1e5052018-08-30 10:21:48 -07001529 } else if input.peek(Token![continue]) {
David Tolnay577fd312018-09-01 02:26:40 -07001530 input.call(expr_continue).map(Expr::Continue)
David Tolnay6e1e5052018-08-30 10:21:48 -07001531 } else if input.peek(Token![return]) {
David Tolnay577fd312018-09-01 02:26:40 -07001532 expr_ret(input, allow_struct).map(Expr::Return)
David Tolnay6e1e5052018-08-30 10:21:48 -07001533 } else if input.peek(token::Bracket) {
David Tolnay577fd312018-09-01 02:26:40 -07001534 array_or_repeat(input)
David Tolnay6e1e5052018-08-30 10:21:48 -07001535 } else if input.peek(Token![if]) {
1536 if input.peek2(Token![let]) {
David Tolnay577fd312018-09-01 02:26:40 -07001537 input.call(expr_if_let).map(Expr::IfLet)
David Tolnay6e1e5052018-08-30 10:21:48 -07001538 } else {
David Tolnay577fd312018-09-01 02:26:40 -07001539 input.call(expr_if).map(Expr::If)
David Tolnay6e1e5052018-08-30 10:21:48 -07001540 }
1541 } else if input.peek(Token![while]) {
1542 if input.peek2(Token![let]) {
David Tolnay577fd312018-09-01 02:26:40 -07001543 input.call(expr_while_let).map(Expr::WhileLet)
David Tolnay6e1e5052018-08-30 10:21:48 -07001544 } else {
David Tolnay577fd312018-09-01 02:26:40 -07001545 input.call(expr_while).map(Expr::While)
David Tolnay6e1e5052018-08-30 10:21:48 -07001546 }
1547 } else if input.peek(Token![for]) {
David Tolnay577fd312018-09-01 02:26:40 -07001548 input.call(expr_for_loop).map(Expr::ForLoop)
David Tolnay6e1e5052018-08-30 10:21:48 -07001549 } else if input.peek(Token![loop]) {
David Tolnay577fd312018-09-01 02:26:40 -07001550 input.call(expr_loop).map(Expr::Loop)
David Tolnay6e1e5052018-08-30 10:21:48 -07001551 } else if input.peek(Token![match]) {
David Tolnay577fd312018-09-01 02:26:40 -07001552 input.call(expr_match).map(Expr::Match)
David Tolnay6e1e5052018-08-30 10:21:48 -07001553 } else if input.peek(Token![yield]) {
David Tolnay577fd312018-09-01 02:26:40 -07001554 input.call(expr_yield).map(Expr::Yield)
David Tolnay6e1e5052018-08-30 10:21:48 -07001555 } else if input.peek(Token![unsafe]) {
David Tolnay577fd312018-09-01 02:26:40 -07001556 input.call(expr_unsafe).map(Expr::Unsafe)
David Tolnay7d2e1db2018-08-30 11:49:04 -07001557 } else if input.peek(token::Brace) {
David Tolnay577fd312018-09-01 02:26:40 -07001558 input.call(expr_block).map(Expr::Block)
David Tolnay6e1e5052018-08-30 10:21:48 -07001559 } else if input.peek(Token![..]) {
David Tolnay577fd312018-09-01 02:26:40 -07001560 expr_range(input, allow_struct).map(Expr::Range)
David Tolnay6e1e5052018-08-30 10:21:48 -07001561 } else if input.peek(Lifetime) {
1562 let the_label: Label = input.parse()?;
1563 let mut expr = if input.peek(Token![while]) {
1564 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001565 Expr::WhileLet(input.call(expr_while_let)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001566 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001567 Expr::While(input.call(expr_while)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001568 }
1569 } else if input.peek(Token![for]) {
David Tolnay310b3262018-08-30 15:33:00 -07001570 Expr::ForLoop(input.call(expr_for_loop)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001571 } else if input.peek(Token![loop]) {
David Tolnay310b3262018-08-30 15:33:00 -07001572 Expr::Loop(input.call(expr_loop)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001573 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001574 Expr::Block(input.call(expr_block)?)
David Tolnay6e1e5052018-08-30 10:21:48 -07001575 } else {
1576 return Err(input.error("expected loop or block expression"));
1577 };
1578 match expr {
David Tolnay73b7ca12018-08-30 21:05:13 -07001579 Expr::WhileLet(ExprWhileLet { ref mut label, .. })
1580 | Expr::While(ExprWhile { ref mut label, .. })
1581 | Expr::ForLoop(ExprForLoop { ref mut label, .. })
1582 | Expr::Loop(ExprLoop { ref mut label, .. })
1583 | Expr::Block(ExprBlock { ref mut label, .. }) => *label = Some(the_label),
David Tolnay6e1e5052018-08-30 10:21:48 -07001584 _ => unreachable!(),
1585 }
David Tolnay577fd312018-09-01 02:26:40 -07001586 Ok(expr)
David Tolnay6e1e5052018-08-30 10:21:48 -07001587 } else {
David Tolnay577fd312018-09-01 02:26:40 -07001588 Err(input.error("expected expression"))
1589 }
David Tolnay6e1e5052018-08-30 10:21:48 -07001590 }
Michael Layzellb78f3b52017-06-04 19:03:03 -04001591
Michael Layzell734adb42017-06-07 16:58:31 -04001592 #[cfg(not(feature = "full"))]
David Tolnay7d2e1db2018-08-30 11:49:04 -07001593 fn atom_expr(input: ParseStream, _allow_struct: AllowStruct) -> Result<Expr> {
David Tolnay6e1e5052018-08-30 10:21:48 -07001594 if input.peek(Lit) {
David Tolnay310b3262018-08-30 15:33:00 -07001595 input.call(expr_lit).map(Expr::Lit)
David Tolnay6e1e5052018-08-30 10:21:48 -07001596 } else if input.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07001597 input.call(expr_paren).map(Expr::Paren)
David Tolnay6e1e5052018-08-30 10:21:48 -07001598 } else if input.peek(Ident)
1599 || input.peek(Token![::])
1600 || input.peek(Token![<])
1601 || input.peek(Token![self])
1602 || input.peek(Token![Self])
1603 || input.peek(Token![super])
1604 || input.peek(Token![extern])
1605 || input.peek(Token![crate])
1606 {
1607 input.parse().map(Expr::Path)
1608 } else {
1609 Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
1610 }
1611 }
1612
1613 #[cfg(feature = "full")]
1614 fn path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1615 let expr: ExprPath = input.parse()?;
1616 if expr.qself.is_some() {
1617 return Ok(Expr::Path(expr));
1618 }
1619
1620 if input.peek(Token![!]) && !input.peek(Token![!=]) {
1621 let mut contains_arguments = false;
1622 for segment in &expr.path.segments {
1623 match segment.arguments {
1624 PathArguments::None => {}
1625 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
1626 contains_arguments = true;
1627 }
1628 }
1629 }
1630
1631 if !contains_arguments {
1632 let bang_token: Token![!] = input.parse()?;
1633 let (delimiter, tts) = mac::parse_delimiter(input)?;
1634 return Ok(Expr::Macro(ExprMacro {
1635 attrs: Vec::new(),
1636 mac: Macro {
1637 path: expr.path,
1638 bang_token: bang_token,
1639 delimiter: delimiter,
1640 tts: tts,
1641 },
1642 }));
1643 }
1644 }
1645
1646 if allow_struct.0 && input.peek(token::Brace) {
1647 let outer_attrs = Vec::new();
1648 expr_struct_helper(input, outer_attrs, expr.path).map(Expr::Struct)
1649 } else {
1650 Ok(Expr::Path(expr))
1651 }
1652 }
1653
1654 #[cfg(feature = "full")]
1655 fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
1656 let content;
1657 let paren_token = parenthesized!(content in input);
1658 let inner_attrs = content.call(Attribute::parse_inner)?;
1659 if content.is_empty() {
1660 return Ok(Expr::Tuple(ExprTuple {
1661 attrs: inner_attrs,
1662 paren_token: paren_token,
1663 elems: Punctuated::new(),
1664 }));
1665 }
1666
1667 let first: Expr = content.parse()?;
1668 if content.is_empty() {
1669 return Ok(Expr::Paren(ExprParen {
1670 attrs: inner_attrs,
1671 paren_token: paren_token,
1672 expr: Box::new(first),
1673 }));
1674 }
1675
1676 let mut elems = Punctuated::new();
1677 elems.push_value(first);
1678 while !content.is_empty() {
1679 let punct = content.parse()?;
1680 elems.push_punct(punct);
1681 if content.is_empty() {
1682 break;
1683 }
1684 let value = content.parse()?;
1685 elems.push_value(value);
1686 }
1687 Ok(Expr::Tuple(ExprTuple {
1688 attrs: inner_attrs,
1689 paren_token: paren_token,
1690 elems: elems,
1691 }))
1692 }
1693
1694 #[cfg(feature = "full")]
1695 fn array_or_repeat(input: ParseStream) -> Result<Expr> {
1696 let content;
1697 let bracket_token = bracketed!(content in input);
1698 let inner_attrs = content.call(Attribute::parse_inner)?;
1699 if content.is_empty() {
1700 return Ok(Expr::Array(ExprArray {
1701 attrs: inner_attrs,
1702 bracket_token: bracket_token,
1703 elems: Punctuated::new(),
1704 }));
1705 }
1706
1707 let first: Expr = content.parse()?;
1708 if content.is_empty() || content.peek(Token![,]) {
1709 let mut elems = Punctuated::new();
1710 elems.push_value(first);
1711 while !content.is_empty() {
1712 let punct = content.parse()?;
1713 elems.push_punct(punct);
1714 if content.is_empty() {
1715 break;
1716 }
1717 let value = content.parse()?;
1718 elems.push_value(value);
1719 }
1720 Ok(Expr::Array(ExprArray {
1721 attrs: inner_attrs,
1722 bracket_token: bracket_token,
1723 elems: elems,
1724 }))
1725 } else if content.peek(Token![;]) {
1726 let semi_token: Token![;] = content.parse()?;
1727 let len: Expr = content.parse()?;
1728 Ok(Expr::Repeat(ExprRepeat {
1729 attrs: inner_attrs,
1730 bracket_token: bracket_token,
1731 expr: Box::new(first),
1732 semi_token: semi_token,
1733 len: Box::new(len),
1734 }))
1735 } else {
1736 Err(content.error("expected `,` or `;`"))
1737 }
1738 }
Michael Layzell734adb42017-06-07 16:58:31 -04001739
Michael Layzell734adb42017-06-07 16:58:31 -04001740 #[cfg(feature = "full")]
David Tolnay01218d12018-08-29 18:13:07 -07001741 fn expr_early(input: ParseStream) -> Result<Expr> {
1742 let mut attrs = input.call(Attribute::parse_outer)?;
1743 let mut expr = if input.peek(Token![if]) {
1744 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001745 Expr::IfLet(input.call(expr_if_let)?)
David Tolnay01218d12018-08-29 18:13:07 -07001746 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001747 Expr::If(input.call(expr_if)?)
David Tolnay01218d12018-08-29 18:13:07 -07001748 }
1749 } else if input.peek(Token![while]) {
1750 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001751 Expr::WhileLet(input.call(expr_while_let)?)
David Tolnay01218d12018-08-29 18:13:07 -07001752 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001753 Expr::While(input.call(expr_while)?)
David Tolnay01218d12018-08-29 18:13:07 -07001754 }
1755 } else if input.peek(Token![for]) {
David Tolnay310b3262018-08-30 15:33:00 -07001756 Expr::ForLoop(input.call(expr_for_loop)?)
David Tolnay01218d12018-08-29 18:13:07 -07001757 } else if input.peek(Token![loop]) {
David Tolnay310b3262018-08-30 15:33:00 -07001758 Expr::Loop(input.call(expr_loop)?)
David Tolnay01218d12018-08-29 18:13:07 -07001759 } else if input.peek(Token![match]) {
David Tolnay310b3262018-08-30 15:33:00 -07001760 Expr::Match(input.call(expr_match)?)
David Tolnay01218d12018-08-29 18:13:07 -07001761 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001762 Expr::TryBlock(input.call(expr_try_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001763 } else if input.peek(Token![unsafe]) {
David Tolnay310b3262018-08-30 15:33:00 -07001764 Expr::Unsafe(input.call(expr_unsafe)?)
David Tolnay01218d12018-08-29 18:13:07 -07001765 } else if input.peek(token::Brace) {
David Tolnay310b3262018-08-30 15:33:00 -07001766 Expr::Block(input.call(expr_block)?)
David Tolnay01218d12018-08-29 18:13:07 -07001767 } else {
1768 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001769 let mut expr = unary_expr(input, allow_struct)?;
David Tolnay01218d12018-08-29 18:13:07 -07001770
1771 attrs.extend(expr.replace_attrs(Vec::new()));
1772 expr.replace_attrs(attrs);
1773
David Tolnay7d2e1db2018-08-30 11:49:04 -07001774 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001775 };
1776
1777 if input.peek(Token![.]) || input.peek(Token![?]) {
1778 expr = trailer_helper(input, expr)?;
1779
1780 attrs.extend(expr.replace_attrs(Vec::new()));
1781 expr.replace_attrs(attrs);
1782
1783 let allow_struct = AllowStruct(true);
David Tolnay7d2e1db2018-08-30 11:49:04 -07001784 return parse_expr(input, expr, allow_struct, Precedence::Any);
David Tolnay01218d12018-08-29 18:13:07 -07001785 }
1786
1787 attrs.extend(expr.replace_attrs(Vec::new()));
1788 expr.replace_attrs(attrs);
1789 Ok(expr)
1790 }
Michael Layzell35418782017-06-07 09:20:25 -04001791
David Tolnay310b3262018-08-30 15:33:00 -07001792 pub fn expr_lit(input: ParseStream) -> Result<ExprLit> {
1793 Ok(ExprLit {
1794 attrs: Vec::new(),
1795 lit: input.parse()?,
1796 })
David Tolnay8c91b882017-12-28 23:04:32 -05001797 }
1798
1799 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001800 fn expr_group(input: ParseStream) -> Result<ExprGroup> {
David Tolnay10951d52018-08-31 10:27:39 -07001801 let group = private::parse_group(input)?;
David Tolnay310b3262018-08-30 15:33:00 -07001802 Ok(ExprGroup {
1803 attrs: Vec::new(),
David Tolnayf57f76f2018-08-31 10:23:17 -07001804 group_token: group.token,
1805 expr: group.content.parse()?,
David Tolnay310b3262018-08-30 15:33:00 -07001806 })
1807 }
1808
1809 #[cfg(not(feature = "full"))]
1810 fn expr_paren(input: ParseStream) -> Result<ExprParen> {
1811 let content;
1812 Ok(ExprParen {
1813 attrs: Vec::new(),
1814 paren_token: parenthesized!(content in input),
1815 expr: content.parse()?,
1816 })
David Tolnay8c91b882017-12-28 23:04:32 -05001817 }
1818
David Tolnaye98775f2017-12-28 23:17:00 -05001819 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001820 fn generic_method_argument(input: ParseStream) -> Result<GenericMethodArgument> {
David Tolnayd60cfec2017-12-29 00:21:38 -05001821 // TODO parse const generics as well
David Tolnay8db2d662018-08-30 17:40:59 -07001822 input.parse().map(GenericMethodArgument::Type)
David Tolnayd60cfec2017-12-29 00:21:38 -05001823 }
1824
1825 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001826 fn expr_if_let(input: ParseStream) -> Result<ExprIfLet> {
1827 Ok(ExprIfLet {
1828 attrs: Vec::new(),
1829 if_token: input.parse()?,
1830 let_token: input.parse()?,
1831 pats: {
1832 let mut pats = Punctuated::new();
1833 let value: Pat = input.parse()?;
1834 pats.push_value(value);
David Tolnay73b7ca12018-08-30 21:05:13 -07001835 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
David Tolnay310b3262018-08-30 15:33:00 -07001836 let punct = input.parse()?;
1837 pats.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07001838 let value: Pat = input.parse()?;
1839 pats.push_value(value);
David Tolnay310b3262018-08-30 15:33:00 -07001840 }
1841 pats
1842 },
1843 eq_token: input.parse()?,
1844 expr: Box::new(input.call(expr_no_struct)?),
1845 then_branch: input.parse()?,
1846 else_branch: {
1847 if input.peek(Token![else]) {
1848 Some(input.call(else_block)?)
1849 } else {
1850 None
1851 }
1852 },
1853 })
David Tolnay29f9ce12016-10-02 20:58:40 -07001854 }
1855
Michael Layzell734adb42017-06-07 16:58:31 -04001856 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001857 fn expr_if(input: ParseStream) -> Result<ExprIf> {
1858 Ok(ExprIf {
1859 attrs: Vec::new(),
1860 if_token: input.parse()?,
1861 cond: Box::new(input.call(expr_no_struct)?),
1862 then_branch: input.parse()?,
1863 else_branch: {
1864 if input.peek(Token![else]) {
1865 Some(input.call(else_block)?)
1866 } else {
1867 None
1868 }
1869 },
1870 })
Alex Crichton954046c2017-05-30 21:49:42 -07001871 }
David Tolnaybb6feae2016-10-02 21:25:20 -07001872
Michael Layzell734adb42017-06-07 16:58:31 -04001873 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07001874 fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
1875 let else_token: Token![else] = input.parse()?;
1876
1877 let lookahead = input.lookahead1();
1878 let else_branch = if input.peek(Token![if]) {
1879 if input.peek2(Token![let]) {
David Tolnay310b3262018-08-30 15:33:00 -07001880 input.call(expr_if_let).map(Expr::IfLet)?
David Tolnay60291082018-08-28 09:54:49 -07001881 } else {
David Tolnay310b3262018-08-30 15:33:00 -07001882 input.call(expr_if).map(Expr::If)?
David Tolnay60291082018-08-28 09:54:49 -07001883 }
1884 } else if input.peek(token::Brace) {
1885 Expr::Block(ExprBlock {
1886 attrs: Vec::new(),
1887 label: None,
1888 block: input.parse()?,
1889 })
1890 } else {
1891 return Err(lookahead.error());
1892 };
1893
1894 Ok((else_token, Box::new(else_branch)))
1895 }
David Tolnay939766a2016-09-23 23:48:12 -07001896
Michael Layzell734adb42017-06-07 16:58:31 -04001897 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001898 fn expr_for_loop(input: ParseStream) -> Result<ExprForLoop> {
1899 let label: Option<Label> = input.parse()?;
1900 let for_token: Token![for] = input.parse()?;
1901 let pat: Pat = input.parse()?;
1902 let in_token: Token![in] = input.parse()?;
1903 let expr: Expr = input.call(expr_no_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07001904
David Tolnay310b3262018-08-30 15:33:00 -07001905 let content;
1906 let brace_token = braced!(content in input);
1907 let inner_attrs = content.call(Attribute::parse_inner)?;
1908 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07001909
David Tolnay310b3262018-08-30 15:33:00 -07001910 Ok(ExprForLoop {
1911 attrs: inner_attrs,
1912 label: label,
1913 for_token: for_token,
1914 pat: Box::new(pat),
1915 in_token: in_token,
1916 expr: Box::new(expr),
1917 body: Block {
David Tolnay60291082018-08-28 09:54:49 -07001918 brace_token: brace_token,
David Tolnay310b3262018-08-30 15:33:00 -07001919 stmts: stmts,
1920 },
1921 })
Alex Crichton954046c2017-05-30 21:49:42 -07001922 }
David Tolnay1978c672016-10-27 22:05:52 -07001923
Michael Layzell734adb42017-06-07 16:58:31 -04001924 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001925 fn expr_loop(input: ParseStream) -> Result<ExprLoop> {
1926 let label: Option<Label> = input.parse()?;
1927 let loop_token: Token![loop] = input.parse()?;
1928
1929 let content;
1930 let brace_token = braced!(content in input);
1931 let inner_attrs = content.call(Attribute::parse_inner)?;
1932 let stmts = content.call(Block::parse_within)?;
1933
1934 Ok(ExprLoop {
1935 attrs: inner_attrs,
1936 label: label,
1937 loop_token: loop_token,
1938 body: Block {
1939 brace_token: brace_token,
1940 stmts: stmts,
1941 },
1942 })
Alex Crichton954046c2017-05-30 21:49:42 -07001943 }
Arnavion02ef13f2017-04-25 00:54:31 -07001944
Michael Layzell734adb42017-06-07 16:58:31 -04001945 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07001946 fn expr_match(input: ParseStream) -> Result<ExprMatch> {
1947 let match_token: Token![match] = input.parse()?;
1948 let expr = expr_no_struct(input)?;
1949
1950 let content;
1951 let brace_token = braced!(content in input);
1952 let inner_attrs = content.call(Attribute::parse_inner)?;
1953
1954 let mut arms = Vec::new();
1955 while !content.is_empty() {
1956 arms.push(content.call(match_arm)?);
1957 }
1958
1959 Ok(ExprMatch {
1960 attrs: inner_attrs,
1961 match_token: match_token,
1962 expr: Box::new(expr),
1963 brace_token: brace_token,
1964 arms: arms,
1965 })
1966 }
1967
1968 #[cfg(feature = "full")]
1969 fn expr_try_block(input: ParseStream) -> Result<ExprTryBlock> {
1970 Ok(ExprTryBlock {
1971 attrs: Vec::new(),
1972 try_token: input.parse()?,
1973 block: input.parse()?,
1974 })
1975 }
1976
1977 #[cfg(feature = "full")]
1978 fn expr_yield(input: ParseStream) -> Result<ExprYield> {
1979 Ok(ExprYield {
1980 attrs: Vec::new(),
1981 yield_token: input.parse()?,
1982 expr: {
1983 if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
1984 Some(input.parse()?)
1985 } else {
1986 None
1987 }
1988 },
1989 })
1990 }
1991
1992 #[cfg(feature = "full")]
1993 fn match_arm(input: ParseStream) -> Result<Arm> {
1994 let requires_comma;
1995 Ok(Arm {
1996 attrs: input.call(Attribute::parse_outer)?,
1997 leading_vert: input.parse()?,
1998 pats: {
1999 let mut pats = Punctuated::new();
2000 let value: Pat = input.parse()?;
2001 pats.push_value(value);
2002 loop {
2003 if !input.peek(Token![|]) {
2004 break;
David Tolnay60291082018-08-28 09:54:49 -07002005 }
David Tolnay310b3262018-08-30 15:33:00 -07002006 let punct = input.parse()?;
2007 pats.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002008 let value: Pat = input.parse()?;
2009 pats.push_value(value);
David Tolnay310b3262018-08-30 15:33:00 -07002010 }
2011 pats
2012 },
2013 guard: {
2014 if input.peek(Token![if]) {
2015 let if_token: Token![if] = input.parse()?;
2016 let guard: Expr = input.parse()?;
2017 Some((if_token, Box::new(guard)))
2018 } else {
2019 None
2020 }
2021 },
2022 fat_arrow_token: input.parse()?,
2023 body: {
2024 let body = input.call(expr_early)?;
David Tolnaye532d6b2018-08-30 16:55:01 -07002025 requires_comma = requires_terminator(&body);
David Tolnay310b3262018-08-30 15:33:00 -07002026 Box::new(body)
2027 },
2028 comma: {
2029 if requires_comma && !input.is_empty() {
2030 Some(input.parse()?)
2031 } else {
2032 input.parse()?
2033 }
2034 },
2035 })
Alex Crichton954046c2017-05-30 21:49:42 -07002036 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07002037
Michael Layzell734adb42017-06-07 16:58:31 -04002038 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002039 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
David Tolnay60291082018-08-28 09:54:49 -07002040 let asyncness: Option<Token![async]> = input.parse()?;
2041 let movability: Option<Token![static]> = if asyncness.is_none() {
2042 input.parse()?
2043 } else {
2044 None
2045 };
2046 let capture: Option<Token![move]> = input.parse()?;
2047 let or1_token: Token![|] = input.parse()?;
2048
2049 let mut inputs = Punctuated::new();
2050 loop {
2051 if input.peek(Token![|]) {
2052 break;
2053 }
2054 let value = fn_arg(input)?;
2055 inputs.push_value(value);
2056 if input.peek(Token![|]) {
2057 break;
2058 }
2059 let punct: Token![,] = input.parse()?;
2060 inputs.push_punct(punct);
2061 }
2062
2063 let or2_token: Token![|] = input.parse()?;
2064
2065 let (output, body) = if input.peek(Token![->]) {
2066 let arrow_token: Token![->] = input.parse()?;
2067 let ty: Type = input.parse()?;
2068 let body: Block = input.parse()?;
2069 let output = ReturnType::Type(arrow_token, Box::new(ty));
2070 let block = Expr::Block(ExprBlock {
2071 attrs: Vec::new(),
2072 label: None,
2073 block: body,
2074 });
2075 (output, block)
2076 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002077 let body = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002078 (ReturnType::Default, body)
2079 };
2080
2081 Ok(ExprClosure {
David Tolnay310b3262018-08-30 15:33:00 -07002082 attrs: Vec::new(),
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002083 asyncness: asyncness,
2084 movability: movability,
2085 capture: capture,
David Tolnay60291082018-08-28 09:54:49 -07002086 or1_token: or1_token,
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09002087 inputs: inputs,
David Tolnay60291082018-08-28 09:54:49 -07002088 or2_token: or2_token,
2089 output: output,
2090 body: Box::new(body),
2091 })
David Tolnay02a9c6f2018-08-24 18:58:45 -04002092 }
Yusuke Sasaki851062f2018-08-01 06:28:28 +09002093
2094 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002095 fn expr_async(input: ParseStream) -> Result<ExprAsync> {
2096 Ok(ExprAsync {
2097 attrs: Vec::new(),
2098 async_token: input.parse()?,
2099 capture: input.parse()?,
2100 block: input.parse()?,
2101 })
David Tolnay60291082018-08-28 09:54:49 -07002102 }
Gregory Katz3e562cc2016-09-28 18:33:02 -04002103
Michael Layzell734adb42017-06-07 16:58:31 -04002104 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002105 fn fn_arg(input: ParseStream) -> Result<FnArg> {
2106 let pat: Pat = input.parse()?;
2107
2108 if input.peek(Token![:]) {
2109 Ok(FnArg::Captured(ArgCaptured {
2110 pat: pat,
2111 colon_token: input.parse()?,
2112 ty: input.parse()?,
2113 }))
2114 } else {
2115 Ok(FnArg::Inferred(pat))
2116 }
2117 }
2118
2119 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002120 fn expr_while(input: ParseStream) -> Result<ExprWhile> {
2121 let label: Option<Label> = input.parse()?;
2122 let while_token: Token![while] = input.parse()?;
2123 let cond = expr_no_struct(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002124
David Tolnay310b3262018-08-30 15:33:00 -07002125 let content;
2126 let brace_token = braced!(content in input);
2127 let inner_attrs = content.call(Attribute::parse_inner)?;
2128 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002129
David Tolnay310b3262018-08-30 15:33:00 -07002130 Ok(ExprWhile {
2131 attrs: inner_attrs,
2132 label: label,
2133 while_token: while_token,
2134 cond: Box::new(cond),
2135 body: Block {
2136 brace_token: brace_token,
2137 stmts: stmts,
2138 },
2139 })
Alex Crichton954046c2017-05-30 21:49:42 -07002140 }
2141
Michael Layzell734adb42017-06-07 16:58:31 -04002142 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002143 fn expr_while_let(input: ParseStream) -> Result<ExprWhileLet> {
2144 let label: Option<Label> = input.parse()?;
2145 let while_token: Token![while] = input.parse()?;
2146 let let_token: Token![let] = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002147
David Tolnay310b3262018-08-30 15:33:00 -07002148 let mut pats = Punctuated::new();
2149 let value: Pat = input.parse()?;
2150 pats.push_value(value);
2151 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2152 let punct = input.parse()?;
2153 pats.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002154 let value: Pat = input.parse()?;
2155 pats.push_value(value);
David Tolnay60291082018-08-28 09:54:49 -07002156 }
David Tolnay310b3262018-08-30 15:33:00 -07002157
2158 let eq_token: Token![=] = input.parse()?;
2159 let expr = expr_no_struct(input)?;
2160
2161 let content;
2162 let brace_token = braced!(content in input);
2163 let inner_attrs = content.call(Attribute::parse_inner)?;
2164 let stmts = content.call(Block::parse_within)?;
2165
2166 Ok(ExprWhileLet {
2167 attrs: inner_attrs,
2168 label: label,
2169 while_token: while_token,
2170 let_token: let_token,
2171 pats: pats,
2172 eq_token: eq_token,
2173 expr: Box::new(expr),
2174 body: Block {
2175 brace_token: brace_token,
2176 stmts: stmts,
2177 },
2178 })
David Tolnaybcd498f2017-12-29 12:02:33 -05002179 }
2180
2181 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002182 impl Parse for Label {
2183 fn parse(input: ParseStream) -> Result<Self> {
2184 Ok(Label {
2185 name: input.parse()?,
2186 colon_token: input.parse()?,
Michael Layzell92639a52017-06-01 00:07:44 -04002187 })
David Tolnay60291082018-08-28 09:54:49 -07002188 }
Alex Crichton954046c2017-05-30 21:49:42 -07002189 }
2190
Michael Layzell734adb42017-06-07 16:58:31 -04002191 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002192 impl Parse for Option<Label> {
2193 fn parse(input: ParseStream) -> Result<Self> {
2194 if input.peek(Lifetime) {
2195 input.parse().map(Some)
2196 } else {
2197 Ok(None)
2198 }
2199 }
2200 }
2201
2202 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002203 fn expr_continue(input: ParseStream) -> Result<ExprContinue> {
2204 Ok(ExprContinue {
2205 attrs: Vec::new(),
2206 continue_token: input.parse()?,
2207 label: input.parse()?,
2208 })
Alex Crichton954046c2017-05-30 21:49:42 -07002209 }
Gregory Katzfd6935d2016-09-30 22:51:25 -04002210
Michael Layzell734adb42017-06-07 16:58:31 -04002211 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002212 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2213 Ok(ExprBreak {
David Tolnay310b3262018-08-30 15:33:00 -07002214 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002215 break_token: input.parse()?,
2216 label: input.parse()?,
2217 expr: {
2218 if input.is_empty()
2219 || input.peek(Token![,])
2220 || input.peek(Token![;])
2221 || !allow_struct.0 && input.peek(token::Brace)
2222 {
2223 None
2224 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002225 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002226 Some(Box::new(expr))
Michael Layzell92639a52017-06-01 00:07:44 -04002227 }
David Tolnay60291082018-08-28 09:54:49 -07002228 },
2229 })
Alex Crichton954046c2017-05-30 21:49:42 -07002230 }
2231
Michael Layzell734adb42017-06-07 16:58:31 -04002232 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002233 fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
2234 Ok(ExprReturn {
David Tolnay310b3262018-08-30 15:33:00 -07002235 attrs: Vec::new(),
David Tolnay60291082018-08-28 09:54:49 -07002236 return_token: input.parse()?,
2237 expr: {
2238 if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
2239 None
2240 } else {
2241 // NOTE: return is greedy and eats blocks after it even when in a
2242 // position where structs are not allowed, such as in if statement
2243 // conditions. For example:
2244 //
2245 // if return { println!("A") } {} // Prints "A"
David Tolnay7d2e1db2018-08-30 11:49:04 -07002246 let expr = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002247 Some(Box::new(expr))
2248 }
2249 },
2250 })
2251 }
2252
2253 #[cfg(feature = "full")]
David Tolnay73b7ca12018-08-30 21:05:13 -07002254 fn expr_struct_helper(
2255 input: ParseStream,
2256 outer_attrs: Vec<Attribute>,
2257 path: Path,
2258 ) -> Result<ExprStruct> {
David Tolnay6e1e5052018-08-30 10:21:48 -07002259 let content;
2260 let brace_token = braced!(content in input);
2261 let inner_attrs = content.call(Attribute::parse_inner)?;
David Tolnay60291082018-08-28 09:54:49 -07002262
David Tolnay6e1e5052018-08-30 10:21:48 -07002263 let mut fields = Punctuated::new();
2264 loop {
2265 let attrs = content.call(Attribute::parse_outer)?;
2266 if content.fork().parse::<Member>().is_err() {
2267 if attrs.is_empty() {
David Tolnay60291082018-08-28 09:54:49 -07002268 break;
David Tolnay6e1e5052018-08-30 10:21:48 -07002269 } else {
2270 return Err(content.error("expected struct field"));
David Tolnay60291082018-08-28 09:54:49 -07002271 }
David Tolnay60291082018-08-28 09:54:49 -07002272 }
2273
David Tolnay6e1e5052018-08-30 10:21:48 -07002274 let member: Member = content.parse()?;
2275 let (colon_token, value) = if content.peek(Token![:]) || !member.is_named() {
2276 let colon_token: Token![:] = content.parse()?;
2277 let value: Expr = content.parse()?;
2278 (Some(colon_token), value)
2279 } else if let Member::Named(ref ident) = member {
2280 let value = Expr::Path(ExprPath {
2281 attrs: Vec::new(),
2282 qself: None,
2283 path: Path::from(ident.clone()),
2284 });
2285 (None, value)
David Tolnay60291082018-08-28 09:54:49 -07002286 } else {
David Tolnay6e1e5052018-08-30 10:21:48 -07002287 unreachable!()
David Tolnay60291082018-08-28 09:54:49 -07002288 };
2289
David Tolnay6e1e5052018-08-30 10:21:48 -07002290 fields.push(FieldValue {
2291 attrs: attrs,
2292 member: member,
2293 colon_token: colon_token,
2294 expr: value,
2295 });
2296
2297 if !content.peek(Token![,]) {
2298 break;
2299 }
2300 let punct: Token![,] = content.parse()?;
2301 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002302 }
David Tolnay6e1e5052018-08-30 10:21:48 -07002303
2304 let (dot2_token, rest) = if fields.empty_or_trailing() && content.peek(Token![..]) {
2305 let dot2_token: Token![..] = content.parse()?;
2306 let rest: Expr = content.parse()?;
2307 (Some(dot2_token), Some(Box::new(rest)))
2308 } else {
2309 (None, None)
2310 };
2311
2312 Ok(ExprStruct {
David Tolnayb5f6fc02018-09-01 02:18:50 -07002313 attrs: private::attrs(outer_attrs, inner_attrs),
David Tolnay6e1e5052018-08-30 10:21:48 -07002314 brace_token: brace_token,
2315 path: path,
2316 fields: fields,
2317 dot2_token: dot2_token,
2318 rest: rest,
2319 })
Alex Crichton954046c2017-05-30 21:49:42 -07002320 }
David Tolnay055a7042016-10-02 19:23:54 -07002321
Michael Layzell734adb42017-06-07 16:58:31 -04002322 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002323 fn expr_unsafe(input: ParseStream) -> Result<ExprUnsafe> {
2324 let unsafe_token: Token![unsafe] = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002325
David Tolnay310b3262018-08-30 15:33:00 -07002326 let content;
2327 let brace_token = braced!(content in input);
2328 let inner_attrs = content.call(Attribute::parse_inner)?;
2329 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002330
David Tolnay310b3262018-08-30 15:33:00 -07002331 Ok(ExprUnsafe {
2332 attrs: inner_attrs,
2333 unsafe_token: unsafe_token,
2334 block: Block {
2335 brace_token: brace_token,
2336 stmts: stmts,
2337 },
2338 })
Alex Crichton954046c2017-05-30 21:49:42 -07002339 }
David Tolnay055a7042016-10-02 19:23:54 -07002340
Michael Layzell734adb42017-06-07 16:58:31 -04002341 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002342 pub fn expr_block(input: ParseStream) -> Result<ExprBlock> {
2343 let label: Option<Label> = input.parse()?;
David Tolnay60291082018-08-28 09:54:49 -07002344
David Tolnay310b3262018-08-30 15:33:00 -07002345 let content;
2346 let brace_token = braced!(content in input);
2347 let inner_attrs = content.call(Attribute::parse_inner)?;
2348 let stmts = content.call(Block::parse_within)?;
David Tolnay60291082018-08-28 09:54:49 -07002349
David Tolnay310b3262018-08-30 15:33:00 -07002350 Ok(ExprBlock {
2351 attrs: inner_attrs,
2352 label: label,
2353 block: Block {
2354 brace_token: brace_token,
2355 stmts: stmts,
2356 },
2357 })
Alex Crichton954046c2017-05-30 21:49:42 -07002358 }
David Tolnay89e05672016-10-02 14:39:42 -07002359
Michael Layzell734adb42017-06-07 16:58:31 -04002360 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002361 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2362 Ok(ExprRange {
David Tolnay8c91b882017-12-28 23:04:32 -05002363 attrs: Vec::new(),
2364 from: None,
David Tolnay60291082018-08-28 09:54:49 -07002365 limits: input.parse()?,
2366 to: {
2367 if input.is_empty()
2368 || input.peek(Token![,])
2369 || input.peek(Token![;])
2370 || !allow_struct.0 && input.peek(token::Brace)
2371 {
2372 None
2373 } else {
David Tolnay7d2e1db2018-08-30 11:49:04 -07002374 let to = ambiguous_expr(input, allow_struct)?;
David Tolnay60291082018-08-28 09:54:49 -07002375 Some(Box::new(to))
2376 }
2377 },
2378 })
2379 }
David Tolnay438c9052016-10-07 23:24:48 -07002380
Michael Layzell734adb42017-06-07 16:58:31 -04002381 #[cfg(feature = "full")]
David Tolnayc4c631e2018-08-27 10:44:37 -07002382 impl Parse for RangeLimits {
2383 fn parse(input: ParseStream) -> Result<Self> {
2384 let lookahead = input.lookahead1();
2385 if lookahead.peek(Token![..=]) {
2386 input.parse().map(RangeLimits::Closed)
2387 } else if lookahead.peek(Token![...]) {
2388 let dot3: Token![...] = input.parse()?;
2389 Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2390 } else if lookahead.peek(Token![..]) {
2391 input.parse().map(RangeLimits::HalfOpen)
2392 } else {
2393 Err(lookahead.error())
2394 }
2395 }
Alex Crichton954046c2017-05-30 21:49:42 -07002396 }
David Tolnay438c9052016-10-07 23:24:48 -07002397
David Tolnay60291082018-08-28 09:54:49 -07002398 impl Parse for ExprPath {
2399 fn parse(input: ParseStream) -> Result<Self> {
2400 #[cfg(not(feature = "full"))]
2401 let attrs = Vec::new();
2402 #[cfg(feature = "full")]
2403 let attrs = input.call(Attribute::parse_outer)?;
David Tolnayeb981bb2018-07-21 19:31:38 -07002404
David Tolnay60291082018-08-28 09:54:49 -07002405 let (qself, path) = path::parsing::qpath(input, true)?;
2406
2407 Ok(ExprPath {
David Tolnay73c9b522018-07-21 15:58:40 -07002408 attrs: attrs,
David Tolnay60291082018-08-28 09:54:49 -07002409 qself: qself,
2410 path: path,
Michael Layzell92639a52017-06-01 00:07:44 -04002411 })
David Tolnay60291082018-08-28 09:54:49 -07002412 }
Alex Crichton954046c2017-05-30 21:49:42 -07002413 }
David Tolnay42602292016-10-01 22:25:45 -07002414
Michael Layzell734adb42017-06-07 16:58:31 -04002415 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002416 impl Parse for Block {
2417 fn parse(input: ParseStream) -> Result<Self> {
2418 let content;
2419 Ok(Block {
2420 brace_token: braced!(content in input),
2421 stmts: content.call(Block::parse_within)?,
Michael Layzell92639a52017-06-01 00:07:44 -04002422 })
David Tolnay60291082018-08-28 09:54:49 -07002423 }
Alex Crichton954046c2017-05-30 21:49:42 -07002424 }
David Tolnay939766a2016-09-23 23:48:12 -07002425
Michael Layzell734adb42017-06-07 16:58:31 -04002426 #[cfg(feature = "full")]
Alex Crichton954046c2017-05-30 21:49:42 -07002427 impl Block {
David Tolnay6b457252018-09-01 15:55:47 -07002428 /// Parse the body of a block as zero or more statements, possibly
2429 /// including one trailing expression.
2430 ///
David Tolnay206edfb2018-09-01 16:02:20 -07002431 /// *This function is available if Syn is built with the `"parsing"`
2432 /// feature.*
2433 ///
David Tolnay6b457252018-09-01 15:55:47 -07002434 /// # Example
2435 ///
2436 /// ```
2437 /// # extern crate syn;
2438 /// #
2439 /// use syn::{braced, token, Attribute, Block, Ident, Stmt, Token};
2440 /// use syn::parse::{Parse, ParseStream, Result};
2441 ///
2442 /// // Parse a function with no generics or parameter list.
2443 /// struct MiniFunction {
2444 /// attrs: Vec<Attribute>,
2445 /// fn_token: Token![fn],
2446 /// name: Ident,
2447 /// brace_token: token::Brace,
2448 /// stmts: Vec<Stmt>,
2449 /// }
2450 ///
2451 /// impl Parse for MiniFunction {
2452 /// fn parse(input: ParseStream) -> Result<Self> {
2453 /// let outer_attrs = input.call(Attribute::parse_outer)?;
2454 /// let fn_token: Token![fn] = input.parse()?;
2455 /// let name: Ident = input.parse()?;
2456 ///
2457 /// let content;
2458 /// let brace_token = braced!(content in input);
2459 /// let inner_attrs = content.call(Attribute::parse_inner)?;
2460 /// let stmts = content.call(Block::parse_within)?;
2461 ///
2462 /// Ok(MiniFunction {
2463 /// attrs: {
2464 /// let mut attrs = outer_attrs;
2465 /// attrs.extend(inner_attrs);
2466 /// attrs
2467 /// },
2468 /// fn_token: fn_token,
2469 /// name: name,
2470 /// brace_token: brace_token,
2471 /// stmts: stmts,
2472 /// })
2473 /// }
2474 /// }
2475 /// #
2476 /// # fn main() {}
2477 /// ```
David Tolnay9389c382018-08-27 09:13:37 -07002478 pub fn parse_within(input: ParseStream) -> Result<Vec<Stmt>> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002479 let mut stmts = Vec::new();
David Tolnay7158c5f2018-08-30 17:28:34 -07002480 loop {
2481 while input.peek(Token![;]) {
2482 input.parse::<Token![;]>()?;
Michael Layzell92639a52017-06-01 00:07:44 -04002483 }
David Tolnay7158c5f2018-08-30 17:28:34 -07002484 if input.is_empty() {
2485 break;
2486 }
2487 let s = parse_stmt(input, true)?;
2488 let requires_semicolon = if let Stmt::Expr(ref s) = s {
2489 requires_terminator(s)
2490 } else {
2491 false
2492 };
David Tolnaye532d6b2018-08-30 16:55:01 -07002493 stmts.push(s);
David Tolnay7158c5f2018-08-30 17:28:34 -07002494 if input.is_empty() {
2495 break;
2496 } else if requires_semicolon {
2497 return Err(input.error("unexpected token"));
2498 }
David Tolnaye532d6b2018-08-30 16:55:01 -07002499 }
2500 Ok(stmts)
2501 }
Alex Crichton954046c2017-05-30 21:49:42 -07002502 }
2503
Michael Layzell734adb42017-06-07 16:58:31 -04002504 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002505 impl Parse for Stmt {
2506 fn parse(input: ParseStream) -> Result<Self> {
David Tolnaye532d6b2018-08-30 16:55:01 -07002507 parse_stmt(input, false)
2508 }
2509 }
David Tolnay939766a2016-09-23 23:48:12 -07002510
David Tolnaye532d6b2018-08-30 16:55:01 -07002511 #[cfg(feature = "full")]
2512 fn parse_stmt(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
2513 let ahead = input.fork();
2514 ahead.call(Attribute::parse_outer)?;
2515
David Tolnaye532d6b2018-08-30 16:55:01 -07002516 if {
2517 let ahead = ahead.fork();
2518 // Only parse braces here; paren and bracket will get parsed as
2519 // expression statements
2520 ahead.call(Path::parse_mod_style).is_ok()
2521 && ahead.parse::<Token![!]>().is_ok()
2522 && (ahead.peek(token::Brace) || ahead.peek(Ident))
2523 } {
2524 stmt_mac(input)
2525 } else if ahead.peek(Token![let]) {
2526 stmt_local(input).map(Stmt::Local)
2527 } else if ahead.peek(Token![pub])
2528 || ahead.peek(Token![crate]) && !ahead.peek2(Token![::])
2529 || ahead.peek(Token![extern]) && !ahead.peek2(Token![::])
2530 || ahead.peek(Token![use])
2531 || ahead.peek(Token![static]) && (ahead.peek2(Token![mut]) || ahead.peek2(Ident))
2532 || ahead.peek(Token![const])
2533 || ahead.peek(Token![unsafe]) && !ahead.peek2(token::Brace)
2534 || ahead.peek(Token![async]) && (ahead.peek2(Token![extern]) || ahead.peek2(Token![fn]))
2535 || ahead.peek(Token![fn])
2536 || ahead.peek(Token![mod])
2537 || ahead.peek(Token![type])
2538 || ahead.peek(Token![existential]) && ahead.peek2(Token![type])
2539 || ahead.peek(Token![struct])
2540 || ahead.peek(Token![enum])
2541 || ahead.peek(Token![union]) && ahead.peek2(Ident)
2542 || ahead.peek(Token![auto]) && ahead.peek2(Token![trait])
2543 || ahead.peek(Token![trait])
David Tolnay73b7ca12018-08-30 21:05:13 -07002544 || ahead.peek(Token![default])
2545 && (ahead.peek2(Token![unsafe]) || ahead.peek2(Token![impl ]))
2546 || ahead.peek(Token![impl ])
David Tolnaye532d6b2018-08-30 16:55:01 -07002547 || ahead.peek(Token![macro])
2548 {
2549 input.parse().map(Stmt::Item)
2550 } else {
2551 stmt_expr(input, allow_nosemi)
David Tolnay60291082018-08-28 09:54:49 -07002552 }
Alex Crichton954046c2017-05-30 21:49:42 -07002553 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07002554
Michael Layzell734adb42017-06-07 16:58:31 -04002555 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002556 fn stmt_mac(input: ParseStream) -> Result<Stmt> {
2557 let attrs = input.call(Attribute::parse_outer)?;
2558 let path = input.call(Path::parse_mod_style)?;
2559 let bang_token: Token![!] = input.parse()?;
2560 let ident: Option<Ident> = input.parse()?;
2561 let (delimiter, tts) = mac::parse_delimiter(input)?;
2562 let semi_token: Option<Token![;]> = input.parse()?;
2563
2564 Ok(Stmt::Item(Item::Macro(ItemMacro {
2565 attrs: attrs,
2566 ident: ident,
2567 mac: Macro {
2568 path: path,
2569 bang_token: bang_token,
2570 delimiter: delimiter,
2571 tts: tts,
2572 },
2573 semi_token: semi_token,
2574 })))
Alex Crichton954046c2017-05-30 21:49:42 -07002575 }
David Tolnay84aa0752016-10-02 23:01:13 -07002576
Michael Layzell734adb42017-06-07 16:58:31 -04002577 #[cfg(feature = "full")]
David Tolnay60291082018-08-28 09:54:49 -07002578 fn stmt_local(input: ParseStream) -> Result<Local> {
2579 Ok(Local {
2580 attrs: input.call(Attribute::parse_outer)?,
2581 let_token: input.parse()?,
2582 pats: {
2583 let mut pats = Punctuated::new();
2584 let value: Pat = input.parse()?;
2585 pats.push_value(value);
2586 while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
2587 let punct = input.parse()?;
2588 pats.push_punct(punct);
2589 let value: Pat = input.parse()?;
2590 pats.push_value(value);
2591 }
2592 pats
2593 },
2594 ty: {
2595 if input.peek(Token![:]) {
2596 let colon_token: Token![:] = input.parse()?;
2597 let ty: Type = input.parse()?;
2598 Some((colon_token, Box::new(ty)))
2599 } else {
2600 None
2601 }
2602 },
2603 init: {
2604 if input.peek(Token![=]) {
2605 let eq_token: Token![=] = input.parse()?;
2606 let init: Expr = input.parse()?;
2607 Some((eq_token, Box::new(init)))
2608 } else {
2609 None
2610 }
2611 },
2612 semi_token: input.parse()?,
2613 })
2614 }
2615
2616 #[cfg(feature = "full")]
David Tolnaye532d6b2018-08-30 16:55:01 -07002617 fn stmt_expr(input: ParseStream, allow_nosemi: bool) -> Result<Stmt> {
David Tolnay60291082018-08-28 09:54:49 -07002618 let mut attrs = input.call(Attribute::parse_outer)?;
David Tolnay01218d12018-08-29 18:13:07 -07002619 let mut e = expr_early(input)?;
David Tolnay60291082018-08-28 09:54:49 -07002620
2621 attrs.extend(e.replace_attrs(Vec::new()));
2622 e.replace_attrs(attrs);
2623
2624 if input.peek(Token![;]) {
David Tolnay01218d12018-08-29 18:13:07 -07002625 return Ok(Stmt::Semi(e, input.parse()?));
David Tolnay60291082018-08-28 09:54:49 -07002626 }
David Tolnay60291082018-08-28 09:54:49 -07002627
David Tolnayf00a2762018-08-30 17:22:22 -07002628 if allow_nosemi || !requires_terminator(&e) {
David Tolnaye532d6b2018-08-30 16:55:01 -07002629 Ok(Stmt::Expr(e))
2630 } else {
2631 Err(input.error("expected semicolon"))
David Tolnay01218d12018-08-29 18:13:07 -07002632 }
David Tolnay60291082018-08-28 09:54:49 -07002633 }
2634
2635 #[cfg(feature = "full")]
2636 impl Parse for Pat {
2637 fn parse(input: ParseStream) -> Result<Self> {
2638 // TODO: better error messages
2639 let lookahead = input.lookahead1();
2640 if lookahead.peek(Token![_]) {
David Tolnay310b3262018-08-30 15:33:00 -07002641 input.call(pat_wild).map(Pat::Wild)
David Tolnay60291082018-08-28 09:54:49 -07002642 } else if lookahead.peek(Token![box]) {
David Tolnay310b3262018-08-30 15:33:00 -07002643 input.call(pat_box).map(Pat::Box)
2644 } else if input.fork().call(pat_range).is_ok() {
David Tolnay60291082018-08-28 09:54:49 -07002645 // must be before Pat::Lit
David Tolnay310b3262018-08-30 15:33:00 -07002646 input.call(pat_range).map(Pat::Range)
2647 } else if input.fork().call(pat_tuple_struct).is_ok() {
David Tolnay60291082018-08-28 09:54:49 -07002648 // must be before Pat::Ident
David Tolnay310b3262018-08-30 15:33:00 -07002649 input.call(pat_tuple_struct).map(Pat::TupleStruct)
2650 } else if input.fork().call(pat_struct).is_ok() {
David Tolnay60291082018-08-28 09:54:49 -07002651 // must be before Pat::Ident
David Tolnay310b3262018-08-30 15:33:00 -07002652 input.call(pat_struct).map(Pat::Struct)
2653 } else if input.fork().call(pat_macro).is_ok() {
David Tolnay60291082018-08-28 09:54:49 -07002654 // must be before Pat::Ident
David Tolnay310b3262018-08-30 15:33:00 -07002655 input.call(pat_macro).map(Pat::Macro)
2656 } else if input.fork().call(pat_lit).is_ok() {
David Tolnay60291082018-08-28 09:54:49 -07002657 // must be before Pat::Ident
David Tolnay310b3262018-08-30 15:33:00 -07002658 input.call(pat_lit).map(Pat::Lit)
2659 } else if input.fork().call(pat_ident).is_ok() {
2660 input.call(pat_ident).map(Pat::Ident)
2661 } else if input.fork().call(pat_path).is_ok() {
2662 input.call(pat_path).map(Pat::Path)
David Tolnay60291082018-08-28 09:54:49 -07002663 } else if lookahead.peek(token::Paren) {
David Tolnay310b3262018-08-30 15:33:00 -07002664 input.call(pat_tuple).map(Pat::Tuple)
David Tolnay60291082018-08-28 09:54:49 -07002665 } else if lookahead.peek(Token![&]) {
David Tolnay310b3262018-08-30 15:33:00 -07002666 input.call(pat_ref).map(Pat::Ref)
David Tolnay60291082018-08-28 09:54:49 -07002667 } else if lookahead.peek(token::Bracket) {
David Tolnay310b3262018-08-30 15:33:00 -07002668 input.call(pat_slice).map(Pat::Slice)
David Tolnay60291082018-08-28 09:54:49 -07002669 } else {
2670 Err(lookahead.error())
2671 }
2672 }
2673 }
2674
2675 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002676 fn pat_wild(input: ParseStream) -> Result<PatWild> {
2677 Ok(PatWild {
2678 underscore_token: input.parse()?,
2679 })
Alex Crichton954046c2017-05-30 21:49:42 -07002680 }
2681
Michael Layzell734adb42017-06-07 16:58:31 -04002682 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002683 fn pat_box(input: ParseStream) -> Result<PatBox> {
2684 Ok(PatBox {
2685 box_token: input.parse()?,
2686 pat: input.parse()?,
2687 })
David Tolnay60291082018-08-28 09:54:49 -07002688 }
2689
2690 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002691 fn pat_ident(input: ParseStream) -> Result<PatIdent> {
2692 Ok(PatIdent {
2693 by_ref: input.parse()?,
2694 mutability: input.parse()?,
2695 ident: {
2696 let ident = if input.peek(Ident) || input.peek(Token![self]) {
David Tolnay0dea1b92018-08-30 17:47:29 -07002697 input.call(Ident::parse_any)?
David Tolnay310b3262018-08-30 15:33:00 -07002698 } else {
2699 return Err(input.error("expected identifier or `self`"));
2700 };
2701 if input.peek(Token![<]) || input.peek(Token![::]) {
2702 return Err(input.error("unexpected token"));
David Tolnay60291082018-08-28 09:54:49 -07002703 }
David Tolnay310b3262018-08-30 15:33:00 -07002704 ident
2705 },
2706 subpat: {
2707 if input.peek(Token![@]) {
2708 let at_token: Token![@] = input.parse()?;
2709 let subpat: Pat = input.parse()?;
2710 Some((at_token, Box::new(subpat)))
2711 } else {
2712 None
2713 }
2714 },
2715 })
David Tolnay60291082018-08-28 09:54:49 -07002716 }
2717
2718 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002719 fn pat_tuple_struct(input: ParseStream) -> Result<PatTupleStruct> {
2720 Ok(PatTupleStruct {
2721 path: input.parse()?,
2722 pat: input.call(pat_tuple)?,
2723 })
2724 }
David Tolnay60291082018-08-28 09:54:49 -07002725
David Tolnay310b3262018-08-30 15:33:00 -07002726 #[cfg(feature = "full")]
2727 fn pat_struct(input: ParseStream) -> Result<PatStruct> {
2728 let path: Path = input.parse()?;
2729
2730 let content;
2731 let brace_token = braced!(content in input);
2732
2733 let mut fields = Punctuated::new();
2734 while !content.is_empty() && !content.peek(Token![..]) {
2735 let value = content.call(field_pat)?;
2736 fields.push_value(value);
2737 if !content.peek(Token![,]) {
2738 break;
David Tolnay60291082018-08-28 09:54:49 -07002739 }
David Tolnay310b3262018-08-30 15:33:00 -07002740 let punct: Token![,] = content.parse()?;
2741 fields.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002742 }
David Tolnay310b3262018-08-30 15:33:00 -07002743
2744 let dot2_token = if fields.empty_or_trailing() && content.peek(Token![..]) {
2745 Some(content.parse()?)
2746 } else {
2747 None
2748 };
2749
2750 Ok(PatStruct {
2751 path: path,
2752 brace_token: brace_token,
2753 fields: fields,
2754 dot2_token: dot2_token,
2755 })
2756 }
2757
2758 #[cfg(feature = "full")]
2759 fn field_pat(input: ParseStream) -> Result<FieldPat> {
2760 let boxed: Option<Token![box]> = input.parse()?;
2761 let by_ref: Option<Token![ref]> = input.parse()?;
2762 let mutability: Option<Token![mut]> = input.parse()?;
2763 let member: Member = input.parse()?;
2764
2765 if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
2766 || member.is_unnamed()
2767 {
2768 return Ok(FieldPat {
2769 attrs: Vec::new(),
2770 member: member,
2771 colon_token: input.parse()?,
2772 pat: input.parse()?,
2773 });
2774 }
2775
2776 let ident = match member {
2777 Member::Named(ident) => ident,
2778 Member::Unnamed(_) => unreachable!(),
2779 };
2780
2781 let mut pat = Pat::Ident(PatIdent {
2782 by_ref: by_ref,
2783 mutability: mutability,
2784 ident: ident.clone(),
2785 subpat: None,
2786 });
2787
2788 if let Some(boxed) = boxed {
2789 pat = Pat::Box(PatBox {
2790 pat: Box::new(pat),
2791 box_token: boxed,
2792 });
2793 }
2794
2795 Ok(FieldPat {
2796 member: Member::Named(ident),
2797 pat: Box::new(pat),
2798 attrs: Vec::new(),
2799 colon_token: None,
2800 })
Alex Crichton954046c2017-05-30 21:49:42 -07002801 }
2802
David Tolnay1501f7e2018-08-27 14:21:03 -07002803 impl Parse for Member {
2804 fn parse(input: ParseStream) -> Result<Self> {
2805 if input.peek(Ident) {
2806 input.parse().map(Member::Named)
2807 } else if input.peek(LitInt) {
2808 input.parse().map(Member::Unnamed)
2809 } else {
2810 Err(input.error("expected identifier or integer"))
2811 }
2812 }
David Tolnay85b69a42017-12-27 20:43:10 -05002813 }
2814
David Tolnay1501f7e2018-08-27 14:21:03 -07002815 impl Parse for Index {
2816 fn parse(input: ParseStream) -> Result<Self> {
2817 let lit: LitInt = input.parse()?;
2818 if let IntSuffix::None = lit.suffix() {
2819 Ok(Index {
2820 index: lit.value() as u32,
2821 span: lit.span(),
2822 })
2823 } else {
David Tolnayff8c9342018-09-01 13:45:48 -07002824 Err(Error::new(lit.span(), "expected unsuffixed integer"))
David Tolnay1501f7e2018-08-27 14:21:03 -07002825 }
2826 }
David Tolnay85b69a42017-12-27 20:43:10 -05002827 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07002828
Michael Layzell734adb42017-06-07 16:58:31 -04002829 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002830 fn pat_path(input: ParseStream) -> Result<PatPath> {
2831 let p: ExprPath = input.parse()?;
2832 Ok(PatPath {
2833 qself: p.qself,
2834 path: p.path,
2835 })
Alex Crichton954046c2017-05-30 21:49:42 -07002836 }
David Tolnay9636c052016-10-02 17:11:17 -07002837
Michael Layzell734adb42017-06-07 16:58:31 -04002838 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002839 fn pat_tuple(input: ParseStream) -> Result<PatTuple> {
2840 let content;
2841 let paren_token = parenthesized!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002842
David Tolnay310b3262018-08-30 15:33:00 -07002843 let mut front = Punctuated::new();
2844 let mut dot2_token = None::<Token![..]>;
2845 let mut comma_token = None::<Token![,]>;
2846 loop {
2847 if content.is_empty() {
2848 break;
David Tolnay60291082018-08-28 09:54:49 -07002849 }
David Tolnay310b3262018-08-30 15:33:00 -07002850 if content.peek(Token![..]) {
2851 dot2_token = Some(content.parse()?);
2852 comma_token = content.parse()?;
2853 break;
David Tolnay60291082018-08-28 09:54:49 -07002854 }
David Tolnay310b3262018-08-30 15:33:00 -07002855 let value: Pat = content.parse()?;
2856 front.push_value(value);
2857 if content.is_empty() {
2858 break;
2859 }
2860 let punct = content.parse()?;
2861 front.push_punct(punct);
2862 }
2863
David Tolnayf5ebc192018-08-30 18:23:46 -07002864 let mut back = Punctuated::new();
2865 while !content.is_empty() {
2866 let value: Pat = content.parse()?;
2867 back.push_value(value);
2868 if content.is_empty() {
2869 break;
2870 }
2871 let punct = content.parse()?;
2872 back.push_punct(punct);
2873 }
David Tolnay310b3262018-08-30 15:33:00 -07002874
2875 Ok(PatTuple {
2876 paren_token: paren_token,
2877 front: front,
2878 dot2_token: dot2_token,
2879 comma_token: comma_token,
2880 back: back,
2881 })
2882 }
2883
2884 #[cfg(feature = "full")]
2885 fn pat_ref(input: ParseStream) -> Result<PatRef> {
2886 Ok(PatRef {
2887 and_token: input.parse()?,
2888 mutability: input.parse()?,
2889 pat: input.parse()?,
2890 })
2891 }
2892
2893 #[cfg(feature = "full")]
2894 fn pat_lit(input: ParseStream) -> Result<PatLit> {
2895 if input.peek(Lit) || input.peek(Token![-]) && input.peek2(Lit) {
2896 Ok(PatLit {
2897 expr: input.call(pat_lit_expr)?,
2898 })
2899 } else {
2900 Err(input.error("expected literal pattern"))
David Tolnay60291082018-08-28 09:54:49 -07002901 }
2902 }
2903
2904 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002905 fn pat_range(input: ParseStream) -> Result<PatRange> {
2906 Ok(PatRange {
2907 lo: input.call(pat_lit_expr)?,
2908 limits: input.parse()?,
2909 hi: input.call(pat_lit_expr)?,
2910 })
David Tolnay60291082018-08-28 09:54:49 -07002911 }
2912
2913 #[cfg(feature = "full")]
2914 fn pat_lit_expr(input: ParseStream) -> Result<Box<Expr>> {
2915 let neg: Option<Token![-]> = input.parse()?;
2916
2917 let lookahead = input.lookahead1();
2918 let expr = if lookahead.peek(Lit) {
David Tolnay310b3262018-08-30 15:33:00 -07002919 Expr::Lit(input.call(expr_lit)?)
David Tolnay60291082018-08-28 09:54:49 -07002920 } else if lookahead.peek(Ident)
2921 || lookahead.peek(Token![::])
2922 || lookahead.peek(Token![<])
2923 || lookahead.peek(Token![self])
2924 || lookahead.peek(Token![Self])
2925 || lookahead.peek(Token![super])
2926 || lookahead.peek(Token![extern])
2927 || lookahead.peek(Token![crate])
2928 {
2929 Expr::Path(input.parse()?)
2930 } else {
2931 return Err(lookahead.error());
2932 };
2933
2934 Ok(Box::new(if let Some(neg) = neg {
David Tolnay8c91b882017-12-28 23:04:32 -05002935 Expr::Unary(ExprUnary {
2936 attrs: Vec::new(),
David Tolnayc29b9892017-12-27 22:58:14 -05002937 op: UnOp::Neg(neg),
David Tolnay60291082018-08-28 09:54:49 -07002938 expr: Box::new(expr),
David Tolnay3bc597f2017-12-31 02:31:11 -05002939 })
David Tolnay0ad9e9f2016-10-29 22:20:02 -07002940 } else {
David Tolnay60291082018-08-28 09:54:49 -07002941 expr
2942 }))
Alex Crichton954046c2017-05-30 21:49:42 -07002943 }
David Tolnay323279a2017-12-29 11:26:32 -05002944
2945 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07002946 fn pat_slice(input: ParseStream) -> Result<PatSlice> {
2947 let content;
2948 let bracket_token = bracketed!(content in input);
David Tolnay60291082018-08-28 09:54:49 -07002949
David Tolnay310b3262018-08-30 15:33:00 -07002950 let mut front = Punctuated::new();
2951 let mut middle = None;
2952 loop {
2953 if content.is_empty() || content.peek(Token![..]) {
2954 break;
David Tolnay60291082018-08-28 09:54:49 -07002955 }
David Tolnay310b3262018-08-30 15:33:00 -07002956 let value: Pat = content.parse()?;
2957 if content.peek(Token![..]) {
2958 middle = Some(Box::new(value));
2959 break;
David Tolnay60291082018-08-28 09:54:49 -07002960 }
David Tolnay310b3262018-08-30 15:33:00 -07002961 front.push_value(value);
2962 if content.is_empty() {
2963 break;
2964 }
2965 let punct = content.parse()?;
2966 front.push_punct(punct);
David Tolnay60291082018-08-28 09:54:49 -07002967 }
David Tolnay310b3262018-08-30 15:33:00 -07002968
2969 let dot2_token: Option<Token![..]> = content.parse()?;
2970 let mut comma_token = None::<Token![,]>;
2971 let mut back = Punctuated::new();
2972 if dot2_token.is_some() {
2973 comma_token = content.parse()?;
2974 if comma_token.is_some() {
2975 loop {
2976 if content.is_empty() {
2977 break;
2978 }
2979 let value: Pat = content.parse()?;
2980 back.push_value(value);
2981 if content.is_empty() {
2982 break;
2983 }
2984 let punct = content.parse()?;
2985 back.push_punct(punct);
2986 }
2987 }
2988 }
2989
2990 Ok(PatSlice {
2991 bracket_token: bracket_token,
2992 front: front,
2993 middle: middle,
2994 dot2_token: dot2_token,
2995 comma_token: comma_token,
2996 back: back,
2997 })
David Tolnay60291082018-08-28 09:54:49 -07002998 }
2999
3000 #[cfg(feature = "full")]
David Tolnay310b3262018-08-30 15:33:00 -07003001 fn pat_macro(input: ParseStream) -> Result<PatMacro> {
3002 Ok(PatMacro {
3003 mac: input.parse()?,
3004 })
David Tolnay323279a2017-12-29 11:26:32 -05003005 }
David Tolnay1501f7e2018-08-27 14:21:03 -07003006
3007 #[cfg(feature = "full")]
3008 impl Member {
3009 fn is_named(&self) -> bool {
3010 match *self {
3011 Member::Named(_) => true,
3012 Member::Unnamed(_) => false,
3013 }
3014 }
David Tolnay60291082018-08-28 09:54:49 -07003015
3016 fn is_unnamed(&self) -> bool {
3017 match *self {
3018 Member::Named(_) => false,
3019 Member::Unnamed(_) => true,
3020 }
3021 }
David Tolnay1501f7e2018-08-27 14:21:03 -07003022 }
David Tolnayb9c8e322016-09-23 20:48:37 -07003023}
3024
David Tolnayf4bbbd92016-09-23 14:41:55 -07003025#[cfg(feature = "printing")]
3026mod printing {
3027 use super::*;
David Tolnay64023912018-08-31 09:51:12 -07003028
Alex Crichtona74a1c82018-05-16 10:20:44 -07003029 use proc_macro2::{Literal, TokenStream};
3030 use quote::{ToTokens, TokenStreamExt};
David Tolnayf4bbbd92016-09-23 14:41:55 -07003031
David Tolnay64023912018-08-31 09:51:12 -07003032 #[cfg(feature = "full")]
3033 use attr::FilterAttrs;
3034 #[cfg(feature = "full")]
3035 use print::TokensOrDefault;
3036
David Tolnaybcf26022017-12-25 22:10:52 -05003037 // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
David Tolnayb6a0e7d2018-05-20 22:06:47 -07003038 // before appending it to `TokenStream`.
Michael Layzell3936ceb2017-07-08 00:28:36 -04003039 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003040 fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) {
David Tolnay8c91b882017-12-28 23:04:32 -05003041 if let Expr::Struct(_) = *e {
David Tolnay32954ef2017-12-26 22:43:16 -05003042 token::Paren::default().surround(tokens, |tokens| {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003043 e.to_tokens(tokens);
3044 });
3045 } else {
3046 e.to_tokens(tokens);
3047 }
3048 }
3049
David Tolnay8c91b882017-12-28 23:04:32 -05003050 #[cfg(feature = "full")]
David Tolnayd997aef2018-07-21 18:42:31 -07003051 fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
David Tolnay8c91b882017-12-28 23:04:32 -05003052 tokens.append_all(attrs.outer());
3053 }
Michael Layzell734adb42017-06-07 16:58:31 -04003054
David Tolnayd997aef2018-07-21 18:42:31 -07003055 #[cfg(feature = "full")]
3056 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3057 tokens.append_all(attrs.inner());
3058 }
3059
David Tolnay8c91b882017-12-28 23:04:32 -05003060 #[cfg(not(feature = "full"))]
David Tolnayd997aef2018-07-21 18:42:31 -07003061 fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3062
3063 #[cfg(not(feature = "full"))]
3064 fn inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
Alex Crichton62a0a592017-05-22 13:58:53 -07003065
Michael Layzell734adb42017-06-07 16:58:31 -04003066 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003067 impl ToTokens for ExprBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003068 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003069 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003070 self.box_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003071 self.expr.to_tokens(tokens);
3072 }
3073 }
3074
Michael Layzell734adb42017-06-07 16:58:31 -04003075 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003076 impl ToTokens for ExprInPlace {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003077 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003078 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8701a5c2017-12-28 23:31:10 -05003079 self.place.to_tokens(tokens);
3080 self.arrow_token.to_tokens(tokens);
3081 self.value.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003082 }
3083 }
3084
Michael Layzell734adb42017-06-07 16:58:31 -04003085 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003086 impl ToTokens for ExprArray {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003087 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003088 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003089 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003090 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003091 self.elems.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003092 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003093 }
3094 }
3095
3096 impl ToTokens for ExprCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003097 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003098 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003099 self.func.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003100 self.paren_token.surround(tokens, |tokens| {
3101 self.args.to_tokens(tokens);
3102 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003103 }
3104 }
3105
Michael Layzell734adb42017-06-07 16:58:31 -04003106 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003107 impl ToTokens for ExprMethodCall {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003108 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003109 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay76418512017-12-28 23:47:47 -05003110 self.receiver.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003111 self.dot_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003112 self.method.to_tokens(tokens);
David Tolnayd60cfec2017-12-29 00:21:38 -05003113 self.turbofish.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003114 self.paren_token.surround(tokens, |tokens| {
3115 self.args.to_tokens(tokens);
3116 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003117 }
3118 }
3119
Michael Layzell734adb42017-06-07 16:58:31 -04003120 #[cfg(feature = "full")]
David Tolnayd60cfec2017-12-29 00:21:38 -05003121 impl ToTokens for MethodTurbofish {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003122 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003123 self.colon2_token.to_tokens(tokens);
3124 self.lt_token.to_tokens(tokens);
3125 self.args.to_tokens(tokens);
3126 self.gt_token.to_tokens(tokens);
3127 }
3128 }
3129
3130 #[cfg(feature = "full")]
3131 impl ToTokens for GenericMethodArgument {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003132 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd60cfec2017-12-29 00:21:38 -05003133 match *self {
3134 GenericMethodArgument::Type(ref t) => t.to_tokens(tokens),
3135 GenericMethodArgument::Const(ref c) => c.to_tokens(tokens),
3136 }
3137 }
3138 }
3139
3140 #[cfg(feature = "full")]
David Tolnay05362582017-12-26 01:33:57 -05003141 impl ToTokens for ExprTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003142 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003143 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003144 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003145 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay2a86fdd2017-12-28 23:34:28 -05003146 self.elems.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003147 // If we only have one argument, we need a trailing comma to
David Tolnay05362582017-12-26 01:33:57 -05003148 // distinguish ExprTuple from ExprParen.
David Tolnaya0834b42018-01-01 21:30:02 -08003149 if self.elems.len() == 1 && !self.elems.trailing_punct() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003150 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003151 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003152 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003153 }
3154 }
3155
3156 impl ToTokens for ExprBinary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003157 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003158 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003159 self.left.to_tokens(tokens);
3160 self.op.to_tokens(tokens);
3161 self.right.to_tokens(tokens);
3162 }
3163 }
3164
3165 impl ToTokens for ExprUnary {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003166 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003167 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003168 self.op.to_tokens(tokens);
3169 self.expr.to_tokens(tokens);
3170 }
3171 }
3172
David Tolnay8c91b882017-12-28 23:04:32 -05003173 impl ToTokens for ExprLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003174 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003175 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003176 self.lit.to_tokens(tokens);
3177 }
3178 }
3179
Alex Crichton62a0a592017-05-22 13:58:53 -07003180 impl ToTokens for ExprCast {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003181 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003182 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003183 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003184 self.as_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003185 self.ty.to_tokens(tokens);
3186 }
3187 }
3188
David Tolnay0cf94f22017-12-28 23:46:26 -05003189 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003190 impl ToTokens for ExprType {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003191 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003192 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003193 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003194 self.colon_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003195 self.ty.to_tokens(tokens);
3196 }
3197 }
3198
Michael Layzell734adb42017-06-07 16:58:31 -04003199 #[cfg(feature = "full")]
Alex Crichtona74a1c82018-05-16 10:20:44 -07003200 fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>) {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003201 if let Some((ref else_token, ref else_)) = *else_ {
3202 else_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003203
3204 // If we are not one of the valid expressions to exist in an else
3205 // clause, wrap ourselves in a block.
David Tolnay2ccf32a2017-12-29 00:34:26 -05003206 match **else_ {
David Tolnay8c91b882017-12-28 23:04:32 -05003207 Expr::If(_) | Expr::IfLet(_) | Expr::Block(_) => {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003208 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003209 }
3210 _ => {
David Tolnay32954ef2017-12-26 22:43:16 -05003211 token::Brace::default().surround(tokens, |tokens| {
David Tolnay2ccf32a2017-12-29 00:34:26 -05003212 else_.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003213 });
3214 }
3215 }
3216 }
3217 }
3218
3219 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003220 impl ToTokens for ExprIf {
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);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003223 self.if_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003224 wrap_bare_struct(tokens, &self.cond);
David Tolnay2ccf32a2017-12-29 00:34:26 -05003225 self.then_branch.to_tokens(tokens);
3226 maybe_wrap_else(tokens, &self.else_branch);
Alex Crichton62a0a592017-05-22 13:58:53 -07003227 }
3228 }
3229
Michael Layzell734adb42017-06-07 16:58:31 -04003230 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003231 impl ToTokens for ExprIfLet {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003232 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003233 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003234 self.if_token.to_tokens(tokens);
3235 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003236 self.pats.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003237 self.eq_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003238 wrap_bare_struct(tokens, &self.expr);
David Tolnay2ccf32a2017-12-29 00:34:26 -05003239 self.then_branch.to_tokens(tokens);
3240 maybe_wrap_else(tokens, &self.else_branch);
Alex Crichton62a0a592017-05-22 13:58:53 -07003241 }
3242 }
3243
Michael Layzell734adb42017-06-07 16:58:31 -04003244 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003245 impl ToTokens for ExprWhile {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003246 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003247 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003248 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003249 self.while_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003250 wrap_bare_struct(tokens, &self.cond);
David Tolnay5d314dc2018-07-21 16:40:01 -07003251 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003252 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003253 tokens.append_all(&self.body.stmts);
3254 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003255 }
3256 }
3257
Michael Layzell734adb42017-06-07 16:58:31 -04003258 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003259 impl ToTokens for ExprWhileLet {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003260 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003261 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003262 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003263 self.while_token.to_tokens(tokens);
3264 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003265 self.pats.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003266 self.eq_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003267 wrap_bare_struct(tokens, &self.expr);
David Tolnay5d314dc2018-07-21 16:40:01 -07003268 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003269 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003270 tokens.append_all(&self.body.stmts);
3271 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003272 }
3273 }
3274
Michael Layzell734adb42017-06-07 16:58:31 -04003275 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003276 impl ToTokens for ExprForLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003277 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003278 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003279 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003280 self.for_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003281 self.pat.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003282 self.in_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003283 wrap_bare_struct(tokens, &self.expr);
David Tolnay5d314dc2018-07-21 16:40:01 -07003284 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003285 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003286 tokens.append_all(&self.body.stmts);
3287 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003288 }
3289 }
3290
Michael Layzell734adb42017-06-07 16:58:31 -04003291 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003292 impl ToTokens for ExprLoop {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003293 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003294 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnaybcd498f2017-12-29 12:02:33 -05003295 self.label.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003296 self.loop_token.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003297 self.body.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003298 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003299 tokens.append_all(&self.body.stmts);
3300 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003301 }
3302 }
3303
Michael Layzell734adb42017-06-07 16:58:31 -04003304 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003305 impl ToTokens for ExprMatch {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003306 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003307 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003308 self.match_token.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003309 wrap_bare_struct(tokens, &self.expr);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003310 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003311 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay51382052017-12-27 13:46:21 -05003312 for (i, arm) in self.arms.iter().enumerate() {
Michael Layzell3936ceb2017-07-08 00:28:36 -04003313 arm.to_tokens(tokens);
3314 // Ensure that we have a comma after a non-block arm, except
3315 // for the last one.
3316 let is_last = i == self.arms.len() - 1;
David Tolnaye532d6b2018-08-30 16:55:01 -07003317 if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003318 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003319 }
3320 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003321 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003322 }
3323 }
3324
Michael Layzell734adb42017-06-07 16:58:31 -04003325 #[cfg(feature = "full")]
David Tolnay02a9c6f2018-08-24 18:58:45 -04003326 impl ToTokens for ExprAsync {
3327 fn to_tokens(&self, tokens: &mut TokenStream) {
3328 outer_attrs_to_tokens(&self.attrs, tokens);
3329 self.async_token.to_tokens(tokens);
3330 self.capture.to_tokens(tokens);
3331 self.block.to_tokens(tokens);
3332 }
3333 }
3334
3335 #[cfg(feature = "full")]
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003336 impl ToTokens for ExprTryBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003337 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003338 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnayfb2dd4b2018-08-24 16:45:34 -04003339 self.try_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003340 self.block.to_tokens(tokens);
3341 }
3342 }
3343
Michael Layzell734adb42017-06-07 16:58:31 -04003344 #[cfg(feature = "full")]
Alex Crichtonfe110462017-06-01 12:49:27 -07003345 impl ToTokens for ExprYield {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003346 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003347 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonfe110462017-06-01 12:49:27 -07003348 self.yield_token.to_tokens(tokens);
3349 self.expr.to_tokens(tokens);
3350 }
3351 }
3352
3353 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003354 impl ToTokens for ExprClosure {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003355 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003356 outer_attrs_to_tokens(&self.attrs, tokens);
Yusuke Sasaki4e5d9662018-07-21 02:49:47 +09003357 self.asyncness.to_tokens(tokens);
David Tolnay13d4c0e2018-03-31 20:53:59 +02003358 self.movability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003359 self.capture.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003360 self.or1_token.to_tokens(tokens);
David Tolnay56080682018-01-06 14:01:52 -08003361 for input in self.inputs.pairs() {
3362 match **input.value() {
David Tolnay51382052017-12-27 13:46:21 -05003363 FnArg::Captured(ArgCaptured {
3364 ref pat,
3365 ty: Type::Infer(_),
3366 ..
3367 }) => {
Alex Crichton62a0a592017-05-22 13:58:53 -07003368 pat.to_tokens(tokens);
David Tolnay9636c052016-10-02 17:11:17 -07003369 }
David Tolnay56080682018-01-06 14:01:52 -08003370 _ => input.value().to_tokens(tokens),
David Tolnay3c2467c2016-10-02 17:55:08 -07003371 }
David Tolnayf2cfd722017-12-31 18:02:51 -05003372 input.punct().to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003373 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003374 self.or2_token.to_tokens(tokens);
David Tolnay7f675742017-12-27 22:43:21 -05003375 self.output.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003376 self.body.to_tokens(tokens);
3377 }
3378 }
3379
Michael Layzell734adb42017-06-07 16:58:31 -04003380 #[cfg(feature = "full")]
Nika Layzell640832a2017-12-04 13:37:09 -05003381 impl ToTokens for ExprUnsafe {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003382 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003383 outer_attrs_to_tokens(&self.attrs, tokens);
Nika Layzell640832a2017-12-04 13:37:09 -05003384 self.unsafe_token.to_tokens(tokens);
David Tolnayc4be3512018-08-27 06:25:44 -07003385 self.block.brace_token.surround(tokens, |tokens| {
3386 inner_attrs_to_tokens(&self.attrs, tokens);
3387 tokens.append_all(&self.block.stmts);
3388 });
Nika Layzell640832a2017-12-04 13:37:09 -05003389 }
3390 }
3391
3392 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003393 impl ToTokens for ExprBlock {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003394 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003395 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay1d8e9962018-08-24 19:04:20 -04003396 self.label.to_tokens(tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003397 self.block.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003398 inner_attrs_to_tokens(&self.attrs, tokens);
David Tolnay5d314dc2018-07-21 16:40:01 -07003399 tokens.append_all(&self.block.stmts);
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 ExprAssign {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003406 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003407 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003408 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003409 self.eq_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003410 self.right.to_tokens(tokens);
3411 }
3412 }
3413
Michael Layzell734adb42017-06-07 16:58:31 -04003414 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003415 impl ToTokens for ExprAssignOp {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003416 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003417 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003418 self.left.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003419 self.op.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003420 self.right.to_tokens(tokens);
3421 }
3422 }
3423
3424 impl ToTokens for ExprField {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003425 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003426 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003427 self.base.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003428 self.dot_token.to_tokens(tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003429 self.member.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003430 }
3431 }
3432
David Tolnay85b69a42017-12-27 20:43:10 -05003433 impl ToTokens for Member {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003434 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay85b69a42017-12-27 20:43:10 -05003435 match *self {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003436 Member::Named(ref ident) => ident.to_tokens(tokens),
David Tolnay85b69a42017-12-27 20:43:10 -05003437 Member::Unnamed(ref index) => index.to_tokens(tokens),
3438 }
3439 }
3440 }
3441
David Tolnay85b69a42017-12-27 20:43:10 -05003442 impl ToTokens for Index {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003443 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichton9a4dca22018-03-28 06:32:19 -07003444 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
3445 lit.set_span(self.span);
3446 tokens.append(lit);
Alex Crichton62a0a592017-05-22 13:58:53 -07003447 }
3448 }
3449
3450 impl ToTokens for ExprIndex {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003451 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003452 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003453 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003454 self.bracket_token.surround(tokens, |tokens| {
3455 self.index.to_tokens(tokens);
3456 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003457 }
3458 }
3459
Michael Layzell734adb42017-06-07 16:58:31 -04003460 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003461 impl ToTokens for ExprRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003462 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003463 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003464 self.from.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003465 match self.limits {
3466 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
3467 RangeLimits::Closed(ref t) => t.to_tokens(tokens),
3468 }
Alex Crichton62a0a592017-05-22 13:58:53 -07003469 self.to.to_tokens(tokens);
3470 }
3471 }
3472
3473 impl ToTokens for ExprPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003474 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003475 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003476 ::PathTokens(&self.qself, &self.path).to_tokens(tokens)
Alex Crichton62a0a592017-05-22 13:58:53 -07003477 }
3478 }
3479
Michael Layzell734adb42017-06-07 16:58:31 -04003480 #[cfg(feature = "full")]
David Tolnay00674ba2018-03-31 18:14:11 +02003481 impl ToTokens for ExprReference {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003482 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003483 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003484 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003485 self.mutability.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003486 self.expr.to_tokens(tokens);
3487 }
3488 }
3489
Michael Layzell734adb42017-06-07 16:58:31 -04003490 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003491 impl ToTokens for ExprBreak {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003492 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003493 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003494 self.break_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003495 self.label.to_tokens(tokens);
3496 self.expr.to_tokens(tokens);
3497 }
3498 }
3499
Michael Layzell734adb42017-06-07 16:58:31 -04003500 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003501 impl ToTokens for ExprContinue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003502 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003503 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003504 self.continue_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003505 self.label.to_tokens(tokens);
3506 }
3507 }
3508
Michael Layzell734adb42017-06-07 16:58:31 -04003509 #[cfg(feature = "full")]
David Tolnayc246cd32017-12-28 23:14:32 -05003510 impl ToTokens for ExprReturn {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003511 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003512 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003513 self.return_token.to_tokens(tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003514 self.expr.to_tokens(tokens);
3515 }
3516 }
3517
Michael Layzell734adb42017-06-07 16:58:31 -04003518 #[cfg(feature = "full")]
David Tolnay8c91b882017-12-28 23:04:32 -05003519 impl ToTokens for ExprMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003520 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003521 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay8c91b882017-12-28 23:04:32 -05003522 self.mac.to_tokens(tokens);
3523 }
3524 }
3525
3526 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003527 impl ToTokens for ExprStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003528 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003529 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003530 self.path.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003531 self.brace_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003532 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003533 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003534 if self.rest.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -07003535 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003536 self.rest.to_tokens(tokens);
3537 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003538 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003539 }
3540 }
3541
Michael Layzell734adb42017-06-07 16:58:31 -04003542 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003543 impl ToTokens for ExprRepeat {
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);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003546 self.bracket_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003547 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003548 self.expr.to_tokens(tokens);
3549 self.semi_token.to_tokens(tokens);
David Tolnay84d80442018-01-07 01:03:20 -08003550 self.len.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003551 })
Alex Crichton62a0a592017-05-22 13:58:53 -07003552 }
3553 }
3554
David Tolnaye98775f2017-12-28 23:17:00 -05003555 #[cfg(feature = "full")]
Michael Layzell93c36282017-06-04 20:43:14 -04003556 impl ToTokens for ExprGroup {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003557 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003558 outer_attrs_to_tokens(&self.attrs, tokens);
Michael Layzell93c36282017-06-04 20:43:14 -04003559 self.group_token.surround(tokens, |tokens| {
3560 self.expr.to_tokens(tokens);
3561 });
3562 }
3563 }
3564
Alex Crichton62a0a592017-05-22 13:58:53 -07003565 impl ToTokens for ExprParen {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003566 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003567 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003568 self.paren_token.surround(tokens, |tokens| {
David Tolnayd997aef2018-07-21 18:42:31 -07003569 inner_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003570 self.expr.to_tokens(tokens);
3571 });
Alex Crichton62a0a592017-05-22 13:58:53 -07003572 }
3573 }
3574
Michael Layzell734adb42017-06-07 16:58:31 -04003575 #[cfg(feature = "full")]
Alex Crichton62a0a592017-05-22 13:58:53 -07003576 impl ToTokens for ExprTry {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003577 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003578 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichton62a0a592017-05-22 13:58:53 -07003579 self.expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003580 self.question_token.to_tokens(tokens);
David Tolnayf4bbbd92016-09-23 14:41:55 -07003581 }
3582 }
David Tolnayb4ad3b52016-10-01 21:58:13 -07003583
David Tolnay2ae520a2017-12-29 11:19:50 -05003584 impl ToTokens for ExprVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003585 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003586 self.tts.to_tokens(tokens);
3587 }
3588 }
3589
Michael Layzell734adb42017-06-07 16:58:31 -04003590 #[cfg(feature = "full")]
David Tolnaybcd498f2017-12-29 12:02:33 -05003591 impl ToTokens for Label {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003592 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnaybcd498f2017-12-29 12:02:33 -05003593 self.name.to_tokens(tokens);
3594 self.colon_token.to_tokens(tokens);
3595 }
3596 }
3597
3598 #[cfg(feature = "full")]
David Tolnay055a7042016-10-02 19:23:54 -07003599 impl ToTokens for FieldValue {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003600 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003601 outer_attrs_to_tokens(&self.attrs, tokens);
David Tolnay85b69a42017-12-27 20:43:10 -05003602 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003603 if let Some(ref colon_token) = self.colon_token {
3604 colon_token.to_tokens(tokens);
David Tolnay276690f2016-10-30 12:06:59 -07003605 self.expr.to_tokens(tokens);
3606 }
David Tolnay055a7042016-10-02 19:23:54 -07003607 }
3608 }
3609
Michael Layzell734adb42017-06-07 16:58:31 -04003610 #[cfg(feature = "full")]
David Tolnayb4ad3b52016-10-01 21:58:13 -07003611 impl ToTokens for Arm {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003612 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003613 tokens.append_all(&self.attrs);
David Tolnay18cc4d42018-03-31 18:47:20 +02003614 self.leading_vert.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003615 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003616 if let Some((ref if_token, ref guard)) = self.guard {
3617 if_token.to_tokens(tokens);
3618 guard.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003619 }
David Tolnaydfb91432018-03-31 19:19:44 +02003620 self.fat_arrow_token.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003621 self.body.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003622 self.comma.to_tokens(tokens);
David Tolnayb4ad3b52016-10-01 21:58:13 -07003623 }
3624 }
3625
Michael Layzell734adb42017-06-07 16:58:31 -04003626 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003627 impl ToTokens for PatWild {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003628 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003629 self.underscore_token.to_tokens(tokens);
3630 }
3631 }
3632
Michael Layzell734adb42017-06-07 16:58:31 -04003633 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003634 impl ToTokens for PatIdent {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003635 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay24237fb2017-12-29 02:15:26 -05003636 self.by_ref.to_tokens(tokens);
David Tolnayefc96fb2017-12-29 02:03:15 -05003637 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003638 self.ident.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003639 if let Some((ref at_token, ref subpat)) = self.subpat {
3640 at_token.to_tokens(tokens);
3641 subpat.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003642 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003643 }
3644 }
3645
Michael Layzell734adb42017-06-07 16:58:31 -04003646 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003647 impl ToTokens for PatStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003648 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003649 self.path.to_tokens(tokens);
3650 self.brace_token.surround(tokens, |tokens| {
3651 self.fields.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003652 // NOTE: We need a comma before the dot2 token if it is present.
3653 if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003654 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003655 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003656 self.dot2_token.to_tokens(tokens);
3657 });
3658 }
3659 }
3660
Michael Layzell734adb42017-06-07 16:58:31 -04003661 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003662 impl ToTokens for PatTupleStruct {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003663 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003664 self.path.to_tokens(tokens);
3665 self.pat.to_tokens(tokens);
3666 }
3667 }
3668
Michael Layzell734adb42017-06-07 16:58:31 -04003669 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003670 impl ToTokens for PatPath {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003671 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003672 ::PathTokens(&self.qself, &self.path).to_tokens(tokens);
3673 }
3674 }
3675
Michael Layzell734adb42017-06-07 16:58:31 -04003676 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003677 impl ToTokens for PatTuple {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003678 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003679 self.paren_token.surround(tokens, |tokens| {
David Tolnay41871922017-12-29 01:53:45 -05003680 self.front.to_tokens(tokens);
3681 if let Some(ref dot2_token) = self.dot2_token {
3682 if !self.front.empty_or_trailing() {
3683 // Ensure there is a comma before the .. token.
David Tolnayf8db7ba2017-11-11 22:52:16 -08003684 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003685 }
David Tolnay41871922017-12-29 01:53:45 -05003686 dot2_token.to_tokens(tokens);
3687 self.comma_token.to_tokens(tokens);
3688 if self.comma_token.is_none() && !self.back.is_empty() {
3689 // Ensure there is a comma after the .. token.
3690 <Token![,]>::default().to_tokens(tokens);
3691 }
David Tolnay8d9e81a2016-10-03 22:36:32 -07003692 }
David Tolnay41871922017-12-29 01:53:45 -05003693 self.back.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003694 });
3695 }
3696 }
3697
Michael Layzell734adb42017-06-07 16:58:31 -04003698 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003699 impl ToTokens for PatBox {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003700 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003701 self.box_token.to_tokens(tokens);
3702 self.pat.to_tokens(tokens);
3703 }
3704 }
3705
Michael Layzell734adb42017-06-07 16:58:31 -04003706 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003707 impl ToTokens for PatRef {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003708 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003709 self.and_token.to_tokens(tokens);
David Tolnay24237fb2017-12-29 02:15:26 -05003710 self.mutability.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003711 self.pat.to_tokens(tokens);
3712 }
3713 }
3714
Michael Layzell734adb42017-06-07 16:58:31 -04003715 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003716 impl ToTokens for PatLit {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003717 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003718 self.expr.to_tokens(tokens);
3719 }
3720 }
3721
Michael Layzell734adb42017-06-07 16:58:31 -04003722 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003723 impl ToTokens for PatRange {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003724 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003725 self.lo.to_tokens(tokens);
David Tolnay475288a2017-12-19 22:59:44 -08003726 match self.limits {
3727 RangeLimits::HalfOpen(ref t) => t.to_tokens(tokens),
David Tolnay7ac699c2018-08-24 14:00:58 -04003728 RangeLimits::Closed(ref t) => Token![...](t.spans).to_tokens(tokens),
David Tolnay475288a2017-12-19 22:59:44 -08003729 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003730 self.hi.to_tokens(tokens);
3731 }
3732 }
3733
Michael Layzell734adb42017-06-07 16:58:31 -04003734 #[cfg(feature = "full")]
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003735 impl ToTokens for PatSlice {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003736 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003737 self.bracket_token.surround(tokens, |tokens| {
3738 self.front.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003739
3740 // If we need a comma before the middle or standalone .. token,
3741 // then make sure it's present.
David Tolnay51382052017-12-27 13:46:21 -05003742 if !self.front.empty_or_trailing()
3743 && (self.middle.is_some() || self.dot2_token.is_some())
Michael Layzell3936ceb2017-07-08 00:28:36 -04003744 {
David Tolnayf8db7ba2017-11-11 22:52:16 -08003745 <Token![,]>::default().to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003746 }
3747
3748 // If we have an identifier, we always need a .. token.
3749 if self.middle.is_some() {
3750 self.middle.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -07003751 TokensOrDefault(&self.dot2_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003752 } else if self.dot2_token.is_some() {
3753 self.dot2_token.to_tokens(tokens);
3754 }
3755
3756 // Make sure we have a comma before the back half.
3757 if !self.back.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -07003758 TokensOrDefault(&self.comma_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003759 self.back.to_tokens(tokens);
3760 } else {
3761 self.comma_token.to_tokens(tokens);
3762 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003763 })
David Tolnayb4ad3b52016-10-01 21:58:13 -07003764 }
3765 }
3766
Michael Layzell734adb42017-06-07 16:58:31 -04003767 #[cfg(feature = "full")]
David Tolnay323279a2017-12-29 11:26:32 -05003768 impl ToTokens for PatMacro {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003769 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay323279a2017-12-29 11:26:32 -05003770 self.mac.to_tokens(tokens);
3771 }
3772 }
3773
3774 #[cfg(feature = "full")]
David Tolnay2ae520a2017-12-29 11:19:50 -05003775 impl ToTokens for PatVerbatim {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003776 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay2ae520a2017-12-29 11:19:50 -05003777 self.tts.to_tokens(tokens);
3778 }
3779 }
3780
3781 #[cfg(feature = "full")]
David Tolnay8d9e81a2016-10-03 22:36:32 -07003782 impl ToTokens for FieldPat {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003783 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay5d7098a2017-12-29 01:35:24 -05003784 if let Some(ref colon_token) = self.colon_token {
David Tolnay85b69a42017-12-27 20:43:10 -05003785 self.member.to_tokens(tokens);
David Tolnay5d7098a2017-12-29 01:35:24 -05003786 colon_token.to_tokens(tokens);
David Tolnay8d9e81a2016-10-03 22:36:32 -07003787 }
3788 self.pat.to_tokens(tokens);
3789 }
3790 }
3791
Michael Layzell734adb42017-06-07 16:58:31 -04003792 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003793 impl ToTokens for Block {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003794 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003795 self.brace_token.surround(tokens, |tokens| {
3796 tokens.append_all(&self.stmts);
3797 });
David Tolnay42602292016-10-01 22:25:45 -07003798 }
3799 }
3800
Michael Layzell734adb42017-06-07 16:58:31 -04003801 #[cfg(feature = "full")]
David Tolnay42602292016-10-01 22:25:45 -07003802 impl ToTokens for Stmt {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003803 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay42602292016-10-01 22:25:45 -07003804 match *self {
David Tolnay191e0582016-10-02 18:31:09 -07003805 Stmt::Local(ref local) => local.to_tokens(tokens),
David Tolnay42602292016-10-01 22:25:45 -07003806 Stmt::Item(ref item) => item.to_tokens(tokens),
3807 Stmt::Expr(ref expr) => expr.to_tokens(tokens),
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003808 Stmt::Semi(ref expr, ref semi) => {
David Tolnay42602292016-10-01 22:25:45 -07003809 expr.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003810 semi.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -07003811 }
David Tolnay42602292016-10-01 22:25:45 -07003812 }
3813 }
3814 }
David Tolnay191e0582016-10-02 18:31:09 -07003815
Michael Layzell734adb42017-06-07 16:58:31 -04003816 #[cfg(feature = "full")]
David Tolnay191e0582016-10-02 18:31:09 -07003817 impl ToTokens for Local {
Alex Crichtona74a1c82018-05-16 10:20:44 -07003818 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnayd997aef2018-07-21 18:42:31 -07003819 outer_attrs_to_tokens(&self.attrs, tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003820 self.let_token.to_tokens(tokens);
David Tolnay5b5b7d22018-03-31 21:05:00 +02003821 self.pats.to_tokens(tokens);
David Tolnay8b4d3022017-12-29 12:11:10 -05003822 if let Some((ref colon_token, ref ty)) = self.ty {
3823 colon_token.to_tokens(tokens);
3824 ty.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003825 }
David Tolnay8b4d3022017-12-29 12:11:10 -05003826 if let Some((ref eq_token, ref init)) = self.init {
3827 eq_token.to_tokens(tokens);
3828 init.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -04003829 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -07003830 self.semi_token.to_tokens(tokens);
David Tolnay191e0582016-10-02 18:31:09 -07003831 }
3832 }
David Tolnayf4bbbd92016-09-23 14:41:55 -07003833}