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