]> git.proxmox.com Git - rustc.git/blame - vendor/syn/src/expr.rs
New upstream version 1.52.0~beta.3+dfsg1
[rustc.git] / vendor / syn / src / expr.rs
CommitLineData
e74abb32
XL
1use super::*;
2use crate::punctuated::Punctuated;
1b1a35ee
XL
3#[cfg(feature = "full")]
4use crate::reserved::Reserved;
e74abb32 5use proc_macro2::{Span, TokenStream};
60c5eb7d
XL
6#[cfg(feature = "printing")]
7use quote::IdentFragment;
8#[cfg(feature = "printing")]
9use std::fmt::{self, Display};
e74abb32 10use std::hash::{Hash, Hasher};
3dfed10e 11#[cfg(feature = "parsing")]
e74abb32
XL
12use std::mem;
13
14ast_enum_of_structs! {
15 /// A Rust expression.
16 ///
f035d41b
XL
17 /// *This type is available only if Syn is built with the `"derive"` or `"full"`
18 /// feature, but most of the variants are not available unless "full" is enabled.*
e74abb32
XL
19 ///
20 /// # Syntax tree enums
21 ///
22 /// This type is a syntax tree enum. In Syn this and other syntax tree enums
23 /// are designed to be traversed using the following rebinding idiom.
24 ///
25 /// ```
26 /// # use syn::Expr;
27 /// #
28 /// # fn example(expr: Expr) {
29 /// # const IGNORE: &str = stringify! {
30 /// let expr: Expr = /* ... */;
31 /// # };
32 /// match expr {
33 /// Expr::MethodCall(expr) => {
34 /// /* ... */
35 /// }
36 /// Expr::Cast(expr) => {
37 /// /* ... */
38 /// }
39 /// Expr::If(expr) => {
40 /// /* ... */
41 /// }
42 ///
43 /// /* ... */
44 /// # _ => {}
45 /// # }
46 /// # }
47 /// ```
48 ///
49 /// We begin with a variable `expr` of type `Expr` that has no fields
50 /// (because it is an enum), and by matching on it and rebinding a variable
51 /// with the same name `expr` we effectively imbue our variable with all of
52 /// the data fields provided by the variant that it turned out to be. So for
53 /// example above if we ended up in the `MethodCall` case then we get to use
54 /// `expr.receiver`, `expr.args` etc; if we ended up in the `If` case we get
55 /// to use `expr.cond`, `expr.then_branch`, `expr.else_branch`.
56 ///
57 /// This approach avoids repeating the variant names twice on every line.
58 ///
59 /// ```
60 /// # use syn::{Expr, ExprMethodCall};
61 /// #
62 /// # fn example(expr: Expr) {
63 /// // Repetitive; recommend not doing this.
64 /// match expr {
65 /// Expr::MethodCall(ExprMethodCall { method, args, .. }) => {
66 /// # }
67 /// # _ => {}
68 /// # }
69 /// # }
70 /// ```
71 ///
72 /// In general, the name to which a syntax tree enum variant is bound should
73 /// be a suitable name for the complete syntax tree enum type.
74 ///
75 /// ```
76 /// # use syn::{Expr, ExprField};
77 /// #
78 /// # fn example(discriminant: ExprField) {
79 /// // Binding is called `base` which is the name I would use if I were
80 /// // assigning `*discriminant.base` without an `if let`.
81 /// if let Expr::Tuple(base) = *discriminant.base {
82 /// # }
83 /// # }
84 /// ```
85 ///
86 /// A sign that you may not be choosing the right variable names is if you
87 /// see names getting repeated in your code, like accessing
88 /// `receiver.receiver` or `pat.pat` or `cond.cond`.
5869c6ff 89 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
1b1a35ee 90 pub enum Expr {
e74abb32
XL
91 /// A slice literal expression: `[a, b, c, d]`.
92 Array(ExprArray),
93
94 /// An assignment expression: `a = compute()`.
95 Assign(ExprAssign),
96
97 /// A compound assignment expression: `counter += 1`.
98 AssignOp(ExprAssignOp),
99
100 /// An async block: `async { ... }`.
101 Async(ExprAsync),
102
103 /// An await expression: `fut.await`.
104 Await(ExprAwait),
105
106 /// A binary operation: `a + b`, `a * b`.
107 Binary(ExprBinary),
108
109 /// A blocked scope: `{ ... }`.
110 Block(ExprBlock),
111
112 /// A box expression: `box f`.
113 Box(ExprBox),
114
115 /// A `break`, with an optional label to break and an optional
116 /// expression.
117 Break(ExprBreak),
118
119 /// A function call expression: `invoke(a, b)`.
120 Call(ExprCall),
121
122 /// A cast expression: `foo as f64`.
123 Cast(ExprCast),
124
125 /// A closure expression: `|a, b| a + b`.
126 Closure(ExprClosure),
127
128 /// A `continue`, with an optional label.
129 Continue(ExprContinue),
130
131 /// Access of a named struct field (`obj.k`) or unnamed tuple struct
132 /// field (`obj.0`).
133 Field(ExprField),
134
135 /// A for loop: `for pat in expr { ... }`.
136 ForLoop(ExprForLoop),
137
138 /// An expression contained within invisible delimiters.
139 ///
140 /// This variant is important for faithfully representing the precedence
141 /// of expressions and is related to `None`-delimited spans in a
142 /// `TokenStream`.
143 Group(ExprGroup),
144
145 /// An `if` expression with an optional `else` block: `if expr { ... }
146 /// else { ... }`.
147 ///
148 /// The `else` branch expression may only be an `If` or `Block`
149 /// expression, not any of the other types of expression.
150 If(ExprIf),
151
152 /// A square bracketed indexing expression: `vector[2]`.
153 Index(ExprIndex),
154
155 /// A `let` guard: `let Some(x) = opt`.
156 Let(ExprLet),
157
158 /// A literal in place of an expression: `1`, `"foo"`.
159 Lit(ExprLit),
160
161 /// Conditionless loop: `loop { ... }`.
162 Loop(ExprLoop),
163
164 /// A macro invocation expression: `format!("{}", q)`.
165 Macro(ExprMacro),
166
167 /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
168 Match(ExprMatch),
169
170 /// A method call expression: `x.foo::<T>(a, b)`.
171 MethodCall(ExprMethodCall),
172
173 /// A parenthesized expression: `(a + b)`.
174 Paren(ExprParen),
175
176 /// A path like `std::mem::replace` possibly containing generic
177 /// parameters and a qualified self-type.
178 ///
179 /// A plain identifier like `x` is a path of length 1.
180 Path(ExprPath),
181
182 /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
183 Range(ExprRange),
184
185 /// A referencing operation: `&a` or `&mut a`.
186 Reference(ExprReference),
187
188 /// An array literal constructed from one repeated element: `[0u8; N]`.
189 Repeat(ExprRepeat),
190
191 /// A `return`, with an optional value to be returned.
192 Return(ExprReturn),
193
194 /// A struct literal expression: `Point { x: 1, y: 1 }`.
195 ///
196 /// The `rest` provides the value of the remaining fields as in `S { a:
197 /// 1, b: 1, ..rest }`.
198 Struct(ExprStruct),
199
200 /// A try-expression: `expr?`.
201 Try(ExprTry),
202
203 /// A try block: `try { ... }`.
204 TryBlock(ExprTryBlock),
205
206 /// A tuple expression: `(a, b, c, d)`.
207 Tuple(ExprTuple),
208
209 /// A type ascription expression: `foo: f64`.
210 Type(ExprType),
211
212 /// A unary operation: `!x`, `*x`.
213 Unary(ExprUnary),
214
215 /// An unsafe block: `unsafe { ... }`.
216 Unsafe(ExprUnsafe),
217
218 /// Tokens in expression position not interpreted by Syn.
219 Verbatim(TokenStream),
220
221 /// A while loop: `while expr { ... }`.
222 While(ExprWhile),
223
224 /// A yield expression: `yield expr`.
225 Yield(ExprYield),
226
5869c6ff
XL
227 // The following is the only supported idiom for exhaustive matching of
228 // this enum.
229 //
230 // match expr {
231 // Expr::Array(e) => {...}
232 // Expr::Assign(e) => {...}
233 // ...
234 // Expr::Yield(e) => {...}
235 //
236 // #[cfg(test)]
237 // Expr::__TestExhaustive(_) => unimplemented!(),
238 // #[cfg(not(test))]
239 // _ => { /* some sane fallback */ }
240 // }
241 //
242 // This way we fail your tests but don't break your library when adding
243 // a variant. You will be notified by a test failure when a variant is
244 // added, so that you can add code to handle it, but your library will
245 // continue to compile and work for downstream users in the interim.
246 //
247 // Once `deny(reachable)` is available in rustc, Expr will be
248 // reimplemented as a non_exhaustive enum.
249 // https://github.com/rust-lang/rust/issues/44109#issuecomment-521781237
e74abb32 250 #[doc(hidden)]
5869c6ff 251 __TestExhaustive(crate::private),
e74abb32
XL
252 }
253}
254
255ast_struct! {
256 /// A slice literal expression: `[a, b, c, d]`.
257 ///
f035d41b 258 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 259 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
260 pub struct ExprArray #full {
261 pub attrs: Vec<Attribute>,
262 pub bracket_token: token::Bracket,
263 pub elems: Punctuated<Expr, Token![,]>,
264 }
265}
266
267ast_struct! {
268 /// An assignment expression: `a = compute()`.
269 ///
f035d41b 270 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 271 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
272 pub struct ExprAssign #full {
273 pub attrs: Vec<Attribute>,
274 pub left: Box<Expr>,
275 pub eq_token: Token![=],
276 pub right: Box<Expr>,
277 }
278}
279
280ast_struct! {
281 /// A compound assignment expression: `counter += 1`.
282 ///
f035d41b 283 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 284 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
285 pub struct ExprAssignOp #full {
286 pub attrs: Vec<Attribute>,
287 pub left: Box<Expr>,
288 pub op: BinOp,
289 pub right: Box<Expr>,
290 }
291}
292
293ast_struct! {
294 /// An async block: `async { ... }`.
295 ///
f035d41b 296 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 297 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
298 pub struct ExprAsync #full {
299 pub attrs: Vec<Attribute>,
300 pub async_token: Token![async],
301 pub capture: Option<Token![move]>,
302 pub block: Block,
303 }
304}
305
306ast_struct! {
307 /// An await expression: `fut.await`.
308 ///
f035d41b 309 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 310 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
311 pub struct ExprAwait #full {
312 pub attrs: Vec<Attribute>,
313 pub base: Box<Expr>,
314 pub dot_token: Token![.],
315 pub await_token: token::Await,
316 }
317}
318
319ast_struct! {
320 /// A binary operation: `a + b`, `a * b`.
321 ///
f035d41b 322 /// *This type is available only if Syn is built with the `"derive"` or
e74abb32 323 /// `"full"` feature.*
5869c6ff 324 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
e74abb32
XL
325 pub struct ExprBinary {
326 pub attrs: Vec<Attribute>,
327 pub left: Box<Expr>,
328 pub op: BinOp,
329 pub right: Box<Expr>,
330 }
331}
332
333ast_struct! {
334 /// A blocked scope: `{ ... }`.
335 ///
f035d41b 336 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 337 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
338 pub struct ExprBlock #full {
339 pub attrs: Vec<Attribute>,
340 pub label: Option<Label>,
341 pub block: Block,
342 }
343}
344
345ast_struct! {
346 /// A box expression: `box f`.
347 ///
f035d41b 348 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 349 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
350 pub struct ExprBox #full {
351 pub attrs: Vec<Attribute>,
352 pub box_token: Token![box],
353 pub expr: Box<Expr>,
354 }
355}
356
357ast_struct! {
358 /// A `break`, with an optional label to break and an optional
359 /// expression.
360 ///
f035d41b 361 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 362 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
363 pub struct ExprBreak #full {
364 pub attrs: Vec<Attribute>,
365 pub break_token: Token![break],
366 pub label: Option<Lifetime>,
367 pub expr: Option<Box<Expr>>,
368 }
369}
370
371ast_struct! {
372 /// A function call expression: `invoke(a, b)`.
373 ///
f035d41b 374 /// *This type is available only if Syn is built with the `"derive"` or
e74abb32 375 /// `"full"` feature.*
5869c6ff 376 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
e74abb32
XL
377 pub struct ExprCall {
378 pub attrs: Vec<Attribute>,
379 pub func: Box<Expr>,
380 pub paren_token: token::Paren,
381 pub args: Punctuated<Expr, Token![,]>,
382 }
383}
384
385ast_struct! {
386 /// A cast expression: `foo as f64`.
387 ///
f035d41b 388 /// *This type is available only if Syn is built with the `"derive"` or
e74abb32 389 /// `"full"` feature.*
5869c6ff 390 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
e74abb32
XL
391 pub struct ExprCast {
392 pub attrs: Vec<Attribute>,
393 pub expr: Box<Expr>,
394 pub as_token: Token![as],
395 pub ty: Box<Type>,
396 }
397}
398
399ast_struct! {
400 /// A closure expression: `|a, b| a + b`.
401 ///
f035d41b 402 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 403 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
404 pub struct ExprClosure #full {
405 pub attrs: Vec<Attribute>,
406 pub asyncness: Option<Token![async]>,
407 pub movability: Option<Token![static]>,
408 pub capture: Option<Token![move]>,
409 pub or1_token: Token![|],
410 pub inputs: Punctuated<Pat, Token![,]>,
411 pub or2_token: Token![|],
412 pub output: ReturnType,
413 pub body: Box<Expr>,
414 }
415}
416
417ast_struct! {
418 /// A `continue`, with an optional label.
419 ///
f035d41b 420 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 421 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
422 pub struct ExprContinue #full {
423 pub attrs: Vec<Attribute>,
424 pub continue_token: Token![continue],
425 pub label: Option<Lifetime>,
426 }
427}
428
429ast_struct! {
430 /// Access of a named struct field (`obj.k`) or unnamed tuple struct
431 /// field (`obj.0`).
432 ///
f035d41b 433 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 434 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
e74abb32
XL
435 pub struct ExprField {
436 pub attrs: Vec<Attribute>,
437 pub base: Box<Expr>,
438 pub dot_token: Token![.],
439 pub member: Member,
440 }
441}
442
443ast_struct! {
444 /// A for loop: `for pat in expr { ... }`.
445 ///
f035d41b 446 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 447 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
448 pub struct ExprForLoop #full {
449 pub attrs: Vec<Attribute>,
450 pub label: Option<Label>,
451 pub for_token: Token![for],
452 pub pat: Pat,
453 pub in_token: Token![in],
454 pub expr: Box<Expr>,
455 pub body: Block,
456 }
457}
458
459ast_struct! {
460 /// An expression contained within invisible delimiters.
461 ///
462 /// This variant is important for faithfully representing the precedence
463 /// of expressions and is related to `None`-delimited spans in a
464 /// `TokenStream`.
465 ///
f035d41b 466 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 467 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
468 pub struct ExprGroup #full {
469 pub attrs: Vec<Attribute>,
470 pub group_token: token::Group,
471 pub expr: Box<Expr>,
472 }
473}
474
475ast_struct! {
476 /// An `if` expression with an optional `else` block: `if expr { ... }
477 /// else { ... }`.
478 ///
479 /// The `else` branch expression may only be an `If` or `Block`
480 /// expression, not any of the other types of expression.
481 ///
f035d41b 482 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 483 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
484 pub struct ExprIf #full {
485 pub attrs: Vec<Attribute>,
486 pub if_token: Token![if],
487 pub cond: Box<Expr>,
488 pub then_branch: Block,
489 pub else_branch: Option<(Token![else], Box<Expr>)>,
490 }
491}
492
493ast_struct! {
494 /// A square bracketed indexing expression: `vector[2]`.
495 ///
f035d41b 496 /// *This type is available only if Syn is built with the `"derive"` or
e74abb32 497 /// `"full"` feature.*
5869c6ff 498 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
e74abb32
XL
499 pub struct ExprIndex {
500 pub attrs: Vec<Attribute>,
501 pub expr: Box<Expr>,
502 pub bracket_token: token::Bracket,
503 pub index: Box<Expr>,
504 }
505}
506
507ast_struct! {
508 /// A `let` guard: `let Some(x) = opt`.
509 ///
f035d41b 510 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 511 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
512 pub struct ExprLet #full {
513 pub attrs: Vec<Attribute>,
514 pub let_token: Token![let],
515 pub pat: Pat,
516 pub eq_token: Token![=],
517 pub expr: Box<Expr>,
518 }
519}
520
521ast_struct! {
522 /// A literal in place of an expression: `1`, `"foo"`.
523 ///
f035d41b 524 /// *This type is available only if Syn is built with the `"derive"` or
e74abb32 525 /// `"full"` feature.*
5869c6ff 526 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
e74abb32
XL
527 pub struct ExprLit {
528 pub attrs: Vec<Attribute>,
529 pub lit: Lit,
530 }
531}
532
533ast_struct! {
534 /// Conditionless loop: `loop { ... }`.
535 ///
f035d41b 536 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 537 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
538 pub struct ExprLoop #full {
539 pub attrs: Vec<Attribute>,
540 pub label: Option<Label>,
541 pub loop_token: Token![loop],
542 pub body: Block,
543 }
544}
545
546ast_struct! {
547 /// A macro invocation expression: `format!("{}", q)`.
548 ///
f035d41b 549 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 550 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
551 pub struct ExprMacro #full {
552 pub attrs: Vec<Attribute>,
553 pub mac: Macro,
554 }
555}
556
557ast_struct! {
558 /// A `match` expression: `match n { Some(n) => {}, None => {} }`.
559 ///
f035d41b 560 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 561 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
562 pub struct ExprMatch #full {
563 pub attrs: Vec<Attribute>,
564 pub match_token: Token![match],
565 pub expr: Box<Expr>,
566 pub brace_token: token::Brace,
567 pub arms: Vec<Arm>,
568 }
569}
570
571ast_struct! {
572 /// A method call expression: `x.foo::<T>(a, b)`.
573 ///
f035d41b 574 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 575 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
576 pub struct ExprMethodCall #full {
577 pub attrs: Vec<Attribute>,
578 pub receiver: Box<Expr>,
579 pub dot_token: Token![.],
580 pub method: Ident,
581 pub turbofish: Option<MethodTurbofish>,
582 pub paren_token: token::Paren,
583 pub args: Punctuated<Expr, Token![,]>,
584 }
585}
586
587ast_struct! {
588 /// A parenthesized expression: `(a + b)`.
589 ///
f035d41b 590 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 591 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
e74abb32
XL
592 pub struct ExprParen {
593 pub attrs: Vec<Attribute>,
594 pub paren_token: token::Paren,
595 pub expr: Box<Expr>,
596 }
597}
598
599ast_struct! {
600 /// A path like `std::mem::replace` possibly containing generic
601 /// parameters and a qualified self-type.
602 ///
603 /// A plain identifier like `x` is a path of length 1.
604 ///
f035d41b 605 /// *This type is available only if Syn is built with the `"derive"` or
e74abb32 606 /// `"full"` feature.*
5869c6ff 607 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
e74abb32
XL
608 pub struct ExprPath {
609 pub attrs: Vec<Attribute>,
610 pub qself: Option<QSelf>,
611 pub path: Path,
612 }
613}
614
615ast_struct! {
616 /// A range expression: `1..2`, `1..`, `..2`, `1..=2`, `..=2`.
617 ///
f035d41b 618 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 619 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
620 pub struct ExprRange #full {
621 pub attrs: Vec<Attribute>,
622 pub from: Option<Box<Expr>>,
623 pub limits: RangeLimits,
624 pub to: Option<Box<Expr>>,
625 }
626}
627
628ast_struct! {
629 /// A referencing operation: `&a` or `&mut a`.
630 ///
f035d41b 631 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 632 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
633 pub struct ExprReference #full {
634 pub attrs: Vec<Attribute>,
635 pub and_token: Token![&],
636 pub raw: Reserved,
637 pub mutability: Option<Token![mut]>,
638 pub expr: Box<Expr>,
639 }
640}
641
642ast_struct! {
643 /// An array literal constructed from one repeated element: `[0u8; N]`.
644 ///
f035d41b 645 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 646 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
647 pub struct ExprRepeat #full {
648 pub attrs: Vec<Attribute>,
649 pub bracket_token: token::Bracket,
650 pub expr: Box<Expr>,
651 pub semi_token: Token![;],
652 pub len: Box<Expr>,
653 }
654}
655
656ast_struct! {
657 /// A `return`, with an optional value to be returned.
658 ///
f035d41b 659 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 660 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
661 pub struct ExprReturn #full {
662 pub attrs: Vec<Attribute>,
663 pub return_token: Token![return],
664 pub expr: Option<Box<Expr>>,
665 }
666}
667
668ast_struct! {
669 /// A struct literal expression: `Point { x: 1, y: 1 }`.
670 ///
671 /// The `rest` provides the value of the remaining fields as in `S { a:
672 /// 1, b: 1, ..rest }`.
673 ///
f035d41b 674 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 675 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
676 pub struct ExprStruct #full {
677 pub attrs: Vec<Attribute>,
678 pub path: Path,
679 pub brace_token: token::Brace,
680 pub fields: Punctuated<FieldValue, Token![,]>,
681 pub dot2_token: Option<Token![..]>,
682 pub rest: Option<Box<Expr>>,
683 }
684}
685
686ast_struct! {
687 /// A try-expression: `expr?`.
688 ///
f035d41b 689 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 690 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
691 pub struct ExprTry #full {
692 pub attrs: Vec<Attribute>,
693 pub expr: Box<Expr>,
694 pub question_token: Token![?],
695 }
696}
697
698ast_struct! {
699 /// A try block: `try { ... }`.
700 ///
f035d41b 701 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 702 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
703 pub struct ExprTryBlock #full {
704 pub attrs: Vec<Attribute>,
705 pub try_token: Token![try],
706 pub block: Block,
707 }
708}
709
710ast_struct! {
711 /// A tuple expression: `(a, b, c, d)`.
712 ///
f035d41b 713 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 714 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
715 pub struct ExprTuple #full {
716 pub attrs: Vec<Attribute>,
717 pub paren_token: token::Paren,
718 pub elems: Punctuated<Expr, Token![,]>,
719 }
720}
721
722ast_struct! {
723 /// A type ascription expression: `foo: f64`.
724 ///
f035d41b 725 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 726 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
727 pub struct ExprType #full {
728 pub attrs: Vec<Attribute>,
729 pub expr: Box<Expr>,
730 pub colon_token: Token![:],
731 pub ty: Box<Type>,
732 }
733}
734
735ast_struct! {
736 /// A unary operation: `!x`, `*x`.
737 ///
f035d41b 738 /// *This type is available only if Syn is built with the `"derive"` or
e74abb32 739 /// `"full"` feature.*
5869c6ff 740 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
e74abb32
XL
741 pub struct ExprUnary {
742 pub attrs: Vec<Attribute>,
743 pub op: UnOp,
744 pub expr: Box<Expr>,
745 }
746}
747
748ast_struct! {
749 /// An unsafe block: `unsafe { ... }`.
750 ///
f035d41b 751 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 752 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
753 pub struct ExprUnsafe #full {
754 pub attrs: Vec<Attribute>,
755 pub unsafe_token: Token![unsafe],
756 pub block: Block,
757 }
758}
759
760ast_struct! {
761 /// A while loop: `while expr { ... }`.
762 ///
f035d41b 763 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 764 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
765 pub struct ExprWhile #full {
766 pub attrs: Vec<Attribute>,
767 pub label: Option<Label>,
768 pub while_token: Token![while],
769 pub cond: Box<Expr>,
770 pub body: Block,
771 }
772}
773
774ast_struct! {
775 /// A yield expression: `yield expr`.
776 ///
f035d41b 777 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 778 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
779 pub struct ExprYield #full {
780 pub attrs: Vec<Attribute>,
781 pub yield_token: Token![yield],
782 pub expr: Option<Box<Expr>>,
783 }
784}
785
e74abb32
XL
786impl Expr {
787 #[cfg(all(feature = "parsing", feature = "full"))]
788 pub(crate) fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
789 match self {
790 Expr::Box(ExprBox { attrs, .. })
791 | Expr::Array(ExprArray { attrs, .. })
792 | Expr::Call(ExprCall { attrs, .. })
793 | Expr::MethodCall(ExprMethodCall { attrs, .. })
794 | Expr::Tuple(ExprTuple { attrs, .. })
795 | Expr::Binary(ExprBinary { attrs, .. })
796 | Expr::Unary(ExprUnary { attrs, .. })
797 | Expr::Lit(ExprLit { attrs, .. })
798 | Expr::Cast(ExprCast { attrs, .. })
799 | Expr::Type(ExprType { attrs, .. })
800 | Expr::Let(ExprLet { attrs, .. })
801 | Expr::If(ExprIf { attrs, .. })
802 | Expr::While(ExprWhile { attrs, .. })
803 | Expr::ForLoop(ExprForLoop { attrs, .. })
804 | Expr::Loop(ExprLoop { attrs, .. })
805 | Expr::Match(ExprMatch { attrs, .. })
806 | Expr::Closure(ExprClosure { attrs, .. })
807 | Expr::Unsafe(ExprUnsafe { attrs, .. })
808 | Expr::Block(ExprBlock { attrs, .. })
809 | Expr::Assign(ExprAssign { attrs, .. })
810 | Expr::AssignOp(ExprAssignOp { attrs, .. })
811 | Expr::Field(ExprField { attrs, .. })
812 | Expr::Index(ExprIndex { attrs, .. })
813 | Expr::Range(ExprRange { attrs, .. })
814 | Expr::Path(ExprPath { attrs, .. })
815 | Expr::Reference(ExprReference { attrs, .. })
816 | Expr::Break(ExprBreak { attrs, .. })
817 | Expr::Continue(ExprContinue { attrs, .. })
818 | Expr::Return(ExprReturn { attrs, .. })
819 | Expr::Macro(ExprMacro { attrs, .. })
820 | Expr::Struct(ExprStruct { attrs, .. })
821 | Expr::Repeat(ExprRepeat { attrs, .. })
822 | Expr::Paren(ExprParen { attrs, .. })
823 | Expr::Group(ExprGroup { attrs, .. })
824 | Expr::Try(ExprTry { attrs, .. })
825 | Expr::Async(ExprAsync { attrs, .. })
826 | Expr::Await(ExprAwait { attrs, .. })
827 | Expr::TryBlock(ExprTryBlock { attrs, .. })
828 | Expr::Yield(ExprYield { attrs, .. }) => mem::replace(attrs, new),
829 Expr::Verbatim(_) => Vec::new(),
6a06907d
XL
830
831 #[cfg(test)]
832 Expr::__TestExhaustive(_) => unimplemented!(),
833 #[cfg(not(test))]
834 _ => unreachable!(),
e74abb32
XL
835 }
836 }
837}
838
839ast_enum! {
840 /// A struct or tuple struct field accessed in a struct literal or field
841 /// expression.
842 ///
f035d41b 843 /// *This type is available only if Syn is built with the `"derive"` or `"full"`
e74abb32 844 /// feature.*
5869c6ff 845 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
1b1a35ee 846 pub enum Member {
e74abb32
XL
847 /// A named field like `self.x`.
848 Named(Ident),
849 /// An unnamed field like `self.0`.
850 Unnamed(Index),
851 }
852}
853
1b1a35ee
XL
854impl Eq for Member {}
855
856impl PartialEq for Member {
857 fn eq(&self, other: &Self) -> bool {
858 match (self, other) {
859 (Member::Named(this), Member::Named(other)) => this == other,
860 (Member::Unnamed(this), Member::Unnamed(other)) => this == other,
861 _ => false,
862 }
863 }
864}
865
866impl Hash for Member {
867 fn hash<H: Hasher>(&self, state: &mut H) {
868 match self {
869 Member::Named(m) => m.hash(state),
870 Member::Unnamed(m) => m.hash(state),
871 }
872 }
873}
874
60c5eb7d
XL
875#[cfg(feature = "printing")]
876impl IdentFragment for Member {
877 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
878 match self {
879 Member::Named(m) => Display::fmt(m, formatter),
880 Member::Unnamed(m) => Display::fmt(&m.index, formatter),
881 }
882 }
883
884 fn span(&self) -> Option<Span> {
885 match self {
886 Member::Named(m) => Some(m.span()),
887 Member::Unnamed(m) => Some(m.span),
888 }
889 }
890}
891
e74abb32
XL
892ast_struct! {
893 /// The index of an unnamed tuple struct field.
894 ///
f035d41b 895 /// *This type is available only if Syn is built with the `"derive"` or `"full"`
e74abb32 896 /// feature.*
5869c6ff 897 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
1b1a35ee 898 pub struct Index {
e74abb32
XL
899 pub index: u32,
900 pub span: Span,
901 }
902}
903
904impl From<usize> for Index {
905 fn from(index: usize) -> Index {
906 assert!(index < u32::max_value() as usize);
907 Index {
908 index: index as u32,
909 span: Span::call_site(),
910 }
911 }
912}
913
e74abb32
XL
914impl Eq for Index {}
915
e74abb32
XL
916impl PartialEq for Index {
917 fn eq(&self, other: &Self) -> bool {
918 self.index == other.index
919 }
920}
921
e74abb32
XL
922impl Hash for Index {
923 fn hash<H: Hasher>(&self, state: &mut H) {
924 self.index.hash(state);
925 }
926}
927
60c5eb7d
XL
928#[cfg(feature = "printing")]
929impl IdentFragment for Index {
930 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
931 Display::fmt(&self.index, formatter)
932 }
933
934 fn span(&self) -> Option<Span> {
935 Some(self.span)
936 }
937}
938
e74abb32
XL
939#[cfg(feature = "full")]
940ast_struct! {
941 /// The `::<>` explicit type parameters passed to a method call:
942 /// `parse::<u64>()`.
943 ///
f035d41b 944 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 945 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
946 pub struct MethodTurbofish {
947 pub colon2_token: Token![::],
948 pub lt_token: Token![<],
949 pub args: Punctuated<GenericMethodArgument, Token![,]>,
950 pub gt_token: Token![>],
951 }
952}
953
954#[cfg(feature = "full")]
955ast_enum! {
956 /// An individual generic argument to a method, like `T`.
957 ///
f035d41b 958 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 959 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
960 pub enum GenericMethodArgument {
961 /// A type argument.
962 Type(Type),
963 /// A const expression. Must be inside of a block.
964 ///
965 /// NOTE: Identity expressions are represented as Type arguments, as
966 /// they are indistinguishable syntactically.
967 Const(Expr),
968 }
969}
970
971#[cfg(feature = "full")]
972ast_struct! {
973 /// A field-value pair in a struct literal.
974 ///
f035d41b 975 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 976 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
977 pub struct FieldValue {
978 /// Attributes tagged on the field.
979 pub attrs: Vec<Attribute>,
980
981 /// Name or index of the field.
982 pub member: Member,
983
984 /// The colon in `Struct { x: x }`. If written in shorthand like
985 /// `Struct { x }`, there is no colon.
986 pub colon_token: Option<Token![:]>,
987
988 /// Value of the field.
989 pub expr: Expr,
990 }
991}
992
993#[cfg(feature = "full")]
994ast_struct! {
995 /// A lifetime labeling a `for`, `while`, or `loop`.
996 ///
f035d41b 997 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 998 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
999 pub struct Label {
1000 pub name: Lifetime,
1001 pub colon_token: Token![:],
1002 }
1003}
1004
1005#[cfg(feature = "full")]
1006ast_struct! {
1007 /// One arm of a `match` expression: `0...10 => { return true; }`.
1008 ///
1009 /// As in:
1010 ///
1011 /// ```
1012 /// # fn f() -> bool {
1013 /// # let n = 0;
1014 /// match n {
1015 /// 0...10 => {
1016 /// return true;
1017 /// }
1018 /// // ...
1019 /// # _ => {}
1020 /// }
1021 /// # false
1022 /// # }
1023 /// ```
1024 ///
f035d41b 1025 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 1026 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
1027 pub struct Arm {
1028 pub attrs: Vec<Attribute>,
1029 pub pat: Pat,
1030 pub guard: Option<(Token![if], Box<Expr>)>,
1031 pub fat_arrow_token: Token![=>],
1032 pub body: Box<Expr>,
1033 pub comma: Option<Token![,]>,
1034 }
1035}
1036
1037#[cfg(feature = "full")]
1038ast_enum! {
1039 /// Limit types of a range, inclusive or exclusive.
1040 ///
f035d41b 1041 /// *This type is available only if Syn is built with the `"full"` feature.*
5869c6ff 1042 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
e74abb32
XL
1043 pub enum RangeLimits {
1044 /// Inclusive at the beginning, exclusive at the end.
1045 HalfOpen(Token![..]),
1046 /// Inclusive at the beginning and end.
1047 Closed(Token![..=]),
1048 }
1049}
1050
1051#[cfg(any(feature = "parsing", feature = "printing"))]
1052#[cfg(feature = "full")]
1053pub(crate) fn requires_terminator(expr: &Expr) -> bool {
f035d41b 1054 // see https://github.com/rust-lang/rust/blob/2679c38fc/src/librustc_ast/util/classify.rs#L7-L25
e74abb32
XL
1055 match *expr {
1056 Expr::Unsafe(..)
1057 | Expr::Block(..)
1058 | Expr::If(..)
1059 | Expr::Match(..)
1060 | Expr::While(..)
1061 | Expr::Loop(..)
1062 | Expr::ForLoop(..)
1063 | Expr::Async(..)
1064 | Expr::TryBlock(..) => false,
1065 _ => true,
1066 }
1067}
1068
1069#[cfg(feature = "parsing")]
1070pub(crate) mod parsing {
1071 use super::*;
e74abb32
XL
1072 use crate::parse::{Parse, ParseStream, Result};
1073 use crate::path;
5869c6ff
XL
1074 #[cfg(feature = "full")]
1075 use proc_macro2::TokenTree;
1b1a35ee 1076 use std::cmp::Ordering;
e74abb32 1077
f035d41b
XL
1078 crate::custom_keyword!(raw);
1079
e74abb32
XL
1080 // When we're parsing expressions which occur before blocks, like in an if
1081 // statement's condition, we cannot parse a struct literal.
1082 //
1083 // Struct literals are ambiguous in certain positions
1084 // https://github.com/rust-lang/rfcs/pull/92
e74abb32
XL
1085 pub struct AllowStruct(bool);
1086
e74abb32
XL
1087 enum Precedence {
1088 Any,
1089 Assign,
1090 Range,
1091 Or,
1092 And,
1093 Compare,
1094 BitOr,
1095 BitXor,
1096 BitAnd,
1097 Shift,
1098 Arithmetic,
1099 Term,
1100 Cast,
1101 }
1102
1103 impl Precedence {
1104 fn of(op: &BinOp) -> Self {
1105 match *op {
1106 BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic,
1107 BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term,
1108 BinOp::And(_) => Precedence::And,
1109 BinOp::Or(_) => Precedence::Or,
1110 BinOp::BitXor(_) => Precedence::BitXor,
1111 BinOp::BitAnd(_) => Precedence::BitAnd,
1112 BinOp::BitOr(_) => Precedence::BitOr,
1113 BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
1114 BinOp::Eq(_)
1115 | BinOp::Lt(_)
1116 | BinOp::Le(_)
1117 | BinOp::Ne(_)
1118 | BinOp::Ge(_)
1119 | BinOp::Gt(_) => Precedence::Compare,
1120 BinOp::AddEq(_)
1121 | BinOp::SubEq(_)
1122 | BinOp::MulEq(_)
1123 | BinOp::DivEq(_)
1124 | BinOp::RemEq(_)
1125 | BinOp::BitXorEq(_)
1126 | BinOp::BitAndEq(_)
1127 | BinOp::BitOrEq(_)
1128 | BinOp::ShlEq(_)
1129 | BinOp::ShrEq(_) => Precedence::Assign,
1130 }
1131 }
1132 }
1133
5869c6ff 1134 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
e74abb32
XL
1135 impl Parse for Expr {
1136 fn parse(input: ParseStream) -> Result<Self> {
1137 ambiguous_expr(input, AllowStruct(true))
1138 }
1139 }
1140
f035d41b
XL
1141 impl Expr {
1142 /// An alternative to the primary `Expr::parse` parser (from the
1143 /// [`Parse`] trait) for ambiguous syntactic positions in which a
1144 /// trailing brace should not be taken as part of the expression.
1145 ///
1146 /// Rust grammar has an ambiguity where braces sometimes turn a path
1147 /// expression into a struct initialization and sometimes do not. In the
1148 /// following code, the expression `S {}` is one expression. Presumably
1149 /// there is an empty struct `struct S {}` defined somewhere which it is
1150 /// instantiating.
1151 ///
1152 /// ```
1153 /// # struct S;
1154 /// # impl std::ops::Deref for S {
1155 /// # type Target = bool;
1156 /// # fn deref(&self) -> &Self::Target {
1157 /// # &true
1158 /// # }
1159 /// # }
1160 /// let _ = *S {};
1161 ///
1162 /// // parsed by rustc as: `*(S {})`
1163 /// ```
1164 ///
1165 /// We would want to parse the above using `Expr::parse` after the `=`
1166 /// token.
1167 ///
1168 /// But in the following, `S {}` is *not* a struct init expression.
1169 ///
1170 /// ```
1171 /// # const S: &bool = &true;
1172 /// if *S {} {}
1173 ///
1174 /// // parsed by rustc as:
1175 /// //
1176 /// // if (*S) {
1177 /// // /* empty block */
1178 /// // }
1179 /// // {
1180 /// // /* another empty block */
1181 /// // }
1182 /// ```
1183 ///
1184 /// For that reason we would want to parse if-conditions using
1185 /// `Expr::parse_without_eager_brace` after the `if` token. Same for
1186 /// similar syntactic positions such as the condition expr after a
1187 /// `while` token or the expr at the top of a `match`.
1188 ///
1189 /// The Rust grammar's choices around which way this ambiguity is
1190 /// resolved at various syntactic positions is fairly arbitrary. Really
1191 /// either parse behavior could work in most positions, and language
1192 /// designers just decide each case based on which is more likely to be
1193 /// what the programmer had in mind most of the time.
1194 ///
1195 /// ```
1196 /// # struct S;
1197 /// # fn doc() -> S {
1198 /// if return S {} {}
1199 /// # unreachable!()
1200 /// # }
1201 ///
1202 /// // parsed by rustc as:
1203 /// //
1204 /// // if (return (S {})) {
1205 /// // }
1206 /// //
1207 /// // but could equally well have been this other arbitrary choice:
1208 /// //
1209 /// // if (return S) {
1210 /// // }
1211 /// // {}
1212 /// ```
1213 ///
1214 /// Note the grammar ambiguity on trailing braces is distinct from
1215 /// precedence and is not captured by assigning a precedence level to
1216 /// the braced struct init expr in relation to other operators. This can
1217 /// be illustrated by `return 0..S {}` vs `match 0..S {}`. The former
1218 /// parses as `return (0..(S {}))` implying tighter precedence for
1219 /// struct init than `..`, while the latter parses as `match (0..S) {}`
1220 /// implying tighter precedence for `..` than struct init, a
1221 /// contradiction.
1222 #[cfg(feature = "full")]
5869c6ff 1223 #[cfg_attr(doc_cfg, doc(cfg(all(feature = "full", feature = "parsing"))))]
f035d41b
XL
1224 pub fn parse_without_eager_brace(input: ParseStream) -> Result<Expr> {
1225 ambiguous_expr(input, AllowStruct(false))
1226 }
e74abb32
XL
1227 }
1228
1b1a35ee
XL
1229 impl Copy for AllowStruct {}
1230
1231 impl Clone for AllowStruct {
1232 fn clone(&self) -> Self {
1233 *self
1234 }
1235 }
1236
1237 impl Copy for Precedence {}
1238
1239 impl Clone for Precedence {
1240 fn clone(&self) -> Self {
1241 *self
1242 }
1243 }
1244
1245 impl PartialEq for Precedence {
1246 fn eq(&self, other: &Self) -> bool {
1247 *self as u8 == *other as u8
1248 }
1249 }
1250
1251 impl PartialOrd for Precedence {
1252 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1253 let this = *self as u8;
1254 let other = *other as u8;
1255 Some(this.cmp(&other))
1256 }
1257 }
1258
e74abb32
XL
1259 #[cfg(feature = "full")]
1260 fn parse_expr(
1261 input: ParseStream,
1262 mut lhs: Expr,
1263 allow_struct: AllowStruct,
1264 base: Precedence,
1265 ) -> Result<Expr> {
1266 loop {
1267 if input
1268 .fork()
1269 .parse::<BinOp>()
1270 .ok()
1271 .map_or(false, |op| Precedence::of(&op) >= base)
1272 {
1273 let op: BinOp = input.parse()?;
1274 let precedence = Precedence::of(&op);
1275 let mut rhs = unary_expr(input, allow_struct)?;
1276 loop {
1277 let next = peek_precedence(input);
1278 if next > precedence || next == precedence && precedence == Precedence::Assign {
1279 rhs = parse_expr(input, rhs, allow_struct, next)?;
1280 } else {
1281 break;
1282 }
1283 }
1284 lhs = if precedence == Precedence::Assign {
1285 Expr::AssignOp(ExprAssignOp {
1286 attrs: Vec::new(),
1287 left: Box::new(lhs),
1288 op,
1289 right: Box::new(rhs),
1290 })
1291 } else {
1292 Expr::Binary(ExprBinary {
1293 attrs: Vec::new(),
1294 left: Box::new(lhs),
1295 op,
1296 right: Box::new(rhs),
1297 })
1298 };
1299 } else if Precedence::Assign >= base
1300 && input.peek(Token![=])
1301 && !input.peek(Token![==])
1302 && !input.peek(Token![=>])
1303 {
1304 let eq_token: Token![=] = input.parse()?;
1305 let mut rhs = unary_expr(input, allow_struct)?;
1306 loop {
1307 let next = peek_precedence(input);
1308 if next >= Precedence::Assign {
1309 rhs = parse_expr(input, rhs, allow_struct, next)?;
1310 } else {
1311 break;
1312 }
1313 }
1314 lhs = Expr::Assign(ExprAssign {
1315 attrs: Vec::new(),
1316 left: Box::new(lhs),
1317 eq_token,
1318 right: Box::new(rhs),
1319 });
1320 } else if Precedence::Range >= base && input.peek(Token![..]) {
1321 let limits: RangeLimits = input.parse()?;
1322 let rhs = if input.is_empty()
1323 || input.peek(Token![,])
1324 || input.peek(Token![;])
1325 || !allow_struct.0 && input.peek(token::Brace)
1326 {
1327 None
1328 } else {
1329 let mut rhs = unary_expr(input, allow_struct)?;
1330 loop {
1331 let next = peek_precedence(input);
1332 if next > Precedence::Range {
1333 rhs = parse_expr(input, rhs, allow_struct, next)?;
1334 } else {
1335 break;
1336 }
1337 }
1338 Some(rhs)
1339 };
1340 lhs = Expr::Range(ExprRange {
1341 attrs: Vec::new(),
1342 from: Some(Box::new(lhs)),
1343 limits,
1344 to: rhs.map(Box::new),
1345 });
1346 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1347 let as_token: Token![as] = input.parse()?;
1348 let ty = input.call(Type::without_plus)?;
1349 lhs = Expr::Cast(ExprCast {
1350 attrs: Vec::new(),
1351 expr: Box::new(lhs),
1352 as_token,
1353 ty: Box::new(ty),
1354 });
1355 } else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) {
1356 let colon_token: Token![:] = input.parse()?;
1357 let ty = input.call(Type::without_plus)?;
1358 lhs = Expr::Type(ExprType {
1359 attrs: Vec::new(),
1360 expr: Box::new(lhs),
1361 colon_token,
1362 ty: Box::new(ty),
1363 });
1364 } else {
1365 break;
1366 }
1367 }
1368 Ok(lhs)
1369 }
1370
1371 #[cfg(not(feature = "full"))]
1372 fn parse_expr(
1373 input: ParseStream,
1374 mut lhs: Expr,
1375 allow_struct: AllowStruct,
1376 base: Precedence,
1377 ) -> Result<Expr> {
1378 loop {
1379 if input
1380 .fork()
1381 .parse::<BinOp>()
1382 .ok()
1383 .map_or(false, |op| Precedence::of(&op) >= base)
1384 {
1385 let op: BinOp = input.parse()?;
1386 let precedence = Precedence::of(&op);
1387 let mut rhs = unary_expr(input, allow_struct)?;
1388 loop {
1389 let next = peek_precedence(input);
1390 if next > precedence || next == precedence && precedence == Precedence::Assign {
1391 rhs = parse_expr(input, rhs, allow_struct, next)?;
1392 } else {
1393 break;
1394 }
1395 }
1396 lhs = Expr::Binary(ExprBinary {
1397 attrs: Vec::new(),
1398 left: Box::new(lhs),
1399 op,
1400 right: Box::new(rhs),
1401 });
1402 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1403 let as_token: Token![as] = input.parse()?;
1404 let ty = input.call(Type::without_plus)?;
1405 lhs = Expr::Cast(ExprCast {
1406 attrs: Vec::new(),
1407 expr: Box::new(lhs),
1408 as_token,
1409 ty: Box::new(ty),
1410 });
1411 } else {
1412 break;
1413 }
1414 }
1415 Ok(lhs)
1416 }
1417
1418 fn peek_precedence(input: ParseStream) -> Precedence {
1419 if let Ok(op) = input.fork().parse() {
1420 Precedence::of(&op)
1421 } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
1422 Precedence::Assign
1423 } else if input.peek(Token![..]) {
1424 Precedence::Range
1425 } else if input.peek(Token![as]) || input.peek(Token![:]) && !input.peek(Token![::]) {
1426 Precedence::Cast
1427 } else {
1428 Precedence::Any
1429 }
1430 }
1431
1432 // Parse an arbitrary expression.
1433 fn ambiguous_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1434 let lhs = unary_expr(input, allow_struct)?;
1435 parse_expr(input, lhs, allow_struct, Precedence::Any)
1436 }
1437
f035d41b
XL
1438 #[cfg(feature = "full")]
1439 fn expr_attrs(input: ParseStream) -> Result<Vec<Attribute>> {
1440 let mut attrs = Vec::new();
1441 loop {
1442 if input.peek(token::Group) {
1443 let ahead = input.fork();
1444 let group = crate::group::parse_group(&ahead)?;
1445 if !group.content.peek(Token![#]) || group.content.peek2(Token![!]) {
1446 break;
1447 }
1448 let attr = group.content.call(attr::parsing::single_parse_outer)?;
1449 if !group.content.is_empty() {
1450 break;
1451 }
1452 attrs.push(attr);
1453 } else if input.peek(Token![#]) {
1454 attrs.push(input.call(attr::parsing::single_parse_outer)?);
1455 } else {
1456 break;
1457 }
1458 }
1459 Ok(attrs)
1460 }
1461
e74abb32
XL
1462 // <UnOp> <trailer>
1463 // & <trailer>
1464 // &mut <trailer>
1465 // box <trailer>
1466 #[cfg(feature = "full")]
1467 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
f035d41b
XL
1468 let begin = input.fork();
1469 let attrs = input.call(expr_attrs)?;
1470 if input.peek(Token![&]) {
1471 let and_token: Token![&] = input.parse()?;
1472 let raw: Option<raw> =
1473 if input.peek(raw) && (input.peek2(Token![mut]) || input.peek2(Token![const])) {
1474 Some(input.parse()?)
1475 } else {
1476 None
1477 };
1478 let mutability: Option<Token![mut]> = input.parse()?;
1479 if raw.is_some() && mutability.is_none() {
1480 input.parse::<Token![const]>()?;
1481 }
1482 let expr = Box::new(unary_expr(input, allow_struct)?);
1483 if raw.is_some() {
1484 Ok(Expr::Verbatim(verbatim::between(begin, input)))
1485 } else {
e74abb32
XL
1486 Ok(Expr::Reference(ExprReference {
1487 attrs,
f035d41b 1488 and_token,
e74abb32 1489 raw: Reserved::default(),
f035d41b
XL
1490 mutability,
1491 expr,
e74abb32
XL
1492 }))
1493 }
f035d41b
XL
1494 } else if input.peek(Token![box]) {
1495 Ok(Expr::Box(ExprBox {
1496 attrs,
1497 box_token: input.parse()?,
1498 expr: Box::new(unary_expr(input, allow_struct)?),
1499 }))
1500 } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
1501 Ok(Expr::Unary(ExprUnary {
1502 attrs,
1503 op: input.parse()?,
1504 expr: Box::new(unary_expr(input, allow_struct)?),
1505 }))
e74abb32 1506 } else {
f035d41b 1507 trailer_expr(attrs, input, allow_struct)
e74abb32
XL
1508 }
1509 }
1510
1511 #[cfg(not(feature = "full"))]
1512 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
f035d41b 1513 if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
e74abb32 1514 Ok(Expr::Unary(ExprUnary {
f035d41b 1515 attrs: Vec::new(),
e74abb32
XL
1516 op: input.parse()?,
1517 expr: Box::new(unary_expr(input, allow_struct)?),
1518 }))
1519 } else {
1520 trailer_expr(input, allow_struct)
1521 }
1522 }
1523
1524 // <atom> (..<args>) ...
1525 // <atom> . <ident> (..<args>) ...
1526 // <atom> . <ident> ...
1527 // <atom> . <lit> ...
1528 // <atom> [ <expr> ] ...
1529 // <atom> ? ...
1530 #[cfg(feature = "full")]
f035d41b
XL
1531 fn trailer_expr(
1532 outer_attrs: Vec<Attribute>,
1533 input: ParseStream,
1534 allow_struct: AllowStruct,
1535 ) -> Result<Expr> {
e74abb32
XL
1536 let atom = atom_expr(input, allow_struct)?;
1537 let mut e = trailer_helper(input, atom)?;
1538
1539 let inner_attrs = e.replace_attrs(Vec::new());
1540 let attrs = private::attrs(outer_attrs, inner_attrs);
1541 e.replace_attrs(attrs);
1542 Ok(e)
1543 }
1544
1545 #[cfg(feature = "full")]
1546 fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
1547 loop {
1548 if input.peek(token::Paren) {
1549 let content;
1550 e = Expr::Call(ExprCall {
1551 attrs: Vec::new(),
1552 func: Box::new(e),
1553 paren_token: parenthesized!(content in input),
1554 args: content.parse_terminated(Expr::parse)?,
1555 });
1556 } else if input.peek(Token![.]) && !input.peek(Token![..]) {
3dfed10e 1557 let mut dot_token: Token![.] = input.parse()?;
e74abb32 1558
f035d41b
XL
1559 let await_token: Option<token::Await> = input.parse()?;
1560 if let Some(await_token) = await_token {
e74abb32
XL
1561 e = Expr::Await(ExprAwait {
1562 attrs: Vec::new(),
1563 base: Box::new(e),
1564 dot_token,
f035d41b 1565 await_token,
e74abb32
XL
1566 });
1567 continue;
1568 }
1569
f035d41b
XL
1570 let float_token: Option<LitFloat> = input.parse()?;
1571 if let Some(float_token) = float_token {
3dfed10e
XL
1572 if multi_index(&mut e, &mut dot_token, float_token)? {
1573 continue;
1574 }
f035d41b
XL
1575 }
1576
e74abb32
XL
1577 let member: Member = input.parse()?;
1578 let turbofish = if member.is_named() && input.peek(Token![::]) {
1579 Some(MethodTurbofish {
1580 colon2_token: input.parse()?,
1581 lt_token: input.parse()?,
1582 args: {
1583 let mut args = Punctuated::new();
1584 loop {
1585 if input.peek(Token![>]) {
1586 break;
1587 }
1588 let value = input.call(generic_method_argument)?;
1589 args.push_value(value);
1590 if input.peek(Token![>]) {
1591 break;
1592 }
1593 let punct = input.parse()?;
1594 args.push_punct(punct);
1595 }
1596 args
1597 },
1598 gt_token: input.parse()?,
1599 })
1600 } else {
1601 None
1602 };
1603
1604 if turbofish.is_some() || input.peek(token::Paren) {
1605 if let Member::Named(method) = member {
1606 let content;
1607 e = Expr::MethodCall(ExprMethodCall {
1608 attrs: Vec::new(),
1609 receiver: Box::new(e),
1610 dot_token,
1611 method,
1612 turbofish,
1613 paren_token: parenthesized!(content in input),
1614 args: content.parse_terminated(Expr::parse)?,
1615 });
1616 continue;
1617 }
1618 }
1619
1620 e = Expr::Field(ExprField {
1621 attrs: Vec::new(),
1622 base: Box::new(e),
1623 dot_token,
1624 member,
1625 });
1626 } else if input.peek(token::Bracket) {
1627 let content;
1628 e = Expr::Index(ExprIndex {
1629 attrs: Vec::new(),
1630 expr: Box::new(e),
1631 bracket_token: bracketed!(content in input),
1632 index: content.parse()?,
1633 });
1634 } else if input.peek(Token![?]) {
1635 e = Expr::Try(ExprTry {
1636 attrs: Vec::new(),
1637 expr: Box::new(e),
1638 question_token: input.parse()?,
1639 });
1640 } else {
1641 break;
1642 }
1643 }
1644 Ok(e)
1645 }
1646
1647 #[cfg(not(feature = "full"))]
1648 fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1649 let mut e = atom_expr(input, allow_struct)?;
1650
1651 loop {
1652 if input.peek(token::Paren) {
1653 let content;
1654 e = Expr::Call(ExprCall {
1655 attrs: Vec::new(),
1656 func: Box::new(e),
1657 paren_token: parenthesized!(content in input),
1658 args: content.parse_terminated(Expr::parse)?,
1659 });
1660 } else if input.peek(Token![.]) && !input.peek(Token![..]) && !input.peek2(token::Await)
1661 {
3dfed10e 1662 let mut dot_token: Token![.] = input.parse()?;
f035d41b
XL
1663 let float_token: Option<LitFloat> = input.parse()?;
1664 if let Some(float_token) = float_token {
3dfed10e
XL
1665 if multi_index(&mut e, &mut dot_token, float_token)? {
1666 continue;
1667 }
f035d41b 1668 }
3dfed10e
XL
1669 e = Expr::Field(ExprField {
1670 attrs: Vec::new(),
1671 base: Box::new(e),
1672 dot_token,
1673 member: input.parse()?,
1674 });
e74abb32
XL
1675 } else if input.peek(token::Bracket) {
1676 let content;
1677 e = Expr::Index(ExprIndex {
1678 attrs: Vec::new(),
1679 expr: Box::new(e),
1680 bracket_token: bracketed!(content in input),
1681 index: content.parse()?,
1682 });
1683 } else {
1684 break;
1685 }
1686 }
1687
1688 Ok(e)
1689 }
1690
1691 // Parse all atomic expressions which don't have to worry about precedence
1692 // interactions, as they are fully contained.
1693 #[cfg(feature = "full")]
1694 fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
f035d41b
XL
1695 if input.peek(token::Group)
1696 && !input.peek2(Token![::])
1697 && !input.peek2(Token![!])
1698 && !input.peek2(token::Brace)
1699 {
e74abb32
XL
1700 input.call(expr_group).map(Expr::Group)
1701 } else if input.peek(Lit) {
1702 input.parse().map(Expr::Lit)
1703 } else if input.peek(Token![async])
1704 && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
1705 {
1706 input.call(expr_async).map(Expr::Async)
1707 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
1708 input.call(expr_try_block).map(Expr::TryBlock)
1709 } else if input.peek(Token![|])
1710 || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1711 || input.peek(Token![static])
1712 || input.peek(Token![move])
1713 {
1714 expr_closure(input, allow_struct).map(Expr::Closure)
1715 } else if input.peek(Ident)
1716 || input.peek(Token![::])
1717 || input.peek(Token![<])
1718 || input.peek(Token![self])
1719 || input.peek(Token![Self])
1720 || input.peek(Token![super])
e74abb32
XL
1721 || input.peek(Token![crate])
1722 {
1723 path_or_macro_or_struct(input, allow_struct)
1724 } else if input.peek(token::Paren) {
1725 paren_or_tuple(input)
1726 } else if input.peek(Token![break]) {
1727 expr_break(input, allow_struct).map(Expr::Break)
1728 } else if input.peek(Token![continue]) {
1729 input.call(expr_continue).map(Expr::Continue)
1730 } else if input.peek(Token![return]) {
1731 expr_ret(input, allow_struct).map(Expr::Return)
1732 } else if input.peek(token::Bracket) {
1733 array_or_repeat(input)
1734 } else if input.peek(Token![let]) {
1735 input.call(expr_let).map(Expr::Let)
1736 } else if input.peek(Token![if]) {
1737 input.parse().map(Expr::If)
1738 } else if input.peek(Token![while]) {
1739 input.parse().map(Expr::While)
1740 } else if input.peek(Token![for]) {
1741 input.parse().map(Expr::ForLoop)
1742 } else if input.peek(Token![loop]) {
1743 input.parse().map(Expr::Loop)
1744 } else if input.peek(Token![match]) {
1745 input.parse().map(Expr::Match)
1746 } else if input.peek(Token![yield]) {
1747 input.call(expr_yield).map(Expr::Yield)
1748 } else if input.peek(Token![unsafe]) {
1749 input.call(expr_unsafe).map(Expr::Unsafe)
5869c6ff
XL
1750 } else if input.peek(Token![const]) {
1751 input.call(expr_const).map(Expr::Verbatim)
e74abb32
XL
1752 } else if input.peek(token::Brace) {
1753 input.call(expr_block).map(Expr::Block)
1754 } else if input.peek(Token![..]) {
1755 expr_range(input, allow_struct).map(Expr::Range)
5869c6ff
XL
1756 } else if input.peek(Token![_]) {
1757 Ok(Expr::Verbatim(TokenStream::from(
1758 input.parse::<TokenTree>()?,
1759 )))
e74abb32
XL
1760 } else if input.peek(Lifetime) {
1761 let the_label: Label = input.parse()?;
1762 let mut expr = if input.peek(Token![while]) {
1763 Expr::While(input.parse()?)
1764 } else if input.peek(Token![for]) {
1765 Expr::ForLoop(input.parse()?)
1766 } else if input.peek(Token![loop]) {
1767 Expr::Loop(input.parse()?)
1768 } else if input.peek(token::Brace) {
1769 Expr::Block(input.call(expr_block)?)
1770 } else {
1771 return Err(input.error("expected loop or block expression"));
1772 };
1773 match &mut expr {
1774 Expr::While(ExprWhile { label, .. })
1775 | Expr::ForLoop(ExprForLoop { label, .. })
1776 | Expr::Loop(ExprLoop { label, .. })
1777 | Expr::Block(ExprBlock { label, .. }) => *label = Some(the_label),
1778 _ => unreachable!(),
1779 }
1780 Ok(expr)
1781 } else {
1782 Err(input.error("expected expression"))
1783 }
1784 }
1785
1786 #[cfg(not(feature = "full"))]
1787 fn atom_expr(input: ParseStream, _allow_struct: AllowStruct) -> Result<Expr> {
1788 if input.peek(Lit) {
1789 input.parse().map(Expr::Lit)
1790 } else if input.peek(token::Paren) {
1791 input.call(expr_paren).map(Expr::Paren)
1792 } else if input.peek(Ident)
1793 || input.peek(Token![::])
1794 || input.peek(Token![<])
1795 || input.peek(Token![self])
1796 || input.peek(Token![Self])
1797 || input.peek(Token![super])
e74abb32
XL
1798 || input.peek(Token![crate])
1799 {
1800 input.parse().map(Expr::Path)
1801 } else {
1802 Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
1803 }
1804 }
1805
1806 #[cfg(feature = "full")]
1807 fn path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1808 let expr: ExprPath = input.parse()?;
1809 if expr.qself.is_some() {
1810 return Ok(Expr::Path(expr));
1811 }
1812
1813 if input.peek(Token![!]) && !input.peek(Token![!=]) {
1814 let mut contains_arguments = false;
1815 for segment in &expr.path.segments {
1816 match segment.arguments {
1817 PathArguments::None => {}
1818 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
1819 contains_arguments = true;
1820 }
1821 }
1822 }
1823
1824 if !contains_arguments {
1825 let bang_token: Token![!] = input.parse()?;
1826 let (delimiter, tokens) = mac::parse_delimiter(input)?;
1827 return Ok(Expr::Macro(ExprMacro {
1828 attrs: Vec::new(),
1829 mac: Macro {
1830 path: expr.path,
1831 bang_token,
1832 delimiter,
1833 tokens,
1834 },
1835 }));
1836 }
1837 }
1838
1839 if allow_struct.0 && input.peek(token::Brace) {
1840 let outer_attrs = Vec::new();
1841 expr_struct_helper(input, outer_attrs, expr.path).map(Expr::Struct)
1842 } else {
1843 Ok(Expr::Path(expr))
1844 }
1845 }
1846
1847 #[cfg(feature = "full")]
1848 fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
1849 let content;
1850 let paren_token = parenthesized!(content in input);
1851 let inner_attrs = content.call(Attribute::parse_inner)?;
1852 if content.is_empty() {
1853 return Ok(Expr::Tuple(ExprTuple {
1854 attrs: inner_attrs,
1855 paren_token,
1856 elems: Punctuated::new(),
1857 }));
1858 }
1859
1860 let first: Expr = content.parse()?;
1861 if content.is_empty() {
1862 return Ok(Expr::Paren(ExprParen {
1863 attrs: inner_attrs,
1864 paren_token,
1865 expr: Box::new(first),
1866 }));
1867 }
1868
1869 let mut elems = Punctuated::new();
1870 elems.push_value(first);
1871 while !content.is_empty() {
1872 let punct = content.parse()?;
1873 elems.push_punct(punct);
1874 if content.is_empty() {
1875 break;
1876 }
1877 let value = content.parse()?;
1878 elems.push_value(value);
1879 }
1880 Ok(Expr::Tuple(ExprTuple {
1881 attrs: inner_attrs,
1882 paren_token,
1883 elems,
1884 }))
1885 }
1886
1887 #[cfg(feature = "full")]
1888 fn array_or_repeat(input: ParseStream) -> Result<Expr> {
1889 let content;
1890 let bracket_token = bracketed!(content in input);
1891 let inner_attrs = content.call(Attribute::parse_inner)?;
1892 if content.is_empty() {
1893 return Ok(Expr::Array(ExprArray {
1894 attrs: inner_attrs,
1895 bracket_token,
1896 elems: Punctuated::new(),
1897 }));
1898 }
1899
1900 let first: Expr = content.parse()?;
1901 if content.is_empty() || content.peek(Token![,]) {
1902 let mut elems = Punctuated::new();
1903 elems.push_value(first);
1904 while !content.is_empty() {
1905 let punct = content.parse()?;
1906 elems.push_punct(punct);
1907 if content.is_empty() {
1908 break;
1909 }
1910 let value = content.parse()?;
1911 elems.push_value(value);
1912 }
1913 Ok(Expr::Array(ExprArray {
1914 attrs: inner_attrs,
1915 bracket_token,
1916 elems,
1917 }))
1918 } else if content.peek(Token![;]) {
1919 let semi_token: Token![;] = content.parse()?;
1920 let len: Expr = content.parse()?;
1921 Ok(Expr::Repeat(ExprRepeat {
1922 attrs: inner_attrs,
1923 bracket_token,
1924 expr: Box::new(first),
1925 semi_token,
1926 len: Box::new(len),
1927 }))
1928 } else {
1929 Err(content.error("expected `,` or `;`"))
1930 }
1931 }
1932
1933 #[cfg(feature = "full")]
1934 pub(crate) fn expr_early(input: ParseStream) -> Result<Expr> {
f035d41b 1935 let mut attrs = input.call(expr_attrs)?;
e74abb32
XL
1936 let mut expr = if input.peek(Token![if]) {
1937 Expr::If(input.parse()?)
1938 } else if input.peek(Token![while]) {
1939 Expr::While(input.parse()?)
1940 } else if input.peek(Token![for]) {
1941 Expr::ForLoop(input.parse()?)
1942 } else if input.peek(Token![loop]) {
1943 Expr::Loop(input.parse()?)
1944 } else if input.peek(Token![match]) {
1945 Expr::Match(input.parse()?)
1946 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
1947 Expr::TryBlock(input.call(expr_try_block)?)
1948 } else if input.peek(Token![unsafe]) {
1949 Expr::Unsafe(input.call(expr_unsafe)?)
5869c6ff
XL
1950 } else if input.peek(Token![const]) {
1951 Expr::Verbatim(input.call(expr_const)?)
e74abb32
XL
1952 } else if input.peek(token::Brace) {
1953 Expr::Block(input.call(expr_block)?)
1954 } else {
1955 let allow_struct = AllowStruct(true);
1956 let mut expr = unary_expr(input, allow_struct)?;
1957
1958 attrs.extend(expr.replace_attrs(Vec::new()));
1959 expr.replace_attrs(attrs);
1960
1961 return parse_expr(input, expr, allow_struct, Precedence::Any);
1962 };
1963
f035d41b 1964 if input.peek(Token![.]) && !input.peek(Token![..]) || input.peek(Token![?]) {
e74abb32
XL
1965 expr = trailer_helper(input, expr)?;
1966
1967 attrs.extend(expr.replace_attrs(Vec::new()));
1968 expr.replace_attrs(attrs);
1969
1970 let allow_struct = AllowStruct(true);
1971 return parse_expr(input, expr, allow_struct, Precedence::Any);
1972 }
1973
1974 attrs.extend(expr.replace_attrs(Vec::new()));
1975 expr.replace_attrs(attrs);
1976 Ok(expr)
1977 }
1978
5869c6ff 1979 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
e74abb32
XL
1980 impl Parse for ExprLit {
1981 fn parse(input: ParseStream) -> Result<Self> {
1982 Ok(ExprLit {
1983 attrs: Vec::new(),
1984 lit: input.parse()?,
1985 })
1986 }
1987 }
1988
1989 #[cfg(feature = "full")]
1990 fn expr_group(input: ParseStream) -> Result<ExprGroup> {
1991 let group = crate::group::parse_group(input)?;
1992 Ok(ExprGroup {
1993 attrs: Vec::new(),
1994 group_token: group.token,
1995 expr: group.content.parse()?,
1996 })
1997 }
1998
1999 #[cfg(not(feature = "full"))]
2000 fn expr_paren(input: ParseStream) -> Result<ExprParen> {
2001 let content;
2002 Ok(ExprParen {
2003 attrs: Vec::new(),
2004 paren_token: parenthesized!(content in input),
2005 expr: content.parse()?,
2006 })
2007 }
2008
2009 #[cfg(feature = "full")]
2010 fn generic_method_argument(input: ParseStream) -> Result<GenericMethodArgument> {
f035d41b
XL
2011 if input.peek(Lit) {
2012 let lit = input.parse()?;
2013 return Ok(GenericMethodArgument::Const(Expr::Lit(lit)));
2014 }
2015
2016 if input.peek(token::Brace) {
2017 let block = input.call(expr::parsing::expr_block)?;
2018 return Ok(GenericMethodArgument::Const(Expr::Block(block)));
2019 }
2020
e74abb32
XL
2021 input.parse().map(GenericMethodArgument::Type)
2022 }
2023
2024 #[cfg(feature = "full")]
2025 fn expr_let(input: ParseStream) -> Result<ExprLet> {
2026 Ok(ExprLet {
2027 attrs: Vec::new(),
2028 let_token: input.parse()?,
f035d41b 2029 pat: pat::parsing::multi_pat_with_leading_vert(input)?,
e74abb32 2030 eq_token: input.parse()?,
f035d41b 2031 expr: Box::new(input.call(Expr::parse_without_eager_brace)?),
e74abb32
XL
2032 })
2033 }
2034
2035 #[cfg(feature = "full")]
5869c6ff 2036 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
e74abb32
XL
2037 impl Parse for ExprIf {
2038 fn parse(input: ParseStream) -> Result<Self> {
f035d41b 2039 let attrs = input.call(Attribute::parse_outer)?;
e74abb32 2040 Ok(ExprIf {
f035d41b 2041 attrs,
e74abb32 2042 if_token: input.parse()?,
f035d41b 2043 cond: Box::new(input.call(Expr::parse_without_eager_brace)?),
e74abb32
XL
2044 then_branch: input.parse()?,
2045 else_branch: {
2046 if input.peek(Token![else]) {
2047 Some(input.call(else_block)?)
2048 } else {
2049 None
2050 }
2051 },
2052 })
2053 }
2054 }
2055
2056 #[cfg(feature = "full")]
2057 fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
2058 let else_token: Token![else] = input.parse()?;
2059
2060 let lookahead = input.lookahead1();
2061 let else_branch = if input.peek(Token![if]) {
2062 input.parse().map(Expr::If)?
2063 } else if input.peek(token::Brace) {
2064 Expr::Block(ExprBlock {
2065 attrs: Vec::new(),
2066 label: None,
2067 block: input.parse()?,
2068 })
2069 } else {
2070 return Err(lookahead.error());
2071 };
2072
2073 Ok((else_token, Box::new(else_branch)))
2074 }
2075
2076 #[cfg(feature = "full")]
5869c6ff 2077 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
e74abb32
XL
2078 impl Parse for ExprForLoop {
2079 fn parse(input: ParseStream) -> Result<Self> {
f035d41b 2080 let outer_attrs = input.call(Attribute::parse_outer)?;
e74abb32
XL
2081 let label: Option<Label> = input.parse()?;
2082 let for_token: Token![for] = input.parse()?;
2083
f035d41b 2084 let pat = pat::parsing::multi_pat_with_leading_vert(input)?;
e74abb32
XL
2085
2086 let in_token: Token![in] = input.parse()?;
f035d41b 2087 let expr: Expr = input.call(Expr::parse_without_eager_brace)?;
e74abb32
XL
2088
2089 let content;
2090 let brace_token = braced!(content in input);
2091 let inner_attrs = content.call(Attribute::parse_inner)?;
2092 let stmts = content.call(Block::parse_within)?;
2093
2094 Ok(ExprForLoop {
f035d41b 2095 attrs: private::attrs(outer_attrs, inner_attrs),
e74abb32
XL
2096 label,
2097 for_token,
2098 pat,
2099 in_token,
2100 expr: Box::new(expr),
2101 body: Block { brace_token, stmts },
2102 })
2103 }
2104 }
2105
2106 #[cfg(feature = "full")]
5869c6ff 2107 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
e74abb32
XL
2108 impl Parse for ExprLoop {
2109 fn parse(input: ParseStream) -> Result<Self> {
f035d41b 2110 let outer_attrs = input.call(Attribute::parse_outer)?;
e74abb32
XL
2111 let label: Option<Label> = input.parse()?;
2112 let loop_token: Token![loop] = input.parse()?;
2113
2114 let content;
2115 let brace_token = braced!(content in input);
2116 let inner_attrs = content.call(Attribute::parse_inner)?;
2117 let stmts = content.call(Block::parse_within)?;
2118
2119 Ok(ExprLoop {
f035d41b 2120 attrs: private::attrs(outer_attrs, inner_attrs),
e74abb32
XL
2121 label,
2122 loop_token,
2123 body: Block { brace_token, stmts },
2124 })
2125 }
2126 }
2127
2128 #[cfg(feature = "full")]
5869c6ff 2129 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
e74abb32
XL
2130 impl Parse for ExprMatch {
2131 fn parse(input: ParseStream) -> Result<Self> {
f035d41b 2132 let outer_attrs = input.call(Attribute::parse_outer)?;
e74abb32 2133 let match_token: Token![match] = input.parse()?;
f035d41b 2134 let expr = Expr::parse_without_eager_brace(input)?;
e74abb32
XL
2135
2136 let content;
2137 let brace_token = braced!(content in input);
2138 let inner_attrs = content.call(Attribute::parse_inner)?;
2139
2140 let mut arms = Vec::new();
2141 while !content.is_empty() {
2142 arms.push(content.call(Arm::parse)?);
2143 }
2144
2145 Ok(ExprMatch {
f035d41b 2146 attrs: private::attrs(outer_attrs, inner_attrs),
e74abb32
XL
2147 match_token,
2148 expr: Box::new(expr),
2149 brace_token,
2150 arms,
2151 })
2152 }
2153 }
2154
2155 macro_rules! impl_by_parsing_expr {
2156 (
2157 $(
2158 $expr_type:ty, $variant:ident, $msg:expr,
2159 )*
2160 ) => {
2161 $(
2162 #[cfg(all(feature = "full", feature = "printing"))]
5869c6ff 2163 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
e74abb32
XL
2164 impl Parse for $expr_type {
2165 fn parse(input: ParseStream) -> Result<Self> {
2166 let mut expr: Expr = input.parse()?;
2167 loop {
2168 match expr {
2169 Expr::$variant(inner) => return Ok(inner),
2170 Expr::Group(next) => expr = *next.expr,
2171 _ => return Err(Error::new_spanned(expr, $msg)),
2172 }
2173 }
2174 }
2175 }
2176 )*
2177 };
2178 }
2179
2180 impl_by_parsing_expr! {
2181 ExprBox, Box, "expected box expression",
2182 ExprArray, Array, "expected slice literal expression",
2183 ExprCall, Call, "expected function call expression",
2184 ExprMethodCall, MethodCall, "expected method call expression",
2185 ExprTuple, Tuple, "expected tuple expression",
2186 ExprBinary, Binary, "expected binary operation",
2187 ExprUnary, Unary, "expected unary operation",
2188 ExprCast, Cast, "expected cast expression",
2189 ExprType, Type, "expected type ascription expression",
2190 ExprLet, Let, "expected let guard",
2191 ExprClosure, Closure, "expected closure expression",
2192 ExprUnsafe, Unsafe, "expected unsafe block",
2193 ExprBlock, Block, "expected blocked scope",
2194 ExprAssign, Assign, "expected assignment expression",
2195 ExprAssignOp, AssignOp, "expected compound assignment expression",
2196 ExprField, Field, "expected struct field access",
2197 ExprIndex, Index, "expected indexing expression",
2198 ExprRange, Range, "expected range expression",
2199 ExprReference, Reference, "expected referencing operation",
2200 ExprBreak, Break, "expected break expression",
2201 ExprContinue, Continue, "expected continue expression",
2202 ExprReturn, Return, "expected return expression",
2203 ExprMacro, Macro, "expected macro invocation expression",
2204 ExprStruct, Struct, "expected struct literal expression",
2205 ExprRepeat, Repeat, "expected array literal constructed from one repeated element",
2206 ExprParen, Paren, "expected parenthesized expression",
2207 ExprTry, Try, "expected try expression",
2208 ExprAsync, Async, "expected async block",
2209 ExprTryBlock, TryBlock, "expected try block",
2210 ExprYield, Yield, "expected yield expression",
2211 }
2212
2213 #[cfg(feature = "full")]
2214 fn expr_try_block(input: ParseStream) -> Result<ExprTryBlock> {
2215 Ok(ExprTryBlock {
2216 attrs: Vec::new(),
2217 try_token: input.parse()?,
2218 block: input.parse()?,
2219 })
2220 }
2221
2222 #[cfg(feature = "full")]
2223 fn expr_yield(input: ParseStream) -> Result<ExprYield> {
2224 Ok(ExprYield {
2225 attrs: Vec::new(),
2226 yield_token: input.parse()?,
2227 expr: {
2228 if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
2229 Some(input.parse()?)
2230 } else {
2231 None
2232 }
2233 },
2234 })
2235 }
2236
2237 #[cfg(feature = "full")]
2238 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
2239 let asyncness: Option<Token![async]> = input.parse()?;
2240 let movability: Option<Token![static]> = if asyncness.is_none() {
2241 input.parse()?
2242 } else {
2243 None
2244 };
2245 let capture: Option<Token![move]> = input.parse()?;
2246 let or1_token: Token![|] = input.parse()?;
2247
2248 let mut inputs = Punctuated::new();
2249 loop {
2250 if input.peek(Token![|]) {
2251 break;
2252 }
2253 let value = closure_arg(input)?;
2254 inputs.push_value(value);
2255 if input.peek(Token![|]) {
2256 break;
2257 }
2258 let punct: Token![,] = input.parse()?;
2259 inputs.push_punct(punct);
2260 }
2261
2262 let or2_token: Token![|] = input.parse()?;
2263
2264 let (output, body) = if input.peek(Token![->]) {
2265 let arrow_token: Token![->] = input.parse()?;
2266 let ty: Type = input.parse()?;
2267 let body: Block = input.parse()?;
2268 let output = ReturnType::Type(arrow_token, Box::new(ty));
2269 let block = Expr::Block(ExprBlock {
2270 attrs: Vec::new(),
2271 label: None,
2272 block: body,
2273 });
2274 (output, block)
2275 } else {
2276 let body = ambiguous_expr(input, allow_struct)?;
2277 (ReturnType::Default, body)
2278 };
2279
2280 Ok(ExprClosure {
2281 attrs: Vec::new(),
2282 asyncness,
2283 movability,
2284 capture,
2285 or1_token,
2286 inputs,
2287 or2_token,
2288 output,
2289 body: Box::new(body),
2290 })
2291 }
2292
2293 #[cfg(feature = "full")]
2294 fn expr_async(input: ParseStream) -> Result<ExprAsync> {
2295 Ok(ExprAsync {
2296 attrs: Vec::new(),
2297 async_token: input.parse()?,
2298 capture: input.parse()?,
2299 block: input.parse()?,
2300 })
2301 }
2302
2303 #[cfg(feature = "full")]
2304 fn closure_arg(input: ParseStream) -> Result<Pat> {
2305 let attrs = input.call(Attribute::parse_outer)?;
2306 let mut pat: Pat = input.parse()?;
2307
2308 if input.peek(Token![:]) {
2309 Ok(Pat::Type(PatType {
2310 attrs,
2311 pat: Box::new(pat),
2312 colon_token: input.parse()?,
2313 ty: input.parse()?,
2314 }))
2315 } else {
2316 match &mut pat {
2317 Pat::Box(pat) => pat.attrs = attrs,
2318 Pat::Ident(pat) => pat.attrs = attrs,
2319 Pat::Lit(pat) => pat.attrs = attrs,
2320 Pat::Macro(pat) => pat.attrs = attrs,
2321 Pat::Or(pat) => pat.attrs = attrs,
2322 Pat::Path(pat) => pat.attrs = attrs,
2323 Pat::Range(pat) => pat.attrs = attrs,
2324 Pat::Reference(pat) => pat.attrs = attrs,
2325 Pat::Rest(pat) => pat.attrs = attrs,
2326 Pat::Slice(pat) => pat.attrs = attrs,
2327 Pat::Struct(pat) => pat.attrs = attrs,
2328 Pat::Tuple(pat) => pat.attrs = attrs,
2329 Pat::TupleStruct(pat) => pat.attrs = attrs,
2330 Pat::Type(_) => unreachable!(),
2331 Pat::Verbatim(_) => {}
2332 Pat::Wild(pat) => pat.attrs = attrs,
6a06907d
XL
2333
2334 #[cfg(test)]
2335 Pat::__TestExhaustive(_) => unimplemented!(),
2336 #[cfg(not(test))]
2337 _ => unreachable!(),
e74abb32
XL
2338 }
2339 Ok(pat)
2340 }
2341 }
2342
2343 #[cfg(feature = "full")]
5869c6ff 2344 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
e74abb32
XL
2345 impl Parse for ExprWhile {
2346 fn parse(input: ParseStream) -> Result<Self> {
f035d41b 2347 let outer_attrs = input.call(Attribute::parse_outer)?;
e74abb32
XL
2348 let label: Option<Label> = input.parse()?;
2349 let while_token: Token![while] = input.parse()?;
f035d41b 2350 let cond = Expr::parse_without_eager_brace(input)?;
e74abb32
XL
2351
2352 let content;
2353 let brace_token = braced!(content in input);
2354 let inner_attrs = content.call(Attribute::parse_inner)?;
2355 let stmts = content.call(Block::parse_within)?;
2356
2357 Ok(ExprWhile {
f035d41b 2358 attrs: private::attrs(outer_attrs, inner_attrs),
e74abb32
XL
2359 label,
2360 while_token,
2361 cond: Box::new(cond),
2362 body: Block { brace_token, stmts },
2363 })
2364 }
2365 }
2366
2367 #[cfg(feature = "full")]
5869c6ff 2368 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
e74abb32
XL
2369 impl Parse for Label {
2370 fn parse(input: ParseStream) -> Result<Self> {
2371 Ok(Label {
2372 name: input.parse()?,
2373 colon_token: input.parse()?,
2374 })
2375 }
2376 }
2377
2378 #[cfg(feature = "full")]
5869c6ff 2379 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
e74abb32
XL
2380 impl Parse for Option<Label> {
2381 fn parse(input: ParseStream) -> Result<Self> {
2382 if input.peek(Lifetime) {
2383 input.parse().map(Some)
2384 } else {
2385 Ok(None)
2386 }
2387 }
2388 }
2389
2390 #[cfg(feature = "full")]
2391 fn expr_continue(input: ParseStream) -> Result<ExprContinue> {
2392 Ok(ExprContinue {
2393 attrs: Vec::new(),
2394 continue_token: input.parse()?,
2395 label: input.parse()?,
2396 })
2397 }
2398
2399 #[cfg(feature = "full")]
2400 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2401 Ok(ExprBreak {
2402 attrs: Vec::new(),
2403 break_token: input.parse()?,
2404 label: input.parse()?,
2405 expr: {
2406 if input.is_empty()
2407 || input.peek(Token![,])
2408 || input.peek(Token![;])
2409 || !allow_struct.0 && input.peek(token::Brace)
2410 {
2411 None
2412 } else {
2413 let expr = ambiguous_expr(input, allow_struct)?;
2414 Some(Box::new(expr))
2415 }
2416 },
2417 })
2418 }
2419
2420 #[cfg(feature = "full")]
2421 fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
2422 Ok(ExprReturn {
2423 attrs: Vec::new(),
2424 return_token: input.parse()?,
2425 expr: {
2426 if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
2427 None
2428 } else {
2429 // NOTE: return is greedy and eats blocks after it even when in a
2430 // position where structs are not allowed, such as in if statement
2431 // conditions. For example:
2432 //
2433 // if return { println!("A") } {} // Prints "A"
2434 let expr = ambiguous_expr(input, allow_struct)?;
2435 Some(Box::new(expr))
2436 }
2437 },
2438 })
2439 }
2440
2441 #[cfg(feature = "full")]
5869c6ff 2442 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
e74abb32
XL
2443 impl Parse for FieldValue {
2444 fn parse(input: ParseStream) -> Result<Self> {
f035d41b 2445 let attrs = input.call(Attribute::parse_outer)?;
e74abb32
XL
2446 let member: Member = input.parse()?;
2447 let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
2448 let colon_token: Token![:] = input.parse()?;
2449 let value: Expr = input.parse()?;
2450 (Some(colon_token), value)
2451 } else if let Member::Named(ident) = &member {
2452 let value = Expr::Path(ExprPath {
2453 attrs: Vec::new(),
2454 qself: None,
2455 path: Path::from(ident.clone()),
2456 });
2457 (None, value)
2458 } else {
2459 unreachable!()
2460 };
2461
2462 Ok(FieldValue {
f035d41b 2463 attrs,
e74abb32
XL
2464 member,
2465 colon_token,
2466 expr: value,
2467 })
2468 }
2469 }
2470
2471 #[cfg(feature = "full")]
2472 fn expr_struct_helper(
2473 input: ParseStream,
2474 outer_attrs: Vec<Attribute>,
2475 path: Path,
2476 ) -> Result<ExprStruct> {
2477 let content;
2478 let brace_token = braced!(content in input);
2479 let inner_attrs = content.call(Attribute::parse_inner)?;
f035d41b 2480 let attrs = private::attrs(outer_attrs, inner_attrs);
e74abb32
XL
2481
2482 let mut fields = Punctuated::new();
f035d41b
XL
2483 while !content.is_empty() {
2484 if content.peek(Token![..]) {
2485 return Ok(ExprStruct {
2486 attrs,
2487 brace_token,
2488 path,
2489 fields,
2490 dot2_token: Some(content.parse()?),
5869c6ff
XL
2491 rest: if content.is_empty() {
2492 None
2493 } else {
2494 Some(Box::new(content.parse()?))
2495 },
f035d41b 2496 });
e74abb32
XL
2497 }
2498
f035d41b
XL
2499 fields.push(content.parse()?);
2500 if content.is_empty() {
e74abb32
XL
2501 break;
2502 }
2503 let punct: Token![,] = content.parse()?;
2504 fields.push_punct(punct);
2505 }
2506
e74abb32 2507 Ok(ExprStruct {
f035d41b 2508 attrs,
e74abb32
XL
2509 brace_token,
2510 path,
2511 fields,
f035d41b
XL
2512 dot2_token: None,
2513 rest: None,
e74abb32
XL
2514 })
2515 }
2516
2517 #[cfg(feature = "full")]
2518 fn expr_unsafe(input: ParseStream) -> Result<ExprUnsafe> {
2519 let unsafe_token: Token![unsafe] = input.parse()?;
2520
2521 let content;
2522 let brace_token = braced!(content in input);
2523 let inner_attrs = content.call(Attribute::parse_inner)?;
2524 let stmts = content.call(Block::parse_within)?;
2525
2526 Ok(ExprUnsafe {
2527 attrs: inner_attrs,
2528 unsafe_token,
2529 block: Block { brace_token, stmts },
2530 })
2531 }
2532
5869c6ff
XL
2533 #[cfg(feature = "full")]
2534 pub(crate) fn expr_const(input: ParseStream) -> Result<TokenStream> {
2535 let begin = input.fork();
2536 input.parse::<Token![const]>()?;
2537
2538 let content;
2539 braced!(content in input);
2540 content.call(Attribute::parse_inner)?;
2541 content.call(Block::parse_within)?;
2542
2543 Ok(verbatim::between(begin, input))
2544 }
2545
e74abb32
XL
2546 #[cfg(feature = "full")]
2547 pub fn expr_block(input: ParseStream) -> Result<ExprBlock> {
2548 let label: Option<Label> = input.parse()?;
2549
2550 let content;
2551 let brace_token = braced!(content in input);
2552 let inner_attrs = content.call(Attribute::parse_inner)?;
2553 let stmts = content.call(Block::parse_within)?;
2554
2555 Ok(ExprBlock {
2556 attrs: inner_attrs,
2557 label,
2558 block: Block { brace_token, stmts },
2559 })
2560 }
2561
2562 #[cfg(feature = "full")]
2563 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2564 Ok(ExprRange {
2565 attrs: Vec::new(),
2566 from: None,
2567 limits: input.parse()?,
2568 to: {
2569 if input.is_empty()
2570 || input.peek(Token![,])
2571 || input.peek(Token![;])
2572 || !allow_struct.0 && input.peek(token::Brace)
2573 {
2574 None
2575 } else {
2576 let to = ambiguous_expr(input, allow_struct)?;
2577 Some(Box::new(to))
2578 }
2579 },
2580 })
2581 }
2582
2583 #[cfg(feature = "full")]
5869c6ff 2584 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
e74abb32
XL
2585 impl Parse for RangeLimits {
2586 fn parse(input: ParseStream) -> Result<Self> {
2587 let lookahead = input.lookahead1();
2588 if lookahead.peek(Token![..=]) {
2589 input.parse().map(RangeLimits::Closed)
2590 } else if lookahead.peek(Token![...]) {
2591 let dot3: Token![...] = input.parse()?;
2592 Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2593 } else if lookahead.peek(Token![..]) {
2594 input.parse().map(RangeLimits::HalfOpen)
2595 } else {
2596 Err(lookahead.error())
2597 }
2598 }
2599 }
2600
5869c6ff 2601 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
e74abb32
XL
2602 impl Parse for ExprPath {
2603 fn parse(input: ParseStream) -> Result<Self> {
2604 #[cfg(not(feature = "full"))]
2605 let attrs = Vec::new();
2606 #[cfg(feature = "full")]
2607 let attrs = input.call(Attribute::parse_outer)?;
2608
2609 let (qself, path) = path::parsing::qpath(input, true)?;
2610
2611 Ok(ExprPath { attrs, qself, path })
2612 }
2613 }
2614
5869c6ff 2615 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
e74abb32
XL
2616 impl Parse for Member {
2617 fn parse(input: ParseStream) -> Result<Self> {
2618 if input.peek(Ident) {
2619 input.parse().map(Member::Named)
2620 } else if input.peek(LitInt) {
2621 input.parse().map(Member::Unnamed)
2622 } else {
2623 Err(input.error("expected identifier or integer"))
2624 }
2625 }
2626 }
2627
2628 #[cfg(feature = "full")]
5869c6ff 2629 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
e74abb32
XL
2630 impl Parse for Arm {
2631 fn parse(input: ParseStream) -> Result<Arm> {
2632 let requires_comma;
2633 Ok(Arm {
2634 attrs: input.call(Attribute::parse_outer)?,
f035d41b 2635 pat: pat::parsing::multi_pat_with_leading_vert(input)?,
e74abb32
XL
2636 guard: {
2637 if input.peek(Token![if]) {
2638 let if_token: Token![if] = input.parse()?;
2639 let guard: Expr = input.parse()?;
2640 Some((if_token, Box::new(guard)))
2641 } else {
2642 None
2643 }
2644 },
2645 fat_arrow_token: input.parse()?,
2646 body: {
2647 let body = input.call(expr_early)?;
2648 requires_comma = requires_terminator(&body);
2649 Box::new(body)
2650 },
2651 comma: {
2652 if requires_comma && !input.is_empty() {
2653 Some(input.parse()?)
2654 } else {
2655 input.parse()?
2656 }
2657 },
2658 })
2659 }
2660 }
2661
5869c6ff 2662 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
e74abb32
XL
2663 impl Parse for Index {
2664 fn parse(input: ParseStream) -> Result<Self> {
2665 let lit: LitInt = input.parse()?;
2666 if lit.suffix().is_empty() {
2667 Ok(Index {
2668 index: lit
2669 .base10_digits()
2670 .parse()
2671 .map_err(|err| Error::new(lit.span(), err))?,
2672 span: lit.span(),
2673 })
2674 } else {
2675 Err(Error::new(lit.span(), "expected unsuffixed integer"))
2676 }
2677 }
2678 }
2679
3dfed10e
XL
2680 fn multi_index(e: &mut Expr, dot_token: &mut Token![.], float: LitFloat) -> Result<bool> {
2681 let mut float_repr = float.to_string();
2682 let trailing_dot = float_repr.ends_with('.');
2683 if trailing_dot {
2684 float_repr.truncate(float_repr.len() - 1);
2685 }
2686 for part in float_repr.split('.') {
f035d41b 2687 let index = crate::parse_str(part).map_err(|err| Error::new(float.span(), err))?;
5869c6ff 2688 let base = mem::replace(e, Expr::__TestExhaustive(crate::private(())));
3dfed10e 2689 *e = Expr::Field(ExprField {
f035d41b 2690 attrs: Vec::new(),
3dfed10e
XL
2691 base: Box::new(base),
2692 dot_token: Token![.](dot_token.span),
f035d41b
XL
2693 member: Member::Unnamed(index),
2694 });
3dfed10e 2695 *dot_token = Token![.](float.span());
f035d41b 2696 }
3dfed10e 2697 Ok(!trailing_dot)
f035d41b
XL
2698 }
2699
e74abb32
XL
2700 #[cfg(feature = "full")]
2701 impl Member {
2702 fn is_named(&self) -> bool {
2703 match *self {
2704 Member::Named(_) => true,
2705 Member::Unnamed(_) => false,
2706 }
2707 }
2708 }
2709}
2710
2711#[cfg(feature = "printing")]
2712pub(crate) mod printing {
2713 use super::*;
e74abb32
XL
2714 #[cfg(feature = "full")]
2715 use crate::attr::FilterAttrs;
29967ef6
XL
2716 use proc_macro2::{Literal, TokenStream};
2717 use quote::{ToTokens, TokenStreamExt};
e74abb32
XL
2718
2719 // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
2720 // before appending it to `TokenStream`.
2721 #[cfg(feature = "full")]
2722 fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) {
2723 if let Expr::Struct(_) = *e {
2724 token::Paren::default().surround(tokens, |tokens| {
2725 e.to_tokens(tokens);
2726 });
2727 } else {
2728 e.to_tokens(tokens);
2729 }
2730 }
2731
2732 #[cfg(feature = "full")]
2733 pub(crate) fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
2734 tokens.append_all(attrs.outer());
2735 }
2736
2737 #[cfg(feature = "full")]
2738 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
2739 tokens.append_all(attrs.inner());
2740 }
2741
2742 #[cfg(not(feature = "full"))]
2743 pub(crate) fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
2744
2745 #[cfg(not(feature = "full"))]
2746 fn inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
2747
2748 #[cfg(feature = "full")]
5869c6ff 2749 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
2750 impl ToTokens for ExprBox {
2751 fn to_tokens(&self, tokens: &mut TokenStream) {
2752 outer_attrs_to_tokens(&self.attrs, tokens);
2753 self.box_token.to_tokens(tokens);
2754 self.expr.to_tokens(tokens);
2755 }
2756 }
2757
2758 #[cfg(feature = "full")]
5869c6ff 2759 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
2760 impl ToTokens for ExprArray {
2761 fn to_tokens(&self, tokens: &mut TokenStream) {
2762 outer_attrs_to_tokens(&self.attrs, tokens);
2763 self.bracket_token.surround(tokens, |tokens| {
2764 inner_attrs_to_tokens(&self.attrs, tokens);
2765 self.elems.to_tokens(tokens);
2766 })
2767 }
2768 }
2769
5869c6ff 2770 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
2771 impl ToTokens for ExprCall {
2772 fn to_tokens(&self, tokens: &mut TokenStream) {
2773 outer_attrs_to_tokens(&self.attrs, tokens);
2774 self.func.to_tokens(tokens);
2775 self.paren_token.surround(tokens, |tokens| {
2776 self.args.to_tokens(tokens);
2777 })
2778 }
2779 }
2780
2781 #[cfg(feature = "full")]
5869c6ff 2782 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
2783 impl ToTokens for ExprMethodCall {
2784 fn to_tokens(&self, tokens: &mut TokenStream) {
2785 outer_attrs_to_tokens(&self.attrs, tokens);
2786 self.receiver.to_tokens(tokens);
2787 self.dot_token.to_tokens(tokens);
2788 self.method.to_tokens(tokens);
2789 self.turbofish.to_tokens(tokens);
2790 self.paren_token.surround(tokens, |tokens| {
2791 self.args.to_tokens(tokens);
2792 });
2793 }
2794 }
2795
2796 #[cfg(feature = "full")]
5869c6ff 2797 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
2798 impl ToTokens for MethodTurbofish {
2799 fn to_tokens(&self, tokens: &mut TokenStream) {
2800 self.colon2_token.to_tokens(tokens);
2801 self.lt_token.to_tokens(tokens);
2802 self.args.to_tokens(tokens);
2803 self.gt_token.to_tokens(tokens);
2804 }
2805 }
2806
2807 #[cfg(feature = "full")]
5869c6ff 2808 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
2809 impl ToTokens for GenericMethodArgument {
2810 fn to_tokens(&self, tokens: &mut TokenStream) {
2811 match self {
2812 GenericMethodArgument::Type(t) => t.to_tokens(tokens),
2813 GenericMethodArgument::Const(c) => c.to_tokens(tokens),
2814 }
2815 }
2816 }
2817
2818 #[cfg(feature = "full")]
5869c6ff 2819 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
2820 impl ToTokens for ExprTuple {
2821 fn to_tokens(&self, tokens: &mut TokenStream) {
2822 outer_attrs_to_tokens(&self.attrs, tokens);
2823 self.paren_token.surround(tokens, |tokens| {
2824 inner_attrs_to_tokens(&self.attrs, tokens);
2825 self.elems.to_tokens(tokens);
2826 // If we only have one argument, we need a trailing comma to
2827 // distinguish ExprTuple from ExprParen.
2828 if self.elems.len() == 1 && !self.elems.trailing_punct() {
2829 <Token![,]>::default().to_tokens(tokens);
2830 }
2831 })
2832 }
2833 }
2834
5869c6ff 2835 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
2836 impl ToTokens for ExprBinary {
2837 fn to_tokens(&self, tokens: &mut TokenStream) {
2838 outer_attrs_to_tokens(&self.attrs, tokens);
2839 self.left.to_tokens(tokens);
2840 self.op.to_tokens(tokens);
2841 self.right.to_tokens(tokens);
2842 }
2843 }
2844
5869c6ff 2845 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
2846 impl ToTokens for ExprUnary {
2847 fn to_tokens(&self, tokens: &mut TokenStream) {
2848 outer_attrs_to_tokens(&self.attrs, tokens);
2849 self.op.to_tokens(tokens);
2850 self.expr.to_tokens(tokens);
2851 }
2852 }
2853
5869c6ff 2854 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
2855 impl ToTokens for ExprLit {
2856 fn to_tokens(&self, tokens: &mut TokenStream) {
2857 outer_attrs_to_tokens(&self.attrs, tokens);
2858 self.lit.to_tokens(tokens);
2859 }
2860 }
2861
5869c6ff 2862 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
2863 impl ToTokens for ExprCast {
2864 fn to_tokens(&self, tokens: &mut TokenStream) {
2865 outer_attrs_to_tokens(&self.attrs, tokens);
2866 self.expr.to_tokens(tokens);
2867 self.as_token.to_tokens(tokens);
2868 self.ty.to_tokens(tokens);
2869 }
2870 }
2871
2872 #[cfg(feature = "full")]
5869c6ff 2873 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
2874 impl ToTokens for ExprType {
2875 fn to_tokens(&self, tokens: &mut TokenStream) {
2876 outer_attrs_to_tokens(&self.attrs, tokens);
2877 self.expr.to_tokens(tokens);
2878 self.colon_token.to_tokens(tokens);
2879 self.ty.to_tokens(tokens);
2880 }
2881 }
2882
2883 #[cfg(feature = "full")]
2884 fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>) {
2885 if let Some((else_token, else_)) = else_ {
2886 else_token.to_tokens(tokens);
2887
2888 // If we are not one of the valid expressions to exist in an else
2889 // clause, wrap ourselves in a block.
2890 match **else_ {
2891 Expr::If(_) | Expr::Block(_) => {
2892 else_.to_tokens(tokens);
2893 }
2894 _ => {
2895 token::Brace::default().surround(tokens, |tokens| {
2896 else_.to_tokens(tokens);
2897 });
2898 }
2899 }
2900 }
2901 }
2902
2903 #[cfg(feature = "full")]
5869c6ff 2904 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
2905 impl ToTokens for ExprLet {
2906 fn to_tokens(&self, tokens: &mut TokenStream) {
2907 outer_attrs_to_tokens(&self.attrs, tokens);
2908 self.let_token.to_tokens(tokens);
2909 self.pat.to_tokens(tokens);
2910 self.eq_token.to_tokens(tokens);
2911 wrap_bare_struct(tokens, &self.expr);
2912 }
2913 }
2914
2915 #[cfg(feature = "full")]
5869c6ff 2916 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
2917 impl ToTokens for ExprIf {
2918 fn to_tokens(&self, tokens: &mut TokenStream) {
2919 outer_attrs_to_tokens(&self.attrs, tokens);
2920 self.if_token.to_tokens(tokens);
2921 wrap_bare_struct(tokens, &self.cond);
2922 self.then_branch.to_tokens(tokens);
2923 maybe_wrap_else(tokens, &self.else_branch);
2924 }
2925 }
2926
2927 #[cfg(feature = "full")]
5869c6ff 2928 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
2929 impl ToTokens for ExprWhile {
2930 fn to_tokens(&self, tokens: &mut TokenStream) {
2931 outer_attrs_to_tokens(&self.attrs, tokens);
2932 self.label.to_tokens(tokens);
2933 self.while_token.to_tokens(tokens);
2934 wrap_bare_struct(tokens, &self.cond);
2935 self.body.brace_token.surround(tokens, |tokens| {
2936 inner_attrs_to_tokens(&self.attrs, tokens);
2937 tokens.append_all(&self.body.stmts);
2938 });
2939 }
2940 }
2941
2942 #[cfg(feature = "full")]
5869c6ff 2943 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
2944 impl ToTokens for ExprForLoop {
2945 fn to_tokens(&self, tokens: &mut TokenStream) {
2946 outer_attrs_to_tokens(&self.attrs, tokens);
2947 self.label.to_tokens(tokens);
2948 self.for_token.to_tokens(tokens);
2949 self.pat.to_tokens(tokens);
2950 self.in_token.to_tokens(tokens);
2951 wrap_bare_struct(tokens, &self.expr);
2952 self.body.brace_token.surround(tokens, |tokens| {
2953 inner_attrs_to_tokens(&self.attrs, tokens);
2954 tokens.append_all(&self.body.stmts);
2955 });
2956 }
2957 }
2958
2959 #[cfg(feature = "full")]
5869c6ff 2960 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
2961 impl ToTokens for ExprLoop {
2962 fn to_tokens(&self, tokens: &mut TokenStream) {
2963 outer_attrs_to_tokens(&self.attrs, tokens);
2964 self.label.to_tokens(tokens);
2965 self.loop_token.to_tokens(tokens);
2966 self.body.brace_token.surround(tokens, |tokens| {
2967 inner_attrs_to_tokens(&self.attrs, tokens);
2968 tokens.append_all(&self.body.stmts);
2969 });
2970 }
2971 }
2972
2973 #[cfg(feature = "full")]
5869c6ff 2974 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
2975 impl ToTokens for ExprMatch {
2976 fn to_tokens(&self, tokens: &mut TokenStream) {
2977 outer_attrs_to_tokens(&self.attrs, tokens);
2978 self.match_token.to_tokens(tokens);
2979 wrap_bare_struct(tokens, &self.expr);
2980 self.brace_token.surround(tokens, |tokens| {
2981 inner_attrs_to_tokens(&self.attrs, tokens);
2982 for (i, arm) in self.arms.iter().enumerate() {
2983 arm.to_tokens(tokens);
2984 // Ensure that we have a comma after a non-block arm, except
2985 // for the last one.
2986 let is_last = i == self.arms.len() - 1;
2987 if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() {
2988 <Token![,]>::default().to_tokens(tokens);
2989 }
2990 }
2991 });
2992 }
2993 }
2994
2995 #[cfg(feature = "full")]
5869c6ff 2996 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
2997 impl ToTokens for ExprAsync {
2998 fn to_tokens(&self, tokens: &mut TokenStream) {
2999 outer_attrs_to_tokens(&self.attrs, tokens);
3000 self.async_token.to_tokens(tokens);
3001 self.capture.to_tokens(tokens);
3002 self.block.to_tokens(tokens);
3003 }
3004 }
3005
3006 #[cfg(feature = "full")]
5869c6ff 3007 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3008 impl ToTokens for ExprAwait {
3009 fn to_tokens(&self, tokens: &mut TokenStream) {
3010 outer_attrs_to_tokens(&self.attrs, tokens);
3011 self.base.to_tokens(tokens);
3012 self.dot_token.to_tokens(tokens);
3013 self.await_token.to_tokens(tokens);
3014 }
3015 }
3016
3017 #[cfg(feature = "full")]
5869c6ff 3018 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3019 impl ToTokens for ExprTryBlock {
3020 fn to_tokens(&self, tokens: &mut TokenStream) {
3021 outer_attrs_to_tokens(&self.attrs, tokens);
3022 self.try_token.to_tokens(tokens);
3023 self.block.to_tokens(tokens);
3024 }
3025 }
3026
3027 #[cfg(feature = "full")]
5869c6ff 3028 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3029 impl ToTokens for ExprYield {
3030 fn to_tokens(&self, tokens: &mut TokenStream) {
3031 outer_attrs_to_tokens(&self.attrs, tokens);
3032 self.yield_token.to_tokens(tokens);
3033 self.expr.to_tokens(tokens);
3034 }
3035 }
3036
3037 #[cfg(feature = "full")]
5869c6ff 3038 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3039 impl ToTokens for ExprClosure {
3040 fn to_tokens(&self, tokens: &mut TokenStream) {
3041 outer_attrs_to_tokens(&self.attrs, tokens);
3042 self.asyncness.to_tokens(tokens);
3043 self.movability.to_tokens(tokens);
3044 self.capture.to_tokens(tokens);
3045 self.or1_token.to_tokens(tokens);
3046 self.inputs.to_tokens(tokens);
3047 self.or2_token.to_tokens(tokens);
3048 self.output.to_tokens(tokens);
3049 self.body.to_tokens(tokens);
3050 }
3051 }
3052
3053 #[cfg(feature = "full")]
5869c6ff 3054 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3055 impl ToTokens for ExprUnsafe {
3056 fn to_tokens(&self, tokens: &mut TokenStream) {
3057 outer_attrs_to_tokens(&self.attrs, tokens);
3058 self.unsafe_token.to_tokens(tokens);
3059 self.block.brace_token.surround(tokens, |tokens| {
3060 inner_attrs_to_tokens(&self.attrs, tokens);
3061 tokens.append_all(&self.block.stmts);
3062 });
3063 }
3064 }
3065
3066 #[cfg(feature = "full")]
5869c6ff 3067 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3068 impl ToTokens for ExprBlock {
3069 fn to_tokens(&self, tokens: &mut TokenStream) {
3070 outer_attrs_to_tokens(&self.attrs, tokens);
3071 self.label.to_tokens(tokens);
3072 self.block.brace_token.surround(tokens, |tokens| {
3073 inner_attrs_to_tokens(&self.attrs, tokens);
3074 tokens.append_all(&self.block.stmts);
3075 });
3076 }
3077 }
3078
3079 #[cfg(feature = "full")]
5869c6ff 3080 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3081 impl ToTokens for ExprAssign {
3082 fn to_tokens(&self, tokens: &mut TokenStream) {
3083 outer_attrs_to_tokens(&self.attrs, tokens);
3084 self.left.to_tokens(tokens);
3085 self.eq_token.to_tokens(tokens);
3086 self.right.to_tokens(tokens);
3087 }
3088 }
3089
3090 #[cfg(feature = "full")]
5869c6ff 3091 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3092 impl ToTokens for ExprAssignOp {
3093 fn to_tokens(&self, tokens: &mut TokenStream) {
3094 outer_attrs_to_tokens(&self.attrs, tokens);
3095 self.left.to_tokens(tokens);
3096 self.op.to_tokens(tokens);
3097 self.right.to_tokens(tokens);
3098 }
3099 }
3100
5869c6ff 3101 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3102 impl ToTokens for ExprField {
3103 fn to_tokens(&self, tokens: &mut TokenStream) {
3104 outer_attrs_to_tokens(&self.attrs, tokens);
3105 self.base.to_tokens(tokens);
3106 self.dot_token.to_tokens(tokens);
3107 self.member.to_tokens(tokens);
3108 }
3109 }
3110
5869c6ff 3111 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3112 impl ToTokens for Member {
3113 fn to_tokens(&self, tokens: &mut TokenStream) {
3114 match self {
3115 Member::Named(ident) => ident.to_tokens(tokens),
3116 Member::Unnamed(index) => index.to_tokens(tokens),
3117 }
3118 }
3119 }
3120
5869c6ff 3121 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3122 impl ToTokens for Index {
3123 fn to_tokens(&self, tokens: &mut TokenStream) {
3124 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
3125 lit.set_span(self.span);
3126 tokens.append(lit);
3127 }
3128 }
3129
5869c6ff 3130 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3131 impl ToTokens for ExprIndex {
3132 fn to_tokens(&self, tokens: &mut TokenStream) {
3133 outer_attrs_to_tokens(&self.attrs, tokens);
3134 self.expr.to_tokens(tokens);
3135 self.bracket_token.surround(tokens, |tokens| {
3136 self.index.to_tokens(tokens);
3137 });
3138 }
3139 }
3140
3141 #[cfg(feature = "full")]
5869c6ff 3142 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3143 impl ToTokens for ExprRange {
3144 fn to_tokens(&self, tokens: &mut TokenStream) {
3145 outer_attrs_to_tokens(&self.attrs, tokens);
3146 self.from.to_tokens(tokens);
3147 match &self.limits {
3148 RangeLimits::HalfOpen(t) => t.to_tokens(tokens),
3149 RangeLimits::Closed(t) => t.to_tokens(tokens),
3150 }
3151 self.to.to_tokens(tokens);
3152 }
3153 }
3154
5869c6ff 3155 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3156 impl ToTokens for ExprPath {
3157 fn to_tokens(&self, tokens: &mut TokenStream) {
3158 outer_attrs_to_tokens(&self.attrs, tokens);
3159 private::print_path(tokens, &self.qself, &self.path);
3160 }
3161 }
3162
3163 #[cfg(feature = "full")]
5869c6ff 3164 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3165 impl ToTokens for ExprReference {
3166 fn to_tokens(&self, tokens: &mut TokenStream) {
3167 outer_attrs_to_tokens(&self.attrs, tokens);
3168 self.and_token.to_tokens(tokens);
3169 self.mutability.to_tokens(tokens);
3170 self.expr.to_tokens(tokens);
3171 }
3172 }
3173
3174 #[cfg(feature = "full")]
5869c6ff 3175 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3176 impl ToTokens for ExprBreak {
3177 fn to_tokens(&self, tokens: &mut TokenStream) {
3178 outer_attrs_to_tokens(&self.attrs, tokens);
3179 self.break_token.to_tokens(tokens);
3180 self.label.to_tokens(tokens);
3181 self.expr.to_tokens(tokens);
3182 }
3183 }
3184
3185 #[cfg(feature = "full")]
5869c6ff 3186 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3187 impl ToTokens for ExprContinue {
3188 fn to_tokens(&self, tokens: &mut TokenStream) {
3189 outer_attrs_to_tokens(&self.attrs, tokens);
3190 self.continue_token.to_tokens(tokens);
3191 self.label.to_tokens(tokens);
3192 }
3193 }
3194
3195 #[cfg(feature = "full")]
5869c6ff 3196 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3197 impl ToTokens for ExprReturn {
3198 fn to_tokens(&self, tokens: &mut TokenStream) {
3199 outer_attrs_to_tokens(&self.attrs, tokens);
3200 self.return_token.to_tokens(tokens);
3201 self.expr.to_tokens(tokens);
3202 }
3203 }
3204
3205 #[cfg(feature = "full")]
5869c6ff 3206 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3207 impl ToTokens for ExprMacro {
3208 fn to_tokens(&self, tokens: &mut TokenStream) {
3209 outer_attrs_to_tokens(&self.attrs, tokens);
3210 self.mac.to_tokens(tokens);
3211 }
3212 }
3213
3214 #[cfg(feature = "full")]
5869c6ff 3215 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3216 impl ToTokens for ExprStruct {
3217 fn to_tokens(&self, tokens: &mut TokenStream) {
3218 outer_attrs_to_tokens(&self.attrs, tokens);
3219 self.path.to_tokens(tokens);
3220 self.brace_token.surround(tokens, |tokens| {
3221 inner_attrs_to_tokens(&self.attrs, tokens);
3222 self.fields.to_tokens(tokens);
5869c6ff
XL
3223 if let Some(dot2_token) = &self.dot2_token {
3224 dot2_token.to_tokens(tokens);
3225 } else if self.rest.is_some() {
3226 Token![..](Span::call_site()).to_tokens(tokens);
e74abb32 3227 }
5869c6ff 3228 self.rest.to_tokens(tokens);
e74abb32
XL
3229 })
3230 }
3231 }
3232
3233 #[cfg(feature = "full")]
5869c6ff 3234 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3235 impl ToTokens for ExprRepeat {
3236 fn to_tokens(&self, tokens: &mut TokenStream) {
3237 outer_attrs_to_tokens(&self.attrs, tokens);
3238 self.bracket_token.surround(tokens, |tokens| {
3239 inner_attrs_to_tokens(&self.attrs, tokens);
3240 self.expr.to_tokens(tokens);
3241 self.semi_token.to_tokens(tokens);
3242 self.len.to_tokens(tokens);
3243 })
3244 }
3245 }
3246
3247 #[cfg(feature = "full")]
5869c6ff 3248 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3249 impl ToTokens for ExprGroup {
3250 fn to_tokens(&self, tokens: &mut TokenStream) {
3251 outer_attrs_to_tokens(&self.attrs, tokens);
3252 self.group_token.surround(tokens, |tokens| {
3253 self.expr.to_tokens(tokens);
3254 });
3255 }
3256 }
3257
5869c6ff 3258 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3259 impl ToTokens for ExprParen {
3260 fn to_tokens(&self, tokens: &mut TokenStream) {
3261 outer_attrs_to_tokens(&self.attrs, tokens);
3262 self.paren_token.surround(tokens, |tokens| {
3263 inner_attrs_to_tokens(&self.attrs, tokens);
3264 self.expr.to_tokens(tokens);
3265 });
3266 }
3267 }
3268
3269 #[cfg(feature = "full")]
5869c6ff 3270 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3271 impl ToTokens for ExprTry {
3272 fn to_tokens(&self, tokens: &mut TokenStream) {
3273 outer_attrs_to_tokens(&self.attrs, tokens);
3274 self.expr.to_tokens(tokens);
3275 self.question_token.to_tokens(tokens);
3276 }
3277 }
3278
3279 #[cfg(feature = "full")]
5869c6ff 3280 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3281 impl ToTokens for Label {
3282 fn to_tokens(&self, tokens: &mut TokenStream) {
3283 self.name.to_tokens(tokens);
3284 self.colon_token.to_tokens(tokens);
3285 }
3286 }
3287
3288 #[cfg(feature = "full")]
5869c6ff 3289 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3290 impl ToTokens for FieldValue {
3291 fn to_tokens(&self, tokens: &mut TokenStream) {
3292 outer_attrs_to_tokens(&self.attrs, tokens);
3293 self.member.to_tokens(tokens);
3294 if let Some(colon_token) = &self.colon_token {
3295 colon_token.to_tokens(tokens);
3296 self.expr.to_tokens(tokens);
3297 }
3298 }
3299 }
3300
3301 #[cfg(feature = "full")]
5869c6ff 3302 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
e74abb32
XL
3303 impl ToTokens for Arm {
3304 fn to_tokens(&self, tokens: &mut TokenStream) {
3305 tokens.append_all(&self.attrs);
3306 self.pat.to_tokens(tokens);
3307 if let Some((if_token, guard)) = &self.guard {
3308 if_token.to_tokens(tokens);
3309 guard.to_tokens(tokens);
3310 }
3311 self.fat_arrow_token.to_tokens(tokens);
3312 self.body.to_tokens(tokens);
3313 self.comma.to_tokens(tokens);
3314 }
3315 }
3316}