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 begin = input.fork();
1828 let expr: ExprPath = input.parse()?;
1829
1830 if expr.qself.is_none() && input.peek(Token![!]) && !input.peek(Token![!=]) {
1831 let mut contains_arguments = false;
1832 for segment in &expr.path.segments {
1833 match segment.arguments {
1834 PathArguments::None => {}
1835 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
1836 contains_arguments = true;
1837 }
1838 }
1839 }
1840
1841 if !contains_arguments {
1842 let bang_token: Token![!] = input.parse()?;
1843 let (delimiter, tokens) = mac::parse_delimiter(input)?;
1844 return Ok(Expr::Macro(ExprMacro {
1845 attrs: Vec::new(),
1846 mac: Macro {
1847 path: expr.path,
1848 bang_token,
1849 delimiter,
1850 tokens,
1851 },
1852 }));
1853 }
1854 }
1855
1856 if allow_struct.0 && input.peek(token::Brace) {
1857 let outer_attrs = Vec::new();
1858 let expr_struct = expr_struct_helper(input, outer_attrs, expr.path)?;
1859 if expr.qself.is_some() {
1860 Ok(Expr::Verbatim(verbatim::between(begin, input)))
1861 } else {
1862 Ok(Expr::Struct(expr_struct))
1863 }
1864 } else {
1865 Ok(Expr::Path(expr))
1866 }
1867 }
1868
1869 #[cfg(feature = "full")]
1870 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
1871 impl Parse for ExprMacro {
parse(input: ParseStream) -> Result<Self>1872 fn parse(input: ParseStream) -> Result<Self> {
1873 Ok(ExprMacro {
1874 attrs: Vec::new(),
1875 mac: input.parse()?,
1876 })
1877 }
1878 }
1879
1880 #[cfg(feature = "full")]
paren_or_tuple(input: ParseStream) -> Result<Expr>1881 fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
1882 let content;
1883 let paren_token = parenthesized!(content in input);
1884 let inner_attrs = content.call(Attribute::parse_inner)?;
1885 if content.is_empty() {
1886 return Ok(Expr::Tuple(ExprTuple {
1887 attrs: inner_attrs,
1888 paren_token,
1889 elems: Punctuated::new(),
1890 }));
1891 }
1892
1893 let first: Expr = content.parse()?;
1894 if content.is_empty() {
1895 return Ok(Expr::Paren(ExprParen {
1896 attrs: inner_attrs,
1897 paren_token,
1898 expr: Box::new(first),
1899 }));
1900 }
1901
1902 let mut elems = Punctuated::new();
1903 elems.push_value(first);
1904 while !content.is_empty() {
1905 let punct = content.parse()?;
1906 elems.push_punct(punct);
1907 if content.is_empty() {
1908 break;
1909 }
1910 let value = content.parse()?;
1911 elems.push_value(value);
1912 }
1913 Ok(Expr::Tuple(ExprTuple {
1914 attrs: inner_attrs,
1915 paren_token,
1916 elems,
1917 }))
1918 }
1919
1920 #[cfg(feature = "full")]
array_or_repeat(input: ParseStream) -> Result<Expr>1921 fn array_or_repeat(input: ParseStream) -> Result<Expr> {
1922 let content;
1923 let bracket_token = bracketed!(content in input);
1924 let inner_attrs = content.call(Attribute::parse_inner)?;
1925 if content.is_empty() {
1926 return Ok(Expr::Array(ExprArray {
1927 attrs: inner_attrs,
1928 bracket_token,
1929 elems: Punctuated::new(),
1930 }));
1931 }
1932
1933 let first: Expr = content.parse()?;
1934 if content.is_empty() || content.peek(Token![,]) {
1935 let mut elems = Punctuated::new();
1936 elems.push_value(first);
1937 while !content.is_empty() {
1938 let punct = content.parse()?;
1939 elems.push_punct(punct);
1940 if content.is_empty() {
1941 break;
1942 }
1943 let value = content.parse()?;
1944 elems.push_value(value);
1945 }
1946 Ok(Expr::Array(ExprArray {
1947 attrs: inner_attrs,
1948 bracket_token,
1949 elems,
1950 }))
1951 } else if content.peek(Token![;]) {
1952 let semi_token: Token![;] = content.parse()?;
1953 let len: Expr = content.parse()?;
1954 Ok(Expr::Repeat(ExprRepeat {
1955 attrs: inner_attrs,
1956 bracket_token,
1957 expr: Box::new(first),
1958 semi_token,
1959 len: Box::new(len),
1960 }))
1961 } else {
1962 Err(content.error("expected `,` or `;`"))
1963 }
1964 }
1965
1966 #[cfg(feature = "full")]
1967 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
1968 impl Parse for ExprArray {
parse(input: ParseStream) -> Result<Self>1969 fn parse(input: ParseStream) -> Result<Self> {
1970 let content;
1971 let bracket_token = bracketed!(content in input);
1972 let inner_attrs = content.call(Attribute::parse_inner)?;
1973 let mut elems = Punctuated::new();
1974
1975 while !content.is_empty() {
1976 let first: Expr = content.parse()?;
1977 elems.push_value(first);
1978 if content.is_empty() {
1979 break;
1980 }
1981 let punct = content.parse()?;
1982 elems.push_punct(punct);
1983 }
1984
1985 Ok(ExprArray {
1986 attrs: inner_attrs,
1987 bracket_token,
1988 elems,
1989 })
1990 }
1991 }
1992
1993 #[cfg(feature = "full")]
1994 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
1995 impl Parse for ExprRepeat {
parse(input: ParseStream) -> Result<Self>1996 fn parse(input: ParseStream) -> Result<Self> {
1997 let content;
1998 Ok(ExprRepeat {
1999 bracket_token: bracketed!(content in input),
2000 attrs: content.call(Attribute::parse_inner)?,
2001 expr: content.parse()?,
2002 semi_token: content.parse()?,
2003 len: content.parse()?,
2004 })
2005 }
2006 }
2007
2008 #[cfg(feature = "full")]
expr_early(input: ParseStream) -> Result<Expr>2009 pub(crate) fn expr_early(input: ParseStream) -> Result<Expr> {
2010 let mut attrs = input.call(expr_attrs)?;
2011 let mut expr = if input.peek(Token![if]) {
2012 Expr::If(input.parse()?)
2013 } else if input.peek(Token![while]) {
2014 Expr::While(input.parse()?)
2015 } else if input.peek(Token![for]) {
2016 Expr::ForLoop(input.parse()?)
2017 } else if input.peek(Token![loop]) {
2018 Expr::Loop(input.parse()?)
2019 } else if input.peek(Token![match]) {
2020 Expr::Match(input.parse()?)
2021 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
2022 Expr::TryBlock(input.parse()?)
2023 } else if input.peek(Token![unsafe]) {
2024 Expr::Unsafe(input.parse()?)
2025 } else if input.peek(Token![const]) {
2026 Expr::Verbatim(input.call(expr_const)?)
2027 } else if input.peek(token::Brace) {
2028 Expr::Block(input.parse()?)
2029 } else {
2030 let allow_struct = AllowStruct(true);
2031 let mut expr = unary_expr(input, allow_struct)?;
2032
2033 attrs.extend(expr.replace_attrs(Vec::new()));
2034 expr.replace_attrs(attrs);
2035
2036 return parse_expr(input, expr, allow_struct, Precedence::Any);
2037 };
2038
2039 if input.peek(Token![.]) && !input.peek(Token![..]) || input.peek(Token![?]) {
2040 expr = trailer_helper(input, expr)?;
2041
2042 attrs.extend(expr.replace_attrs(Vec::new()));
2043 expr.replace_attrs(attrs);
2044
2045 let allow_struct = AllowStruct(true);
2046 return parse_expr(input, expr, allow_struct, Precedence::Any);
2047 }
2048
2049 attrs.extend(expr.replace_attrs(Vec::new()));
2050 expr.replace_attrs(attrs);
2051 Ok(expr)
2052 }
2053
2054 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2055 impl Parse for ExprLit {
parse(input: ParseStream) -> Result<Self>2056 fn parse(input: ParseStream) -> Result<Self> {
2057 Ok(ExprLit {
2058 attrs: Vec::new(),
2059 lit: input.parse()?,
2060 })
2061 }
2062 }
2063
2064 #[cfg(feature = "full")]
expr_group(input: ParseStream) -> Result<ExprGroup>2065 fn expr_group(input: ParseStream) -> Result<ExprGroup> {
2066 let group = crate::group::parse_group(input)?;
2067 Ok(ExprGroup {
2068 attrs: Vec::new(),
2069 group_token: group.token,
2070 expr: group.content.parse()?,
2071 })
2072 }
2073
2074 #[cfg(feature = "full")]
2075 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2076 impl Parse for ExprParen {
parse(input: ParseStream) -> Result<Self>2077 fn parse(input: ParseStream) -> Result<Self> {
2078 expr_paren(input)
2079 }
2080 }
2081
expr_paren(input: ParseStream) -> Result<ExprParen>2082 fn expr_paren(input: ParseStream) -> Result<ExprParen> {
2083 let content;
2084 Ok(ExprParen {
2085 attrs: Vec::new(),
2086 paren_token: parenthesized!(content in input),
2087 expr: content.parse()?,
2088 })
2089 }
2090
2091 #[cfg(feature = "full")]
generic_method_argument(input: ParseStream) -> Result<GenericMethodArgument>2092 fn generic_method_argument(input: ParseStream) -> Result<GenericMethodArgument> {
2093 if input.peek(Lit) {
2094 let lit = input.parse()?;
2095 return Ok(GenericMethodArgument::Const(Expr::Lit(lit)));
2096 }
2097
2098 if input.peek(token::Brace) {
2099 let block: ExprBlock = input.parse()?;
2100 return Ok(GenericMethodArgument::Const(Expr::Block(block)));
2101 }
2102
2103 input.parse().map(GenericMethodArgument::Type)
2104 }
2105
2106 #[cfg(feature = "full")]
2107 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2108 impl Parse for ExprLet {
parse(input: ParseStream) -> Result<Self>2109 fn parse(input: ParseStream) -> Result<Self> {
2110 Ok(ExprLet {
2111 attrs: Vec::new(),
2112 let_token: input.parse()?,
2113 pat: pat::parsing::multi_pat_with_leading_vert(input)?,
2114 eq_token: input.parse()?,
2115 expr: Box::new(input.call(Expr::parse_without_eager_brace)?),
2116 })
2117 }
2118 }
2119
2120 #[cfg(feature = "full")]
2121 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2122 impl Parse for ExprIf {
parse(input: ParseStream) -> Result<Self>2123 fn parse(input: ParseStream) -> Result<Self> {
2124 let attrs = input.call(Attribute::parse_outer)?;
2125 Ok(ExprIf {
2126 attrs,
2127 if_token: input.parse()?,
2128 cond: Box::new(input.call(Expr::parse_without_eager_brace)?),
2129 then_branch: input.parse()?,
2130 else_branch: {
2131 if input.peek(Token![else]) {
2132 Some(input.call(else_block)?)
2133 } else {
2134 None
2135 }
2136 },
2137 })
2138 }
2139 }
2140
2141 #[cfg(feature = "full")]
else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)>2142 fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
2143 let else_token: Token![else] = input.parse()?;
2144
2145 let lookahead = input.lookahead1();
2146 let else_branch = if input.peek(Token![if]) {
2147 input.parse().map(Expr::If)?
2148 } else if input.peek(token::Brace) {
2149 Expr::Block(ExprBlock {
2150 attrs: Vec::new(),
2151 label: None,
2152 block: input.parse()?,
2153 })
2154 } else {
2155 return Err(lookahead.error());
2156 };
2157
2158 Ok((else_token, Box::new(else_branch)))
2159 }
2160
2161 #[cfg(feature = "full")]
2162 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2163 impl Parse for ExprForLoop {
parse(input: ParseStream) -> Result<Self>2164 fn parse(input: ParseStream) -> Result<Self> {
2165 let mut attrs = input.call(Attribute::parse_outer)?;
2166 let label: Option<Label> = input.parse()?;
2167 let for_token: Token![for] = input.parse()?;
2168
2169 let pat = pat::parsing::multi_pat_with_leading_vert(input)?;
2170
2171 let in_token: Token![in] = input.parse()?;
2172 let expr: Expr = input.call(Expr::parse_without_eager_brace)?;
2173
2174 let content;
2175 let brace_token = braced!(content in input);
2176 attr::parsing::parse_inner(&content, &mut attrs)?;
2177 let stmts = content.call(Block::parse_within)?;
2178
2179 Ok(ExprForLoop {
2180 attrs,
2181 label,
2182 for_token,
2183 pat,
2184 in_token,
2185 expr: Box::new(expr),
2186 body: Block { brace_token, stmts },
2187 })
2188 }
2189 }
2190
2191 #[cfg(feature = "full")]
2192 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2193 impl Parse for ExprLoop {
parse(input: ParseStream) -> Result<Self>2194 fn parse(input: ParseStream) -> Result<Self> {
2195 let mut attrs = input.call(Attribute::parse_outer)?;
2196 let label: Option<Label> = input.parse()?;
2197 let loop_token: Token![loop] = input.parse()?;
2198
2199 let content;
2200 let brace_token = braced!(content in input);
2201 attr::parsing::parse_inner(&content, &mut attrs)?;
2202 let stmts = content.call(Block::parse_within)?;
2203
2204 Ok(ExprLoop {
2205 attrs,
2206 label,
2207 loop_token,
2208 body: Block { brace_token, stmts },
2209 })
2210 }
2211 }
2212
2213 #[cfg(feature = "full")]
2214 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2215 impl Parse for ExprMatch {
parse(input: ParseStream) -> Result<Self>2216 fn parse(input: ParseStream) -> Result<Self> {
2217 let mut attrs = input.call(Attribute::parse_outer)?;
2218 let match_token: Token![match] = input.parse()?;
2219 let expr = Expr::parse_without_eager_brace(input)?;
2220
2221 let content;
2222 let brace_token = braced!(content in input);
2223 attr::parsing::parse_inner(&content, &mut attrs)?;
2224
2225 let mut arms = Vec::new();
2226 while !content.is_empty() {
2227 arms.push(content.call(Arm::parse)?);
2228 }
2229
2230 Ok(ExprMatch {
2231 attrs,
2232 match_token,
2233 expr: Box::new(expr),
2234 brace_token,
2235 arms,
2236 })
2237 }
2238 }
2239
2240 macro_rules! impl_by_parsing_expr {
2241 (
2242 $(
2243 $expr_type:ty, $variant:ident, $msg:expr,
2244 )*
2245 ) => {
2246 $(
2247 #[cfg(all(feature = "full", feature = "printing"))]
2248 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2249 impl Parse for $expr_type {
2250 fn parse(input: ParseStream) -> Result<Self> {
2251 let mut expr: Expr = input.parse()?;
2252 loop {
2253 match expr {
2254 Expr::$variant(inner) => return Ok(inner),
2255 Expr::Group(next) => expr = *next.expr,
2256 _ => return Err(Error::new_spanned(expr, $msg)),
2257 }
2258 }
2259 }
2260 }
2261 )*
2262 };
2263 }
2264
2265 impl_by_parsing_expr! {
2266 ExprCall, Call, "expected function call expression",
2267 ExprMethodCall, MethodCall, "expected method call expression",
2268 ExprTuple, Tuple, "expected tuple expression",
2269 ExprBinary, Binary, "expected binary operation",
2270 ExprCast, Cast, "expected cast expression",
2271 ExprType, Type, "expected type ascription expression",
2272 ExprAssign, Assign, "expected assignment expression",
2273 ExprAssignOp, AssignOp, "expected compound assignment expression",
2274 ExprField, Field, "expected struct field access",
2275 ExprIndex, Index, "expected indexing expression",
2276 ExprRange, Range, "expected range expression",
2277 ExprTry, Try, "expected try expression",
2278 }
2279
2280 #[cfg(feature = "full")]
2281 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2282 impl Parse for ExprBox {
parse(input: ParseStream) -> Result<Self>2283 fn parse(input: ParseStream) -> Result<Self> {
2284 let attrs = Vec::new();
2285 let allow_struct = AllowStruct(true);
2286 expr_box(input, attrs, allow_struct)
2287 }
2288 }
2289
2290 #[cfg(feature = "full")]
expr_box( input: ParseStream, attrs: Vec<Attribute>, allow_struct: AllowStruct, ) -> Result<ExprBox>2291 fn expr_box(
2292 input: ParseStream,
2293 attrs: Vec<Attribute>,
2294 allow_struct: AllowStruct,
2295 ) -> Result<ExprBox> {
2296 Ok(ExprBox {
2297 attrs,
2298 box_token: input.parse()?,
2299 expr: Box::new(unary_expr(input, allow_struct)?),
2300 })
2301 }
2302
2303 #[cfg(feature = "full")]
2304 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2305 impl Parse for ExprUnary {
parse(input: ParseStream) -> Result<Self>2306 fn parse(input: ParseStream) -> Result<Self> {
2307 let attrs = Vec::new();
2308 let allow_struct = AllowStruct(true);
2309 expr_unary(input, attrs, allow_struct)
2310 }
2311 }
2312
2313 #[cfg(feature = "full")]
expr_unary( input: ParseStream, attrs: Vec<Attribute>, allow_struct: AllowStruct, ) -> Result<ExprUnary>2314 fn expr_unary(
2315 input: ParseStream,
2316 attrs: Vec<Attribute>,
2317 allow_struct: AllowStruct,
2318 ) -> Result<ExprUnary> {
2319 Ok(ExprUnary {
2320 attrs,
2321 op: input.parse()?,
2322 expr: Box::new(unary_expr(input, allow_struct)?),
2323 })
2324 }
2325
2326 #[cfg(feature = "full")]
2327 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2328 impl Parse for ExprClosure {
parse(input: ParseStream) -> Result<Self>2329 fn parse(input: ParseStream) -> Result<Self> {
2330 let allow_struct = AllowStruct(true);
2331 expr_closure(input, allow_struct)
2332 }
2333 }
2334
2335 #[cfg(feature = "full")]
2336 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2337 impl Parse for ExprReference {
parse(input: ParseStream) -> Result<Self>2338 fn parse(input: ParseStream) -> Result<Self> {
2339 let allow_struct = AllowStruct(true);
2340 Ok(ExprReference {
2341 attrs: Vec::new(),
2342 and_token: input.parse()?,
2343 raw: Reserved::default(),
2344 mutability: input.parse()?,
2345 expr: Box::new(unary_expr(input, allow_struct)?),
2346 })
2347 }
2348 }
2349
2350 #[cfg(feature = "full")]
2351 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2352 impl Parse for ExprBreak {
parse(input: ParseStream) -> Result<Self>2353 fn parse(input: ParseStream) -> Result<Self> {
2354 let allow_struct = AllowStruct(true);
2355 expr_break(input, allow_struct)
2356 }
2357 }
2358
2359 #[cfg(feature = "full")]
2360 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2361 impl Parse for ExprReturn {
parse(input: ParseStream) -> Result<Self>2362 fn parse(input: ParseStream) -> Result<Self> {
2363 let allow_struct = AllowStruct(true);
2364 expr_ret(input, allow_struct)
2365 }
2366 }
2367
2368 #[cfg(feature = "full")]
2369 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2370 impl Parse for ExprTryBlock {
parse(input: ParseStream) -> Result<Self>2371 fn parse(input: ParseStream) -> Result<Self> {
2372 Ok(ExprTryBlock {
2373 attrs: Vec::new(),
2374 try_token: input.parse()?,
2375 block: input.parse()?,
2376 })
2377 }
2378 }
2379
2380 #[cfg(feature = "full")]
2381 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2382 impl Parse for ExprYield {
parse(input: ParseStream) -> Result<Self>2383 fn parse(input: ParseStream) -> Result<Self> {
2384 Ok(ExprYield {
2385 attrs: Vec::new(),
2386 yield_token: input.parse()?,
2387 expr: {
2388 if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
2389 Some(input.parse()?)
2390 } else {
2391 None
2392 }
2393 },
2394 })
2395 }
2396 }
2397
2398 #[cfg(feature = "full")]
expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure>2399 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
2400 let asyncness: Option<Token![async]> = input.parse()?;
2401 let movability: Option<Token![static]> = if asyncness.is_none() {
2402 input.parse()?
2403 } else {
2404 None
2405 };
2406 let capture: Option<Token![move]> = input.parse()?;
2407 let or1_token: Token![|] = input.parse()?;
2408
2409 let mut inputs = Punctuated::new();
2410 loop {
2411 if input.peek(Token![|]) {
2412 break;
2413 }
2414 let value = closure_arg(input)?;
2415 inputs.push_value(value);
2416 if input.peek(Token![|]) {
2417 break;
2418 }
2419 let punct: Token![,] = input.parse()?;
2420 inputs.push_punct(punct);
2421 }
2422
2423 let or2_token: Token![|] = input.parse()?;
2424
2425 let (output, body) = if input.peek(Token![->]) {
2426 let arrow_token: Token![->] = input.parse()?;
2427 let ty: Type = input.parse()?;
2428 let body: Block = input.parse()?;
2429 let output = ReturnType::Type(arrow_token, Box::new(ty));
2430 let block = Expr::Block(ExprBlock {
2431 attrs: Vec::new(),
2432 label: None,
2433 block: body,
2434 });
2435 (output, block)
2436 } else {
2437 let body = ambiguous_expr(input, allow_struct)?;
2438 (ReturnType::Default, body)
2439 };
2440
2441 Ok(ExprClosure {
2442 attrs: Vec::new(),
2443 asyncness,
2444 movability,
2445 capture,
2446 or1_token,
2447 inputs,
2448 or2_token,
2449 output,
2450 body: Box::new(body),
2451 })
2452 }
2453
2454 #[cfg(feature = "full")]
2455 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2456 impl Parse for ExprAsync {
parse(input: ParseStream) -> Result<Self>2457 fn parse(input: ParseStream) -> Result<Self> {
2458 Ok(ExprAsync {
2459 attrs: Vec::new(),
2460 async_token: input.parse()?,
2461 capture: input.parse()?,
2462 block: input.parse()?,
2463 })
2464 }
2465 }
2466
2467 #[cfg(feature = "full")]
closure_arg(input: ParseStream) -> Result<Pat>2468 fn closure_arg(input: ParseStream) -> Result<Pat> {
2469 let attrs = input.call(Attribute::parse_outer)?;
2470 let mut pat: Pat = input.parse()?;
2471
2472 if input.peek(Token![:]) {
2473 Ok(Pat::Type(PatType {
2474 attrs,
2475 pat: Box::new(pat),
2476 colon_token: input.parse()?,
2477 ty: input.parse()?,
2478 }))
2479 } else {
2480 match &mut pat {
2481 Pat::Box(pat) => pat.attrs = attrs,
2482 Pat::Ident(pat) => pat.attrs = attrs,
2483 Pat::Lit(pat) => pat.attrs = attrs,
2484 Pat::Macro(pat) => pat.attrs = attrs,
2485 Pat::Or(pat) => pat.attrs = attrs,
2486 Pat::Path(pat) => pat.attrs = attrs,
2487 Pat::Range(pat) => pat.attrs = attrs,
2488 Pat::Reference(pat) => pat.attrs = attrs,
2489 Pat::Rest(pat) => pat.attrs = attrs,
2490 Pat::Slice(pat) => pat.attrs = attrs,
2491 Pat::Struct(pat) => pat.attrs = attrs,
2492 Pat::Tuple(pat) => pat.attrs = attrs,
2493 Pat::TupleStruct(pat) => pat.attrs = attrs,
2494 Pat::Type(_) => unreachable!(),
2495 Pat::Verbatim(_) => {}
2496 Pat::Wild(pat) => pat.attrs = attrs,
2497
2498 #[cfg(test)]
2499 Pat::__TestExhaustive(_) => unimplemented!(),
2500 #[cfg(not(test))]
2501 _ => unreachable!(),
2502 }
2503 Ok(pat)
2504 }
2505 }
2506
2507 #[cfg(feature = "full")]
2508 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2509 impl Parse for ExprWhile {
parse(input: ParseStream) -> Result<Self>2510 fn parse(input: ParseStream) -> Result<Self> {
2511 let mut attrs = input.call(Attribute::parse_outer)?;
2512 let label: Option<Label> = input.parse()?;
2513 let while_token: Token![while] = input.parse()?;
2514 let cond = Expr::parse_without_eager_brace(input)?;
2515
2516 let content;
2517 let brace_token = braced!(content in input);
2518 attr::parsing::parse_inner(&content, &mut attrs)?;
2519 let stmts = content.call(Block::parse_within)?;
2520
2521 Ok(ExprWhile {
2522 attrs,
2523 label,
2524 while_token,
2525 cond: Box::new(cond),
2526 body: Block { brace_token, stmts },
2527 })
2528 }
2529 }
2530
2531 #[cfg(feature = "full")]
2532 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2533 impl Parse for Label {
parse(input: ParseStream) -> Result<Self>2534 fn parse(input: ParseStream) -> Result<Self> {
2535 Ok(Label {
2536 name: input.parse()?,
2537 colon_token: input.parse()?,
2538 })
2539 }
2540 }
2541
2542 #[cfg(feature = "full")]
2543 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2544 impl Parse for Option<Label> {
parse(input: ParseStream) -> Result<Self>2545 fn parse(input: ParseStream) -> Result<Self> {
2546 if input.peek(Lifetime) {
2547 input.parse().map(Some)
2548 } else {
2549 Ok(None)
2550 }
2551 }
2552 }
2553
2554 #[cfg(feature = "full")]
2555 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2556 impl Parse for ExprContinue {
parse(input: ParseStream) -> Result<Self>2557 fn parse(input: ParseStream) -> Result<Self> {
2558 Ok(ExprContinue {
2559 attrs: Vec::new(),
2560 continue_token: input.parse()?,
2561 label: input.parse()?,
2562 })
2563 }
2564 }
2565
2566 #[cfg(feature = "full")]
expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak>2567 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2568 Ok(ExprBreak {
2569 attrs: Vec::new(),
2570 break_token: input.parse()?,
2571 label: input.parse()?,
2572 expr: {
2573 if input.is_empty()
2574 || input.peek(Token![,])
2575 || input.peek(Token![;])
2576 || !allow_struct.0 && input.peek(token::Brace)
2577 {
2578 None
2579 } else {
2580 let expr = ambiguous_expr(input, allow_struct)?;
2581 Some(Box::new(expr))
2582 }
2583 },
2584 })
2585 }
2586
2587 #[cfg(feature = "full")]
expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn>2588 fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
2589 Ok(ExprReturn {
2590 attrs: Vec::new(),
2591 return_token: input.parse()?,
2592 expr: {
2593 if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
2594 None
2595 } else {
2596 // NOTE: return is greedy and eats blocks after it even when in a
2597 // position where structs are not allowed, such as in if statement
2598 // conditions. For example:
2599 //
2600 // if return { println!("A") } {} // Prints "A"
2601 let expr = ambiguous_expr(input, allow_struct)?;
2602 Some(Box::new(expr))
2603 }
2604 },
2605 })
2606 }
2607
2608 #[cfg(feature = "full")]
2609 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2610 impl Parse for FieldValue {
parse(input: ParseStream) -> Result<Self>2611 fn parse(input: ParseStream) -> Result<Self> {
2612 let attrs = input.call(Attribute::parse_outer)?;
2613 let member: Member = input.parse()?;
2614 let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
2615 let colon_token: Token![:] = input.parse()?;
2616 let value: Expr = input.parse()?;
2617 (Some(colon_token), value)
2618 } else if let Member::Named(ident) = &member {
2619 let value = Expr::Path(ExprPath {
2620 attrs: Vec::new(),
2621 qself: None,
2622 path: Path::from(ident.clone()),
2623 });
2624 (None, value)
2625 } else {
2626 unreachable!()
2627 };
2628
2629 Ok(FieldValue {
2630 attrs,
2631 member,
2632 colon_token,
2633 expr: value,
2634 })
2635 }
2636 }
2637
2638 #[cfg(feature = "full")]
2639 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2640 impl Parse for ExprStruct {
parse(input: ParseStream) -> Result<Self>2641 fn parse(input: ParseStream) -> Result<Self> {
2642 let attrs = Vec::new();
2643 let path: Path = input.parse()?;
2644 expr_struct_helper(input, attrs, path)
2645 }
2646 }
2647
2648 #[cfg(feature = "full")]
expr_struct_helper( input: ParseStream, mut attrs: Vec<Attribute>, path: Path, ) -> Result<ExprStruct>2649 fn expr_struct_helper(
2650 input: ParseStream,
2651 mut attrs: Vec<Attribute>,
2652 path: Path,
2653 ) -> Result<ExprStruct> {
2654 let content;
2655 let brace_token = braced!(content in input);
2656 attr::parsing::parse_inner(&content, &mut attrs)?;
2657
2658 let mut fields = Punctuated::new();
2659 while !content.is_empty() {
2660 if content.peek(Token![..]) {
2661 return Ok(ExprStruct {
2662 attrs,
2663 brace_token,
2664 path,
2665 fields,
2666 dot2_token: Some(content.parse()?),
2667 rest: if content.is_empty() {
2668 None
2669 } else {
2670 Some(Box::new(content.parse()?))
2671 },
2672 });
2673 }
2674
2675 fields.push(content.parse()?);
2676 if content.is_empty() {
2677 break;
2678 }
2679 let punct: Token![,] = content.parse()?;
2680 fields.push_punct(punct);
2681 }
2682
2683 Ok(ExprStruct {
2684 attrs,
2685 brace_token,
2686 path,
2687 fields,
2688 dot2_token: None,
2689 rest: None,
2690 })
2691 }
2692
2693 #[cfg(feature = "full")]
2694 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2695 impl Parse for ExprUnsafe {
parse(input: ParseStream) -> Result<Self>2696 fn parse(input: ParseStream) -> Result<Self> {
2697 let unsafe_token: Token![unsafe] = input.parse()?;
2698
2699 let content;
2700 let brace_token = braced!(content in input);
2701 let inner_attrs = content.call(Attribute::parse_inner)?;
2702 let stmts = content.call(Block::parse_within)?;
2703
2704 Ok(ExprUnsafe {
2705 attrs: inner_attrs,
2706 unsafe_token,
2707 block: Block { brace_token, stmts },
2708 })
2709 }
2710 }
2711
2712 #[cfg(feature = "full")]
expr_const(input: ParseStream) -> Result<TokenStream>2713 pub(crate) fn expr_const(input: ParseStream) -> Result<TokenStream> {
2714 let begin = input.fork();
2715 input.parse::<Token![const]>()?;
2716
2717 let content;
2718 braced!(content in input);
2719 content.call(Attribute::parse_inner)?;
2720 content.call(Block::parse_within)?;
2721
2722 Ok(verbatim::between(begin, input))
2723 }
2724
2725 #[cfg(feature = "full")]
2726 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2727 impl Parse for ExprBlock {
parse(input: ParseStream) -> Result<Self>2728 fn parse(input: ParseStream) -> Result<Self> {
2729 let mut attrs = input.call(Attribute::parse_outer)?;
2730 let label: Option<Label> = input.parse()?;
2731
2732 let content;
2733 let brace_token = braced!(content in input);
2734 attr::parsing::parse_inner(&content, &mut attrs)?;
2735 let stmts = content.call(Block::parse_within)?;
2736
2737 Ok(ExprBlock {
2738 attrs,
2739 label,
2740 block: Block { brace_token, stmts },
2741 })
2742 }
2743 }
2744
2745 #[cfg(feature = "full")]
expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange>2746 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2747 Ok(ExprRange {
2748 attrs: Vec::new(),
2749 from: None,
2750 limits: input.parse()?,
2751 to: {
2752 if input.is_empty()
2753 || input.peek(Token![,])
2754 || input.peek(Token![;])
2755 || input.peek(Token![.]) && !input.peek(Token![..])
2756 || !allow_struct.0 && input.peek(token::Brace)
2757 {
2758 None
2759 } else {
2760 let to = ambiguous_expr(input, allow_struct)?;
2761 Some(Box::new(to))
2762 }
2763 },
2764 })
2765 }
2766
2767 #[cfg(feature = "full")]
2768 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2769 impl Parse for RangeLimits {
parse(input: ParseStream) -> Result<Self>2770 fn parse(input: ParseStream) -> Result<Self> {
2771 let lookahead = input.lookahead1();
2772 if lookahead.peek(Token![..=]) {
2773 input.parse().map(RangeLimits::Closed)
2774 } else if lookahead.peek(Token![...]) {
2775 let dot3: Token![...] = input.parse()?;
2776 Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2777 } else if lookahead.peek(Token![..]) {
2778 input.parse().map(RangeLimits::HalfOpen)
2779 } else {
2780 Err(lookahead.error())
2781 }
2782 }
2783 }
2784
2785 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2786 impl Parse for ExprPath {
parse(input: ParseStream) -> Result<Self>2787 fn parse(input: ParseStream) -> Result<Self> {
2788 #[cfg(not(feature = "full"))]
2789 let attrs = Vec::new();
2790 #[cfg(feature = "full")]
2791 let attrs = input.call(Attribute::parse_outer)?;
2792
2793 let (qself, path) = path::parsing::qpath(input, true)?;
2794
2795 Ok(ExprPath { attrs, qself, path })
2796 }
2797 }
2798
2799 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2800 impl Parse for Member {
parse(input: ParseStream) -> Result<Self>2801 fn parse(input: ParseStream) -> Result<Self> {
2802 if input.peek(Ident) {
2803 input.parse().map(Member::Named)
2804 } else if input.peek(LitInt) {
2805 input.parse().map(Member::Unnamed)
2806 } else {
2807 Err(input.error("expected identifier or integer"))
2808 }
2809 }
2810 }
2811
2812 #[cfg(feature = "full")]
2813 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2814 impl Parse for Arm {
parse(input: ParseStream) -> Result<Arm>2815 fn parse(input: ParseStream) -> Result<Arm> {
2816 let requires_comma;
2817 Ok(Arm {
2818 attrs: input.call(Attribute::parse_outer)?,
2819 pat: pat::parsing::multi_pat_with_leading_vert(input)?,
2820 guard: {
2821 if input.peek(Token![if]) {
2822 let if_token: Token![if] = input.parse()?;
2823 let guard: Expr = input.parse()?;
2824 Some((if_token, Box::new(guard)))
2825 } else {
2826 None
2827 }
2828 },
2829 fat_arrow_token: input.parse()?,
2830 body: {
2831 let body = input.call(expr_early)?;
2832 requires_comma = requires_terminator(&body);
2833 Box::new(body)
2834 },
2835 comma: {
2836 if requires_comma && !input.is_empty() {
2837 Some(input.parse()?)
2838 } else {
2839 input.parse()?
2840 }
2841 },
2842 })
2843 }
2844 }
2845
2846 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2847 impl Parse for Index {
parse(input: ParseStream) -> Result<Self>2848 fn parse(input: ParseStream) -> Result<Self> {
2849 let lit: LitInt = input.parse()?;
2850 if lit.suffix().is_empty() {
2851 Ok(Index {
2852 index: lit
2853 .base10_digits()
2854 .parse()
2855 .map_err(|err| Error::new(lit.span(), err))?,
2856 span: lit.span(),
2857 })
2858 } else {
2859 Err(Error::new(lit.span(), "expected unsuffixed integer"))
2860 }
2861 }
2862 }
2863
multi_index(e: &mut Expr, dot_token: &mut Token![.], float: LitFloat) -> Result<bool>2864 fn multi_index(e: &mut Expr, dot_token: &mut Token![.], float: LitFloat) -> Result<bool> {
2865 let mut float_repr = float.to_string();
2866 let trailing_dot = float_repr.ends_with('.');
2867 if trailing_dot {
2868 float_repr.truncate(float_repr.len() - 1);
2869 }
2870 for part in float_repr.split('.') {
2871 let index = crate::parse_str(part).map_err(|err| Error::new(float.span(), err))?;
2872 let base = mem::replace(e, Expr::__TestExhaustive(crate::private(())));
2873 *e = Expr::Field(ExprField {
2874 attrs: Vec::new(),
2875 base: Box::new(base),
2876 dot_token: Token![.](dot_token.span),
2877 member: Member::Unnamed(index),
2878 });
2879 *dot_token = Token![.](float.span());
2880 }
2881 Ok(!trailing_dot)
2882 }
2883
2884 #[cfg(feature = "full")]
2885 impl Member {
is_named(&self) -> bool2886 fn is_named(&self) -> bool {
2887 match *self {
2888 Member::Named(_) => true,
2889 Member::Unnamed(_) => false,
2890 }
2891 }
2892 }
2893 }
2894
2895 #[cfg(feature = "printing")]
2896 pub(crate) mod printing {
2897 use super::*;
2898 #[cfg(feature = "full")]
2899 use crate::attr::FilterAttrs;
2900 use proc_macro2::{Literal, TokenStream};
2901 use quote::{ToTokens, TokenStreamExt};
2902
2903 // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
2904 // before appending it to `TokenStream`.
2905 #[cfg(feature = "full")]
wrap_bare_struct(tokens: &mut TokenStream, e: &Expr)2906 fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) {
2907 if let Expr::Struct(_) = *e {
2908 token::Paren::default().surround(tokens, |tokens| {
2909 e.to_tokens(tokens);
2910 });
2911 } else {
2912 e.to_tokens(tokens);
2913 }
2914 }
2915
2916 #[cfg(feature = "full")]
outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream)2917 pub(crate) fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
2918 tokens.append_all(attrs.outer());
2919 }
2920
2921 #[cfg(feature = "full")]
inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream)2922 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
2923 tokens.append_all(attrs.inner());
2924 }
2925
2926 #[cfg(not(feature = "full"))]
outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream)2927 pub(crate) fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
2928
2929 #[cfg(not(feature = "full"))]
inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream)2930 fn inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
2931
2932 #[cfg(feature = "full")]
2933 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
2934 impl ToTokens for ExprBox {
to_tokens(&self, tokens: &mut TokenStream)2935 fn to_tokens(&self, tokens: &mut TokenStream) {
2936 outer_attrs_to_tokens(&self.attrs, tokens);
2937 self.box_token.to_tokens(tokens);
2938 self.expr.to_tokens(tokens);
2939 }
2940 }
2941
2942 #[cfg(feature = "full")]
2943 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
2944 impl ToTokens for ExprArray {
to_tokens(&self, tokens: &mut TokenStream)2945 fn to_tokens(&self, tokens: &mut TokenStream) {
2946 outer_attrs_to_tokens(&self.attrs, tokens);
2947 self.bracket_token.surround(tokens, |tokens| {
2948 inner_attrs_to_tokens(&self.attrs, tokens);
2949 self.elems.to_tokens(tokens);
2950 });
2951 }
2952 }
2953
2954 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
2955 impl ToTokens for ExprCall {
to_tokens(&self, tokens: &mut TokenStream)2956 fn to_tokens(&self, tokens: &mut TokenStream) {
2957 outer_attrs_to_tokens(&self.attrs, tokens);
2958 self.func.to_tokens(tokens);
2959 self.paren_token.surround(tokens, |tokens| {
2960 self.args.to_tokens(tokens);
2961 });
2962 }
2963 }
2964
2965 #[cfg(feature = "full")]
2966 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
2967 impl ToTokens for ExprMethodCall {
to_tokens(&self, tokens: &mut TokenStream)2968 fn to_tokens(&self, tokens: &mut TokenStream) {
2969 outer_attrs_to_tokens(&self.attrs, tokens);
2970 self.receiver.to_tokens(tokens);
2971 self.dot_token.to_tokens(tokens);
2972 self.method.to_tokens(tokens);
2973 self.turbofish.to_tokens(tokens);
2974 self.paren_token.surround(tokens, |tokens| {
2975 self.args.to_tokens(tokens);
2976 });
2977 }
2978 }
2979
2980 #[cfg(feature = "full")]
2981 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
2982 impl ToTokens for MethodTurbofish {
to_tokens(&self, tokens: &mut TokenStream)2983 fn to_tokens(&self, tokens: &mut TokenStream) {
2984 self.colon2_token.to_tokens(tokens);
2985 self.lt_token.to_tokens(tokens);
2986 self.args.to_tokens(tokens);
2987 self.gt_token.to_tokens(tokens);
2988 }
2989 }
2990
2991 #[cfg(feature = "full")]
2992 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
2993 impl ToTokens for GenericMethodArgument {
to_tokens(&self, tokens: &mut TokenStream)2994 fn to_tokens(&self, tokens: &mut TokenStream) {
2995 match self {
2996 GenericMethodArgument::Type(t) => t.to_tokens(tokens),
2997 GenericMethodArgument::Const(c) => c.to_tokens(tokens),
2998 }
2999 }
3000 }
3001
3002 #[cfg(feature = "full")]
3003 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3004 impl ToTokens for ExprTuple {
to_tokens(&self, tokens: &mut TokenStream)3005 fn to_tokens(&self, tokens: &mut TokenStream) {
3006 outer_attrs_to_tokens(&self.attrs, tokens);
3007 self.paren_token.surround(tokens, |tokens| {
3008 inner_attrs_to_tokens(&self.attrs, tokens);
3009 self.elems.to_tokens(tokens);
3010 // If we only have one argument, we need a trailing comma to
3011 // distinguish ExprTuple from ExprParen.
3012 if self.elems.len() == 1 && !self.elems.trailing_punct() {
3013 <Token![,]>::default().to_tokens(tokens);
3014 }
3015 });
3016 }
3017 }
3018
3019 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3020 impl ToTokens for ExprBinary {
to_tokens(&self, tokens: &mut TokenStream)3021 fn to_tokens(&self, tokens: &mut TokenStream) {
3022 outer_attrs_to_tokens(&self.attrs, tokens);
3023 self.left.to_tokens(tokens);
3024 self.op.to_tokens(tokens);
3025 self.right.to_tokens(tokens);
3026 }
3027 }
3028
3029 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3030 impl ToTokens for ExprUnary {
to_tokens(&self, tokens: &mut TokenStream)3031 fn to_tokens(&self, tokens: &mut TokenStream) {
3032 outer_attrs_to_tokens(&self.attrs, tokens);
3033 self.op.to_tokens(tokens);
3034 self.expr.to_tokens(tokens);
3035 }
3036 }
3037
3038 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3039 impl ToTokens for ExprLit {
to_tokens(&self, tokens: &mut TokenStream)3040 fn to_tokens(&self, tokens: &mut TokenStream) {
3041 outer_attrs_to_tokens(&self.attrs, tokens);
3042 self.lit.to_tokens(tokens);
3043 }
3044 }
3045
3046 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3047 impl ToTokens for ExprCast {
to_tokens(&self, tokens: &mut TokenStream)3048 fn to_tokens(&self, tokens: &mut TokenStream) {
3049 outer_attrs_to_tokens(&self.attrs, tokens);
3050 self.expr.to_tokens(tokens);
3051 self.as_token.to_tokens(tokens);
3052 self.ty.to_tokens(tokens);
3053 }
3054 }
3055
3056 #[cfg(feature = "full")]
3057 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3058 impl ToTokens for ExprType {
to_tokens(&self, tokens: &mut TokenStream)3059 fn to_tokens(&self, tokens: &mut TokenStream) {
3060 outer_attrs_to_tokens(&self.attrs, tokens);
3061 self.expr.to_tokens(tokens);
3062 self.colon_token.to_tokens(tokens);
3063 self.ty.to_tokens(tokens);
3064 }
3065 }
3066
3067 #[cfg(feature = "full")]
maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>)3068 fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>) {
3069 if let Some((else_token, else_)) = else_ {
3070 else_token.to_tokens(tokens);
3071
3072 // If we are not one of the valid expressions to exist in an else
3073 // clause, wrap ourselves in a block.
3074 match **else_ {
3075 Expr::If(_) | Expr::Block(_) => {
3076 else_.to_tokens(tokens);
3077 }
3078 _ => {
3079 token::Brace::default().surround(tokens, |tokens| {
3080 else_.to_tokens(tokens);
3081 });
3082 }
3083 }
3084 }
3085 }
3086
3087 #[cfg(feature = "full")]
3088 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3089 impl ToTokens for ExprLet {
to_tokens(&self, tokens: &mut TokenStream)3090 fn to_tokens(&self, tokens: &mut TokenStream) {
3091 outer_attrs_to_tokens(&self.attrs, tokens);
3092 self.let_token.to_tokens(tokens);
3093 self.pat.to_tokens(tokens);
3094 self.eq_token.to_tokens(tokens);
3095 wrap_bare_struct(tokens, &self.expr);
3096 }
3097 }
3098
3099 #[cfg(feature = "full")]
3100 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3101 impl ToTokens for ExprIf {
to_tokens(&self, tokens: &mut TokenStream)3102 fn to_tokens(&self, tokens: &mut TokenStream) {
3103 outer_attrs_to_tokens(&self.attrs, tokens);
3104 self.if_token.to_tokens(tokens);
3105 wrap_bare_struct(tokens, &self.cond);
3106 self.then_branch.to_tokens(tokens);
3107 maybe_wrap_else(tokens, &self.else_branch);
3108 }
3109 }
3110
3111 #[cfg(feature = "full")]
3112 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3113 impl ToTokens for ExprWhile {
to_tokens(&self, tokens: &mut TokenStream)3114 fn to_tokens(&self, tokens: &mut TokenStream) {
3115 outer_attrs_to_tokens(&self.attrs, tokens);
3116 self.label.to_tokens(tokens);
3117 self.while_token.to_tokens(tokens);
3118 wrap_bare_struct(tokens, &self.cond);
3119 self.body.brace_token.surround(tokens, |tokens| {
3120 inner_attrs_to_tokens(&self.attrs, tokens);
3121 tokens.append_all(&self.body.stmts);
3122 });
3123 }
3124 }
3125
3126 #[cfg(feature = "full")]
3127 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3128 impl ToTokens for ExprForLoop {
to_tokens(&self, tokens: &mut TokenStream)3129 fn to_tokens(&self, tokens: &mut TokenStream) {
3130 outer_attrs_to_tokens(&self.attrs, tokens);
3131 self.label.to_tokens(tokens);
3132 self.for_token.to_tokens(tokens);
3133 self.pat.to_tokens(tokens);
3134 self.in_token.to_tokens(tokens);
3135 wrap_bare_struct(tokens, &self.expr);
3136 self.body.brace_token.surround(tokens, |tokens| {
3137 inner_attrs_to_tokens(&self.attrs, tokens);
3138 tokens.append_all(&self.body.stmts);
3139 });
3140 }
3141 }
3142
3143 #[cfg(feature = "full")]
3144 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3145 impl ToTokens for ExprLoop {
to_tokens(&self, tokens: &mut TokenStream)3146 fn to_tokens(&self, tokens: &mut TokenStream) {
3147 outer_attrs_to_tokens(&self.attrs, tokens);
3148 self.label.to_tokens(tokens);
3149 self.loop_token.to_tokens(tokens);
3150 self.body.brace_token.surround(tokens, |tokens| {
3151 inner_attrs_to_tokens(&self.attrs, tokens);
3152 tokens.append_all(&self.body.stmts);
3153 });
3154 }
3155 }
3156
3157 #[cfg(feature = "full")]
3158 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3159 impl ToTokens for ExprMatch {
to_tokens(&self, tokens: &mut TokenStream)3160 fn to_tokens(&self, tokens: &mut TokenStream) {
3161 outer_attrs_to_tokens(&self.attrs, tokens);
3162 self.match_token.to_tokens(tokens);
3163 wrap_bare_struct(tokens, &self.expr);
3164 self.brace_token.surround(tokens, |tokens| {
3165 inner_attrs_to_tokens(&self.attrs, tokens);
3166 for (i, arm) in self.arms.iter().enumerate() {
3167 arm.to_tokens(tokens);
3168 // Ensure that we have a comma after a non-block arm, except
3169 // for the last one.
3170 let is_last = i == self.arms.len() - 1;
3171 if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() {
3172 <Token![,]>::default().to_tokens(tokens);
3173 }
3174 }
3175 });
3176 }
3177 }
3178
3179 #[cfg(feature = "full")]
3180 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3181 impl ToTokens for ExprAsync {
to_tokens(&self, tokens: &mut TokenStream)3182 fn to_tokens(&self, tokens: &mut TokenStream) {
3183 outer_attrs_to_tokens(&self.attrs, tokens);
3184 self.async_token.to_tokens(tokens);
3185 self.capture.to_tokens(tokens);
3186 self.block.to_tokens(tokens);
3187 }
3188 }
3189
3190 #[cfg(feature = "full")]
3191 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3192 impl ToTokens for ExprAwait {
to_tokens(&self, tokens: &mut TokenStream)3193 fn to_tokens(&self, tokens: &mut TokenStream) {
3194 outer_attrs_to_tokens(&self.attrs, tokens);
3195 self.base.to_tokens(tokens);
3196 self.dot_token.to_tokens(tokens);
3197 self.await_token.to_tokens(tokens);
3198 }
3199 }
3200
3201 #[cfg(feature = "full")]
3202 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3203 impl ToTokens for ExprTryBlock {
to_tokens(&self, tokens: &mut TokenStream)3204 fn to_tokens(&self, tokens: &mut TokenStream) {
3205 outer_attrs_to_tokens(&self.attrs, tokens);
3206 self.try_token.to_tokens(tokens);
3207 self.block.to_tokens(tokens);
3208 }
3209 }
3210
3211 #[cfg(feature = "full")]
3212 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3213 impl ToTokens for ExprYield {
to_tokens(&self, tokens: &mut TokenStream)3214 fn to_tokens(&self, tokens: &mut TokenStream) {
3215 outer_attrs_to_tokens(&self.attrs, tokens);
3216 self.yield_token.to_tokens(tokens);
3217 self.expr.to_tokens(tokens);
3218 }
3219 }
3220
3221 #[cfg(feature = "full")]
3222 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3223 impl ToTokens for ExprClosure {
to_tokens(&self, tokens: &mut TokenStream)3224 fn to_tokens(&self, tokens: &mut TokenStream) {
3225 outer_attrs_to_tokens(&self.attrs, tokens);
3226 self.asyncness.to_tokens(tokens);
3227 self.movability.to_tokens(tokens);
3228 self.capture.to_tokens(tokens);
3229 self.or1_token.to_tokens(tokens);
3230 self.inputs.to_tokens(tokens);
3231 self.or2_token.to_tokens(tokens);
3232 self.output.to_tokens(tokens);
3233 self.body.to_tokens(tokens);
3234 }
3235 }
3236
3237 #[cfg(feature = "full")]
3238 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3239 impl ToTokens for ExprUnsafe {
to_tokens(&self, tokens: &mut TokenStream)3240 fn to_tokens(&self, tokens: &mut TokenStream) {
3241 outer_attrs_to_tokens(&self.attrs, tokens);
3242 self.unsafe_token.to_tokens(tokens);
3243 self.block.brace_token.surround(tokens, |tokens| {
3244 inner_attrs_to_tokens(&self.attrs, tokens);
3245 tokens.append_all(&self.block.stmts);
3246 });
3247 }
3248 }
3249
3250 #[cfg(feature = "full")]
3251 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3252 impl ToTokens for ExprBlock {
to_tokens(&self, tokens: &mut TokenStream)3253 fn to_tokens(&self, tokens: &mut TokenStream) {
3254 outer_attrs_to_tokens(&self.attrs, tokens);
3255 self.label.to_tokens(tokens);
3256 self.block.brace_token.surround(tokens, |tokens| {
3257 inner_attrs_to_tokens(&self.attrs, tokens);
3258 tokens.append_all(&self.block.stmts);
3259 });
3260 }
3261 }
3262
3263 #[cfg(feature = "full")]
3264 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3265 impl ToTokens for ExprAssign {
to_tokens(&self, tokens: &mut TokenStream)3266 fn to_tokens(&self, tokens: &mut TokenStream) {
3267 outer_attrs_to_tokens(&self.attrs, tokens);
3268 self.left.to_tokens(tokens);
3269 self.eq_token.to_tokens(tokens);
3270 self.right.to_tokens(tokens);
3271 }
3272 }
3273
3274 #[cfg(feature = "full")]
3275 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3276 impl ToTokens for ExprAssignOp {
to_tokens(&self, tokens: &mut TokenStream)3277 fn to_tokens(&self, tokens: &mut TokenStream) {
3278 outer_attrs_to_tokens(&self.attrs, tokens);
3279 self.left.to_tokens(tokens);
3280 self.op.to_tokens(tokens);
3281 self.right.to_tokens(tokens);
3282 }
3283 }
3284
3285 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3286 impl ToTokens for ExprField {
to_tokens(&self, tokens: &mut TokenStream)3287 fn to_tokens(&self, tokens: &mut TokenStream) {
3288 outer_attrs_to_tokens(&self.attrs, tokens);
3289 self.base.to_tokens(tokens);
3290 self.dot_token.to_tokens(tokens);
3291 self.member.to_tokens(tokens);
3292 }
3293 }
3294
3295 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3296 impl ToTokens for Member {
to_tokens(&self, tokens: &mut TokenStream)3297 fn to_tokens(&self, tokens: &mut TokenStream) {
3298 match self {
3299 Member::Named(ident) => ident.to_tokens(tokens),
3300 Member::Unnamed(index) => index.to_tokens(tokens),
3301 }
3302 }
3303 }
3304
3305 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3306 impl ToTokens for Index {
to_tokens(&self, tokens: &mut TokenStream)3307 fn to_tokens(&self, tokens: &mut TokenStream) {
3308 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
3309 lit.set_span(self.span);
3310 tokens.append(lit);
3311 }
3312 }
3313
3314 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3315 impl ToTokens for ExprIndex {
to_tokens(&self, tokens: &mut TokenStream)3316 fn to_tokens(&self, tokens: &mut TokenStream) {
3317 outer_attrs_to_tokens(&self.attrs, tokens);
3318 self.expr.to_tokens(tokens);
3319 self.bracket_token.surround(tokens, |tokens| {
3320 self.index.to_tokens(tokens);
3321 });
3322 }
3323 }
3324
3325 #[cfg(feature = "full")]
3326 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3327 impl ToTokens for ExprRange {
to_tokens(&self, tokens: &mut TokenStream)3328 fn to_tokens(&self, tokens: &mut TokenStream) {
3329 outer_attrs_to_tokens(&self.attrs, tokens);
3330 self.from.to_tokens(tokens);
3331 match &self.limits {
3332 RangeLimits::HalfOpen(t) => t.to_tokens(tokens),
3333 RangeLimits::Closed(t) => t.to_tokens(tokens),
3334 }
3335 self.to.to_tokens(tokens);
3336 }
3337 }
3338
3339 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3340 impl ToTokens for ExprPath {
to_tokens(&self, tokens: &mut TokenStream)3341 fn to_tokens(&self, tokens: &mut TokenStream) {
3342 outer_attrs_to_tokens(&self.attrs, tokens);
3343 private::print_path(tokens, &self.qself, &self.path);
3344 }
3345 }
3346
3347 #[cfg(feature = "full")]
3348 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3349 impl ToTokens for ExprReference {
to_tokens(&self, tokens: &mut TokenStream)3350 fn to_tokens(&self, tokens: &mut TokenStream) {
3351 outer_attrs_to_tokens(&self.attrs, tokens);
3352 self.and_token.to_tokens(tokens);
3353 self.mutability.to_tokens(tokens);
3354 self.expr.to_tokens(tokens);
3355 }
3356 }
3357
3358 #[cfg(feature = "full")]
3359 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3360 impl ToTokens for ExprBreak {
to_tokens(&self, tokens: &mut TokenStream)3361 fn to_tokens(&self, tokens: &mut TokenStream) {
3362 outer_attrs_to_tokens(&self.attrs, tokens);
3363 self.break_token.to_tokens(tokens);
3364 self.label.to_tokens(tokens);
3365 self.expr.to_tokens(tokens);
3366 }
3367 }
3368
3369 #[cfg(feature = "full")]
3370 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3371 impl ToTokens for ExprContinue {
to_tokens(&self, tokens: &mut TokenStream)3372 fn to_tokens(&self, tokens: &mut TokenStream) {
3373 outer_attrs_to_tokens(&self.attrs, tokens);
3374 self.continue_token.to_tokens(tokens);
3375 self.label.to_tokens(tokens);
3376 }
3377 }
3378
3379 #[cfg(feature = "full")]
3380 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3381 impl ToTokens for ExprReturn {
to_tokens(&self, tokens: &mut TokenStream)3382 fn to_tokens(&self, tokens: &mut TokenStream) {
3383 outer_attrs_to_tokens(&self.attrs, tokens);
3384 self.return_token.to_tokens(tokens);
3385 self.expr.to_tokens(tokens);
3386 }
3387 }
3388
3389 #[cfg(feature = "full")]
3390 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3391 impl ToTokens for ExprMacro {
to_tokens(&self, tokens: &mut TokenStream)3392 fn to_tokens(&self, tokens: &mut TokenStream) {
3393 outer_attrs_to_tokens(&self.attrs, tokens);
3394 self.mac.to_tokens(tokens);
3395 }
3396 }
3397
3398 #[cfg(feature = "full")]
3399 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3400 impl ToTokens for ExprStruct {
to_tokens(&self, tokens: &mut TokenStream)3401 fn to_tokens(&self, tokens: &mut TokenStream) {
3402 outer_attrs_to_tokens(&self.attrs, tokens);
3403 self.path.to_tokens(tokens);
3404 self.brace_token.surround(tokens, |tokens| {
3405 inner_attrs_to_tokens(&self.attrs, tokens);
3406 self.fields.to_tokens(tokens);
3407 if let Some(dot2_token) = &self.dot2_token {
3408 dot2_token.to_tokens(tokens);
3409 } else if self.rest.is_some() {
3410 Token![..](Span::call_site()).to_tokens(tokens);
3411 }
3412 self.rest.to_tokens(tokens);
3413 });
3414 }
3415 }
3416
3417 #[cfg(feature = "full")]
3418 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3419 impl ToTokens for ExprRepeat {
to_tokens(&self, tokens: &mut TokenStream)3420 fn to_tokens(&self, tokens: &mut TokenStream) {
3421 outer_attrs_to_tokens(&self.attrs, tokens);
3422 self.bracket_token.surround(tokens, |tokens| {
3423 inner_attrs_to_tokens(&self.attrs, tokens);
3424 self.expr.to_tokens(tokens);
3425 self.semi_token.to_tokens(tokens);
3426 self.len.to_tokens(tokens);
3427 });
3428 }
3429 }
3430
3431 #[cfg(feature = "full")]
3432 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3433 impl ToTokens for ExprGroup {
to_tokens(&self, tokens: &mut TokenStream)3434 fn to_tokens(&self, tokens: &mut TokenStream) {
3435 outer_attrs_to_tokens(&self.attrs, tokens);
3436 self.group_token.surround(tokens, |tokens| {
3437 self.expr.to_tokens(tokens);
3438 });
3439 }
3440 }
3441
3442 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3443 impl ToTokens for ExprParen {
to_tokens(&self, tokens: &mut TokenStream)3444 fn to_tokens(&self, tokens: &mut TokenStream) {
3445 outer_attrs_to_tokens(&self.attrs, tokens);
3446 self.paren_token.surround(tokens, |tokens| {
3447 inner_attrs_to_tokens(&self.attrs, tokens);
3448 self.expr.to_tokens(tokens);
3449 });
3450 }
3451 }
3452
3453 #[cfg(feature = "full")]
3454 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3455 impl ToTokens for ExprTry {
to_tokens(&self, tokens: &mut TokenStream)3456 fn to_tokens(&self, tokens: &mut TokenStream) {
3457 outer_attrs_to_tokens(&self.attrs, tokens);
3458 self.expr.to_tokens(tokens);
3459 self.question_token.to_tokens(tokens);
3460 }
3461 }
3462
3463 #[cfg(feature = "full")]
3464 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3465 impl ToTokens for Label {
to_tokens(&self, tokens: &mut TokenStream)3466 fn to_tokens(&self, tokens: &mut TokenStream) {
3467 self.name.to_tokens(tokens);
3468 self.colon_token.to_tokens(tokens);
3469 }
3470 }
3471
3472 #[cfg(feature = "full")]
3473 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3474 impl ToTokens for FieldValue {
to_tokens(&self, tokens: &mut TokenStream)3475 fn to_tokens(&self, tokens: &mut TokenStream) {
3476 outer_attrs_to_tokens(&self.attrs, tokens);
3477 self.member.to_tokens(tokens);
3478 if let Some(colon_token) = &self.colon_token {
3479 colon_token.to_tokens(tokens);
3480 self.expr.to_tokens(tokens);
3481 }
3482 }
3483 }
3484
3485 #[cfg(feature = "full")]
3486 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3487 impl ToTokens for Arm {
to_tokens(&self, tokens: &mut TokenStream)3488 fn to_tokens(&self, tokens: &mut TokenStream) {
3489 tokens.append_all(&self.attrs);
3490 self.pat.to_tokens(tokens);
3491 if let Some((if_token, guard)) = &self.guard {
3492 if_token.to_tokens(tokens);
3493 guard.to_tokens(tokens);
3494 }
3495 self.fat_arrow_token.to_tokens(tokens);
3496 self.body.to_tokens(tokens);
3497 self.comma.to_tokens(tokens);
3498 }
3499 }
3500 }
3501