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