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 Eq for Member {}
855
856 impl PartialEq for Member {
eq(&self, other: &Self) -> bool857 fn eq(&self, other: &Self) -> bool {
858 match (self, other) {
859 (Member::Named(this), Member::Named(other)) => this == other,
860 (Member::Unnamed(this), Member::Unnamed(other)) => this == other,
861 _ => false,
862 }
863 }
864 }
865
866 impl Hash for Member {
hash<H: Hasher>(&self, state: &mut H)867 fn hash<H: Hasher>(&self, state: &mut H) {
868 match self {
869 Member::Named(m) => m.hash(state),
870 Member::Unnamed(m) => m.hash(state),
871 }
872 }
873 }
874
875 #[cfg(feature = "printing")]
876 impl IdentFragment for Member {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result877 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
878 match self {
879 Member::Named(m) => Display::fmt(m, formatter),
880 Member::Unnamed(m) => Display::fmt(&m.index, formatter),
881 }
882 }
883
span(&self) -> Option<Span>884 fn span(&self) -> Option<Span> {
885 match self {
886 Member::Named(m) => Some(m.span()),
887 Member::Unnamed(m) => Some(m.span),
888 }
889 }
890 }
891
892 ast_struct! {
893 /// The index of an unnamed tuple struct field.
894 ///
895 /// *This type is available only if Syn is built with the `"derive"` or `"full"`
896 /// feature.*
897 #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))]
898 pub struct Index {
899 pub index: u32,
900 pub span: Span,
901 }
902 }
903
904 impl From<usize> for Index {
from(index: usize) -> Index905 fn from(index: usize) -> Index {
906 assert!(index < u32::max_value() as usize);
907 Index {
908 index: index as u32,
909 span: Span::call_site(),
910 }
911 }
912 }
913
914 impl Eq for Index {}
915
916 impl PartialEq for Index {
eq(&self, other: &Self) -> bool917 fn eq(&self, other: &Self) -> bool {
918 self.index == other.index
919 }
920 }
921
922 impl Hash for Index {
hash<H: Hasher>(&self, state: &mut H)923 fn hash<H: Hasher>(&self, state: &mut H) {
924 self.index.hash(state);
925 }
926 }
927
928 #[cfg(feature = "printing")]
929 impl IdentFragment for Index {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result930 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
931 Display::fmt(&self.index, formatter)
932 }
933
span(&self) -> Option<Span>934 fn span(&self) -> Option<Span> {
935 Some(self.span)
936 }
937 }
938
939 #[cfg(feature = "full")]
940 ast_struct! {
941 /// The `::<>` explicit type parameters passed to a method call:
942 /// `parse::<u64>()`.
943 ///
944 /// *This type is available only if Syn is built with the `"full"` feature.*
945 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
946 pub struct MethodTurbofish {
947 pub colon2_token: Token![::],
948 pub lt_token: Token![<],
949 pub args: Punctuated<GenericMethodArgument, Token![,]>,
950 pub gt_token: Token![>],
951 }
952 }
953
954 #[cfg(feature = "full")]
955 ast_enum! {
956 /// An individual generic argument to a method, like `T`.
957 ///
958 /// *This type is available only if Syn is built with the `"full"` feature.*
959 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
960 pub enum GenericMethodArgument {
961 /// A type argument.
962 Type(Type),
963 /// A const expression. Must be inside of a block.
964 ///
965 /// NOTE: Identity expressions are represented as Type arguments, as
966 /// they are indistinguishable syntactically.
967 Const(Expr),
968 }
969 }
970
971 #[cfg(feature = "full")]
972 ast_struct! {
973 /// A field-value pair in a struct literal.
974 ///
975 /// *This type is available only if Syn is built with the `"full"` feature.*
976 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
977 pub struct FieldValue {
978 /// Attributes tagged on the field.
979 pub attrs: Vec<Attribute>,
980
981 /// Name or index of the field.
982 pub member: Member,
983
984 /// The colon in `Struct { x: x }`. If written in shorthand like
985 /// `Struct { x }`, there is no colon.
986 pub colon_token: Option<Token![:]>,
987
988 /// Value of the field.
989 pub expr: Expr,
990 }
991 }
992
993 #[cfg(feature = "full")]
994 ast_struct! {
995 /// A lifetime labeling a `for`, `while`, or `loop`.
996 ///
997 /// *This type is available only if Syn is built with the `"full"` feature.*
998 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
999 pub struct Label {
1000 pub name: Lifetime,
1001 pub colon_token: Token![:],
1002 }
1003 }
1004
1005 #[cfg(feature = "full")]
1006 ast_struct! {
1007 /// One arm of a `match` expression: `0...10 => { return true; }`.
1008 ///
1009 /// As in:
1010 ///
1011 /// ```
1012 /// # fn f() -> bool {
1013 /// # let n = 0;
1014 /// match n {
1015 /// 0...10 => {
1016 /// return true;
1017 /// }
1018 /// // ...
1019 /// # _ => {}
1020 /// }
1021 /// # false
1022 /// # }
1023 /// ```
1024 ///
1025 /// *This type is available only if Syn is built with the `"full"` feature.*
1026 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
1027 pub struct Arm {
1028 pub attrs: Vec<Attribute>,
1029 pub pat: Pat,
1030 pub guard: Option<(Token![if], Box<Expr>)>,
1031 pub fat_arrow_token: Token![=>],
1032 pub body: Box<Expr>,
1033 pub comma: Option<Token![,]>,
1034 }
1035 }
1036
1037 #[cfg(feature = "full")]
1038 ast_enum! {
1039 /// Limit types of a range, inclusive or exclusive.
1040 ///
1041 /// *This type is available only if Syn is built with the `"full"` feature.*
1042 #[cfg_attr(doc_cfg, doc(cfg(feature = "full")))]
1043 pub enum RangeLimits {
1044 /// Inclusive at the beginning, exclusive at the end.
1045 HalfOpen(Token![..]),
1046 /// Inclusive at the beginning and end.
1047 Closed(Token![..=]),
1048 }
1049 }
1050
1051 #[cfg(any(feature = "parsing", feature = "printing"))]
1052 #[cfg(feature = "full")]
requires_terminator(expr: &Expr) -> bool1053 pub(crate) fn requires_terminator(expr: &Expr) -> bool {
1054 // see https://github.com/rust-lang/rust/blob/2679c38fc/src/librustc_ast/util/classify.rs#L7-L25
1055 match *expr {
1056 Expr::Unsafe(..)
1057 | Expr::Block(..)
1058 | Expr::If(..)
1059 | Expr::Match(..)
1060 | Expr::While(..)
1061 | Expr::Loop(..)
1062 | Expr::ForLoop(..)
1063 | Expr::Async(..)
1064 | Expr::TryBlock(..) => false,
1065 _ => true,
1066 }
1067 }
1068
1069 #[cfg(feature = "parsing")]
1070 pub(crate) mod parsing {
1071 use super::*;
1072 use crate::parse::{Parse, ParseStream, Result};
1073 use crate::path;
1074 #[cfg(feature = "full")]
1075 use proc_macro2::TokenTree;
1076 use std::cmp::Ordering;
1077
1078 crate::custom_keyword!(raw);
1079
1080 // When we're parsing expressions which occur before blocks, like in an if
1081 // statement's condition, we cannot parse a struct literal.
1082 //
1083 // Struct literals are ambiguous in certain positions
1084 // https://github.com/rust-lang/rfcs/pull/92
1085 pub struct AllowStruct(bool);
1086
1087 enum Precedence {
1088 Any,
1089 Assign,
1090 Range,
1091 Or,
1092 And,
1093 Compare,
1094 BitOr,
1095 BitXor,
1096 BitAnd,
1097 Shift,
1098 Arithmetic,
1099 Term,
1100 Cast,
1101 }
1102
1103 impl Precedence {
of(op: &BinOp) -> Self1104 fn of(op: &BinOp) -> Self {
1105 match *op {
1106 BinOp::Add(_) | BinOp::Sub(_) => Precedence::Arithmetic,
1107 BinOp::Mul(_) | BinOp::Div(_) | BinOp::Rem(_) => Precedence::Term,
1108 BinOp::And(_) => Precedence::And,
1109 BinOp::Or(_) => Precedence::Or,
1110 BinOp::BitXor(_) => Precedence::BitXor,
1111 BinOp::BitAnd(_) => Precedence::BitAnd,
1112 BinOp::BitOr(_) => Precedence::BitOr,
1113 BinOp::Shl(_) | BinOp::Shr(_) => Precedence::Shift,
1114 BinOp::Eq(_)
1115 | BinOp::Lt(_)
1116 | BinOp::Le(_)
1117 | BinOp::Ne(_)
1118 | BinOp::Ge(_)
1119 | BinOp::Gt(_) => Precedence::Compare,
1120 BinOp::AddEq(_)
1121 | BinOp::SubEq(_)
1122 | BinOp::MulEq(_)
1123 | BinOp::DivEq(_)
1124 | BinOp::RemEq(_)
1125 | BinOp::BitXorEq(_)
1126 | BinOp::BitAndEq(_)
1127 | BinOp::BitOrEq(_)
1128 | BinOp::ShlEq(_)
1129 | BinOp::ShrEq(_) => Precedence::Assign,
1130 }
1131 }
1132 }
1133
1134 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
1135 impl Parse for Expr {
parse(input: ParseStream) -> Result<Self>1136 fn parse(input: ParseStream) -> Result<Self> {
1137 ambiguous_expr(input, AllowStruct(true))
1138 }
1139 }
1140
1141 impl Expr {
1142 /// An alternative to the primary `Expr::parse` parser (from the
1143 /// [`Parse`] trait) for ambiguous syntactic positions in which a
1144 /// trailing brace should not be taken as part of the expression.
1145 ///
1146 /// Rust grammar has an ambiguity where braces sometimes turn a path
1147 /// expression into a struct initialization and sometimes do not. In the
1148 /// following code, the expression `S {}` is one expression. Presumably
1149 /// there is an empty struct `struct S {}` defined somewhere which it is
1150 /// instantiating.
1151 ///
1152 /// ```
1153 /// # struct S;
1154 /// # impl std::ops::Deref for S {
1155 /// # type Target = bool;
1156 /// # fn deref(&self) -> &Self::Target {
1157 /// # &true
1158 /// # }
1159 /// # }
1160 /// let _ = *S {};
1161 ///
1162 /// // parsed by rustc as: `*(S {})`
1163 /// ```
1164 ///
1165 /// We would want to parse the above using `Expr::parse` after the `=`
1166 /// token.
1167 ///
1168 /// But in the following, `S {}` is *not* a struct init expression.
1169 ///
1170 /// ```
1171 /// # const S: &bool = &true;
1172 /// if *S {} {}
1173 ///
1174 /// // parsed by rustc as:
1175 /// //
1176 /// // if (*S) {
1177 /// // /* empty block */
1178 /// // }
1179 /// // {
1180 /// // /* another empty block */
1181 /// // }
1182 /// ```
1183 ///
1184 /// For that reason we would want to parse if-conditions using
1185 /// `Expr::parse_without_eager_brace` after the `if` token. Same for
1186 /// similar syntactic positions such as the condition expr after a
1187 /// `while` token or the expr at the top of a `match`.
1188 ///
1189 /// The Rust grammar's choices around which way this ambiguity is
1190 /// resolved at various syntactic positions is fairly arbitrary. Really
1191 /// either parse behavior could work in most positions, and language
1192 /// designers just decide each case based on which is more likely to be
1193 /// what the programmer had in mind most of the time.
1194 ///
1195 /// ```
1196 /// # struct S;
1197 /// # fn doc() -> S {
1198 /// if return S {} {}
1199 /// # unreachable!()
1200 /// # }
1201 ///
1202 /// // parsed by rustc as:
1203 /// //
1204 /// // if (return (S {})) {
1205 /// // }
1206 /// //
1207 /// // but could equally well have been this other arbitrary choice:
1208 /// //
1209 /// // if (return S) {
1210 /// // }
1211 /// // {}
1212 /// ```
1213 ///
1214 /// Note the grammar ambiguity on trailing braces is distinct from
1215 /// precedence and is not captured by assigning a precedence level to
1216 /// the braced struct init expr in relation to other operators. This can
1217 /// be illustrated by `return 0..S {}` vs `match 0..S {}`. The former
1218 /// parses as `return (0..(S {}))` implying tighter precedence for
1219 /// struct init than `..`, while the latter parses as `match (0..S) {}`
1220 /// implying tighter precedence for `..` than struct init, a
1221 /// contradiction.
1222 #[cfg(feature = "full")]
1223 #[cfg_attr(doc_cfg, doc(cfg(all(feature = "full", feature = "parsing"))))]
parse_without_eager_brace(input: ParseStream) -> Result<Expr>1224 pub fn parse_without_eager_brace(input: ParseStream) -> Result<Expr> {
1225 ambiguous_expr(input, AllowStruct(false))
1226 }
1227 }
1228
1229 impl Copy for AllowStruct {}
1230
1231 impl Clone for AllowStruct {
clone(&self) -> Self1232 fn clone(&self) -> Self {
1233 *self
1234 }
1235 }
1236
1237 impl Copy for Precedence {}
1238
1239 impl Clone for Precedence {
clone(&self) -> Self1240 fn clone(&self) -> Self {
1241 *self
1242 }
1243 }
1244
1245 impl PartialEq for Precedence {
eq(&self, other: &Self) -> bool1246 fn eq(&self, other: &Self) -> bool {
1247 *self as u8 == *other as u8
1248 }
1249 }
1250
1251 impl PartialOrd for Precedence {
partial_cmp(&self, other: &Self) -> Option<Ordering>1252 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1253 let this = *self as u8;
1254 let other = *other as u8;
1255 Some(this.cmp(&other))
1256 }
1257 }
1258
1259 #[cfg(feature = "full")]
parse_expr( input: ParseStream, mut lhs: Expr, allow_struct: AllowStruct, base: Precedence, ) -> Result<Expr>1260 fn parse_expr(
1261 input: ParseStream,
1262 mut lhs: Expr,
1263 allow_struct: AllowStruct,
1264 base: Precedence,
1265 ) -> Result<Expr> {
1266 loop {
1267 if input
1268 .fork()
1269 .parse::<BinOp>()
1270 .ok()
1271 .map_or(false, |op| Precedence::of(&op) >= base)
1272 {
1273 let op: BinOp = input.parse()?;
1274 let precedence = Precedence::of(&op);
1275 let mut rhs = unary_expr(input, allow_struct)?;
1276 loop {
1277 let next = peek_precedence(input);
1278 if next > precedence || next == precedence && precedence == Precedence::Assign {
1279 rhs = parse_expr(input, rhs, allow_struct, next)?;
1280 } else {
1281 break;
1282 }
1283 }
1284 lhs = if precedence == Precedence::Assign {
1285 Expr::AssignOp(ExprAssignOp {
1286 attrs: Vec::new(),
1287 left: Box::new(lhs),
1288 op,
1289 right: Box::new(rhs),
1290 })
1291 } else {
1292 Expr::Binary(ExprBinary {
1293 attrs: Vec::new(),
1294 left: Box::new(lhs),
1295 op,
1296 right: Box::new(rhs),
1297 })
1298 };
1299 } else if Precedence::Assign >= base
1300 && input.peek(Token![=])
1301 && !input.peek(Token![==])
1302 && !input.peek(Token![=>])
1303 {
1304 let eq_token: Token![=] = input.parse()?;
1305 let mut rhs = unary_expr(input, allow_struct)?;
1306 loop {
1307 let next = peek_precedence(input);
1308 if next >= Precedence::Assign {
1309 rhs = parse_expr(input, rhs, allow_struct, next)?;
1310 } else {
1311 break;
1312 }
1313 }
1314 lhs = Expr::Assign(ExprAssign {
1315 attrs: Vec::new(),
1316 left: Box::new(lhs),
1317 eq_token,
1318 right: Box::new(rhs),
1319 });
1320 } else if Precedence::Range >= base && input.peek(Token![..]) {
1321 let limits: RangeLimits = input.parse()?;
1322 let rhs = if input.is_empty()
1323 || input.peek(Token![,])
1324 || input.peek(Token![;])
1325 || !allow_struct.0 && input.peek(token::Brace)
1326 {
1327 None
1328 } else {
1329 let mut rhs = unary_expr(input, allow_struct)?;
1330 loop {
1331 let next = peek_precedence(input);
1332 if next > Precedence::Range {
1333 rhs = parse_expr(input, rhs, allow_struct, next)?;
1334 } else {
1335 break;
1336 }
1337 }
1338 Some(rhs)
1339 };
1340 lhs = Expr::Range(ExprRange {
1341 attrs: Vec::new(),
1342 from: Some(Box::new(lhs)),
1343 limits,
1344 to: rhs.map(Box::new),
1345 });
1346 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1347 let as_token: Token![as] = input.parse()?;
1348 let ty = input.call(Type::without_plus)?;
1349 lhs = Expr::Cast(ExprCast {
1350 attrs: Vec::new(),
1351 expr: Box::new(lhs),
1352 as_token,
1353 ty: Box::new(ty),
1354 });
1355 } else if Precedence::Cast >= base && input.peek(Token![:]) && !input.peek(Token![::]) {
1356 let colon_token: Token![:] = input.parse()?;
1357 let ty = input.call(Type::without_plus)?;
1358 lhs = Expr::Type(ExprType {
1359 attrs: Vec::new(),
1360 expr: Box::new(lhs),
1361 colon_token,
1362 ty: Box::new(ty),
1363 });
1364 } else {
1365 break;
1366 }
1367 }
1368 Ok(lhs)
1369 }
1370
1371 #[cfg(not(feature = "full"))]
parse_expr( input: ParseStream, mut lhs: Expr, allow_struct: AllowStruct, base: Precedence, ) -> Result<Expr>1372 fn parse_expr(
1373 input: ParseStream,
1374 mut lhs: Expr,
1375 allow_struct: AllowStruct,
1376 base: Precedence,
1377 ) -> Result<Expr> {
1378 loop {
1379 if input
1380 .fork()
1381 .parse::<BinOp>()
1382 .ok()
1383 .map_or(false, |op| Precedence::of(&op) >= base)
1384 {
1385 let op: BinOp = input.parse()?;
1386 let precedence = Precedence::of(&op);
1387 let mut rhs = unary_expr(input, allow_struct)?;
1388 loop {
1389 let next = peek_precedence(input);
1390 if next > precedence || next == precedence && precedence == Precedence::Assign {
1391 rhs = parse_expr(input, rhs, allow_struct, next)?;
1392 } else {
1393 break;
1394 }
1395 }
1396 lhs = Expr::Binary(ExprBinary {
1397 attrs: Vec::new(),
1398 left: Box::new(lhs),
1399 op,
1400 right: Box::new(rhs),
1401 });
1402 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1403 let as_token: Token![as] = input.parse()?;
1404 let ty = input.call(Type::without_plus)?;
1405 lhs = Expr::Cast(ExprCast {
1406 attrs: Vec::new(),
1407 expr: Box::new(lhs),
1408 as_token,
1409 ty: Box::new(ty),
1410 });
1411 } else {
1412 break;
1413 }
1414 }
1415 Ok(lhs)
1416 }
1417
peek_precedence(input: ParseStream) -> Precedence1418 fn peek_precedence(input: ParseStream) -> Precedence {
1419 if let Ok(op) = input.fork().parse() {
1420 Precedence::of(&op)
1421 } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
1422 Precedence::Assign
1423 } else if input.peek(Token![..]) {
1424 Precedence::Range
1425 } else if input.peek(Token![as])
1426 || cfg!(feature = "full") && input.peek(Token![:]) && !input.peek(Token![::])
1427 {
1428 Precedence::Cast
1429 } else {
1430 Precedence::Any
1431 }
1432 }
1433
1434 // Parse an arbitrary expression.
ambiguous_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr>1435 fn ambiguous_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1436 let lhs = unary_expr(input, allow_struct)?;
1437 parse_expr(input, lhs, allow_struct, Precedence::Any)
1438 }
1439
1440 #[cfg(feature = "full")]
expr_attrs(input: ParseStream) -> Result<Vec<Attribute>>1441 fn expr_attrs(input: ParseStream) -> Result<Vec<Attribute>> {
1442 let mut attrs = Vec::new();
1443 loop {
1444 if input.peek(token::Group) {
1445 let ahead = input.fork();
1446 let group = crate::group::parse_group(&ahead)?;
1447 if !group.content.peek(Token![#]) || group.content.peek2(Token![!]) {
1448 break;
1449 }
1450 let attr = group.content.call(attr::parsing::single_parse_outer)?;
1451 if !group.content.is_empty() {
1452 break;
1453 }
1454 attrs.push(attr);
1455 } else if input.peek(Token![#]) {
1456 attrs.push(input.call(attr::parsing::single_parse_outer)?);
1457 } else {
1458 break;
1459 }
1460 }
1461 Ok(attrs)
1462 }
1463
1464 // <UnOp> <trailer>
1465 // & <trailer>
1466 // &mut <trailer>
1467 // box <trailer>
1468 #[cfg(feature = "full")]
unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr>1469 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1470 let begin = input.fork();
1471 let attrs = input.call(expr_attrs)?;
1472 if input.peek(Token![&]) {
1473 let and_token: Token![&] = input.parse()?;
1474 let raw: Option<raw> =
1475 if input.peek(raw) && (input.peek2(Token![mut]) || input.peek2(Token![const])) {
1476 Some(input.parse()?)
1477 } else {
1478 None
1479 };
1480 let mutability: Option<Token![mut]> = input.parse()?;
1481 if raw.is_some() && mutability.is_none() {
1482 input.parse::<Token![const]>()?;
1483 }
1484 let expr = Box::new(unary_expr(input, allow_struct)?);
1485 if raw.is_some() {
1486 Ok(Expr::Verbatim(verbatim::between(begin, input)))
1487 } else {
1488 Ok(Expr::Reference(ExprReference {
1489 attrs,
1490 and_token,
1491 raw: Reserved::default(),
1492 mutability,
1493 expr,
1494 }))
1495 }
1496 } else if input.peek(Token![box]) {
1497 expr_box(input, attrs, allow_struct).map(Expr::Box)
1498 } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
1499 expr_unary(input, attrs, allow_struct).map(Expr::Unary)
1500 } else {
1501 trailer_expr(attrs, input, allow_struct)
1502 }
1503 }
1504
1505 #[cfg(not(feature = "full"))]
unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr>1506 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1507 if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
1508 Ok(Expr::Unary(ExprUnary {
1509 attrs: Vec::new(),
1510 op: input.parse()?,
1511 expr: Box::new(unary_expr(input, allow_struct)?),
1512 }))
1513 } else {
1514 trailer_expr(input, allow_struct)
1515 }
1516 }
1517
1518 // <atom> (..<args>) ...
1519 // <atom> . <ident> (..<args>) ...
1520 // <atom> . <ident> ...
1521 // <atom> . <lit> ...
1522 // <atom> [ <expr> ] ...
1523 // <atom> ? ...
1524 #[cfg(feature = "full")]
trailer_expr( outer_attrs: Vec<Attribute>, input: ParseStream, allow_struct: AllowStruct, ) -> Result<Expr>1525 fn trailer_expr(
1526 outer_attrs: Vec<Attribute>,
1527 input: ParseStream,
1528 allow_struct: AllowStruct,
1529 ) -> Result<Expr> {
1530 let atom = atom_expr(input, allow_struct)?;
1531 let mut e = trailer_helper(input, atom)?;
1532
1533 let inner_attrs = e.replace_attrs(Vec::new());
1534 let attrs = private::attrs(outer_attrs, inner_attrs);
1535 e.replace_attrs(attrs);
1536 Ok(e)
1537 }
1538
1539 #[cfg(feature = "full")]
trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr>1540 fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
1541 loop {
1542 if input.peek(token::Paren) {
1543 let content;
1544 e = Expr::Call(ExprCall {
1545 attrs: Vec::new(),
1546 func: Box::new(e),
1547 paren_token: parenthesized!(content in input),
1548 args: content.parse_terminated(Expr::parse)?,
1549 });
1550 } else if input.peek(Token![.]) && !input.peek(Token![..]) {
1551 let mut dot_token: Token![.] = input.parse()?;
1552
1553 let await_token: Option<token::Await> = input.parse()?;
1554 if let Some(await_token) = await_token {
1555 e = Expr::Await(ExprAwait {
1556 attrs: Vec::new(),
1557 base: Box::new(e),
1558 dot_token,
1559 await_token,
1560 });
1561 continue;
1562 }
1563
1564 let float_token: Option<LitFloat> = input.parse()?;
1565 if let Some(float_token) = float_token {
1566 if multi_index(&mut e, &mut dot_token, float_token)? {
1567 continue;
1568 }
1569 }
1570
1571 let member: Member = input.parse()?;
1572 let turbofish = if member.is_named() && input.peek(Token![::]) {
1573 Some(MethodTurbofish {
1574 colon2_token: input.parse()?,
1575 lt_token: input.parse()?,
1576 args: {
1577 let mut args = Punctuated::new();
1578 loop {
1579 if input.peek(Token![>]) {
1580 break;
1581 }
1582 let value = input.call(generic_method_argument)?;
1583 args.push_value(value);
1584 if input.peek(Token![>]) {
1585 break;
1586 }
1587 let punct = input.parse()?;
1588 args.push_punct(punct);
1589 }
1590 args
1591 },
1592 gt_token: input.parse()?,
1593 })
1594 } else {
1595 None
1596 };
1597
1598 if turbofish.is_some() || input.peek(token::Paren) {
1599 if let Member::Named(method) = member {
1600 let content;
1601 e = Expr::MethodCall(ExprMethodCall {
1602 attrs: Vec::new(),
1603 receiver: Box::new(e),
1604 dot_token,
1605 method,
1606 turbofish,
1607 paren_token: parenthesized!(content in input),
1608 args: content.parse_terminated(Expr::parse)?,
1609 });
1610 continue;
1611 }
1612 }
1613
1614 e = Expr::Field(ExprField {
1615 attrs: Vec::new(),
1616 base: Box::new(e),
1617 dot_token,
1618 member,
1619 });
1620 } else if input.peek(token::Bracket) {
1621 let content;
1622 e = Expr::Index(ExprIndex {
1623 attrs: Vec::new(),
1624 expr: Box::new(e),
1625 bracket_token: bracketed!(content in input),
1626 index: content.parse()?,
1627 });
1628 } else if input.peek(Token![?]) {
1629 e = Expr::Try(ExprTry {
1630 attrs: Vec::new(),
1631 expr: Box::new(e),
1632 question_token: input.parse()?,
1633 });
1634 } else {
1635 break;
1636 }
1637 }
1638 Ok(e)
1639 }
1640
1641 #[cfg(not(feature = "full"))]
trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr>1642 fn trailer_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1643 let mut e = atom_expr(input, allow_struct)?;
1644
1645 loop {
1646 if input.peek(token::Paren) {
1647 let content;
1648 e = Expr::Call(ExprCall {
1649 attrs: Vec::new(),
1650 func: Box::new(e),
1651 paren_token: parenthesized!(content in input),
1652 args: content.parse_terminated(Expr::parse)?,
1653 });
1654 } else if input.peek(Token![.]) && !input.peek(Token![..]) && !input.peek2(token::Await)
1655 {
1656 let mut dot_token: Token![.] = input.parse()?;
1657 let float_token: Option<LitFloat> = input.parse()?;
1658 if let Some(float_token) = float_token {
1659 if multi_index(&mut e, &mut dot_token, float_token)? {
1660 continue;
1661 }
1662 }
1663 e = Expr::Field(ExprField {
1664 attrs: Vec::new(),
1665 base: Box::new(e),
1666 dot_token,
1667 member: input.parse()?,
1668 });
1669 } else if input.peek(token::Bracket) {
1670 let content;
1671 e = Expr::Index(ExprIndex {
1672 attrs: Vec::new(),
1673 expr: Box::new(e),
1674 bracket_token: bracketed!(content in input),
1675 index: content.parse()?,
1676 });
1677 } else {
1678 break;
1679 }
1680 }
1681
1682 Ok(e)
1683 }
1684
1685 // Parse all atomic expressions which don't have to worry about precedence
1686 // interactions, as they are fully contained.
1687 #[cfg(feature = "full")]
atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr>1688 fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1689 if input.peek(token::Group)
1690 && !input.peek2(Token![::])
1691 && !input.peek2(Token![!])
1692 && !input.peek2(token::Brace)
1693 {
1694 input.call(expr_group).map(Expr::Group)
1695 } else if input.peek(Lit) {
1696 input.parse().map(Expr::Lit)
1697 } else if input.peek(Token![async])
1698 && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
1699 {
1700 input.parse().map(Expr::Async)
1701 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
1702 input.parse().map(Expr::TryBlock)
1703 } else if input.peek(Token![|])
1704 || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1705 || input.peek(Token![static])
1706 || input.peek(Token![move])
1707 {
1708 expr_closure(input, allow_struct).map(Expr::Closure)
1709 } else if input.peek(Ident)
1710 || input.peek(Token![::])
1711 || input.peek(Token![<])
1712 || input.peek(Token![self])
1713 || input.peek(Token![Self])
1714 || input.peek(Token![super])
1715 || input.peek(Token![crate])
1716 {
1717 path_or_macro_or_struct(input, allow_struct)
1718 } else if input.peek(token::Paren) {
1719 paren_or_tuple(input)
1720 } else if input.peek(Token![break]) {
1721 expr_break(input, allow_struct).map(Expr::Break)
1722 } else if input.peek(Token![continue]) {
1723 input.parse().map(Expr::Continue)
1724 } else if input.peek(Token![return]) {
1725 expr_ret(input, allow_struct).map(Expr::Return)
1726 } else if input.peek(token::Bracket) {
1727 array_or_repeat(input)
1728 } else if input.peek(Token![let]) {
1729 input.parse().map(Expr::Let)
1730 } else if input.peek(Token![if]) {
1731 input.parse().map(Expr::If)
1732 } else if input.peek(Token![while]) {
1733 input.parse().map(Expr::While)
1734 } else if input.peek(Token![for]) {
1735 input.parse().map(Expr::ForLoop)
1736 } else if input.peek(Token![loop]) {
1737 input.parse().map(Expr::Loop)
1738 } else if input.peek(Token![match]) {
1739 input.parse().map(Expr::Match)
1740 } else if input.peek(Token![yield]) {
1741 input.parse().map(Expr::Yield)
1742 } else if input.peek(Token![unsafe]) {
1743 input.parse().map(Expr::Unsafe)
1744 } else if input.peek(Token![const]) {
1745 input.call(expr_const).map(Expr::Verbatim)
1746 } else if input.peek(token::Brace) {
1747 input.parse().map(Expr::Block)
1748 } else if input.peek(Token![..]) {
1749 expr_range(input, allow_struct).map(Expr::Range)
1750 } else if input.peek(Token![_]) {
1751 Ok(Expr::Verbatim(TokenStream::from(
1752 input.parse::<TokenTree>()?,
1753 )))
1754 } else if input.peek(Lifetime) {
1755 let the_label: Label = input.parse()?;
1756 let mut expr = if input.peek(Token![while]) {
1757 Expr::While(input.parse()?)
1758 } else if input.peek(Token![for]) {
1759 Expr::ForLoop(input.parse()?)
1760 } else if input.peek(Token![loop]) {
1761 Expr::Loop(input.parse()?)
1762 } else if input.peek(token::Brace) {
1763 Expr::Block(input.parse()?)
1764 } else {
1765 return Err(input.error("expected loop or block expression"));
1766 };
1767 match &mut expr {
1768 Expr::While(ExprWhile { label, .. })
1769 | Expr::ForLoop(ExprForLoop { label, .. })
1770 | Expr::Loop(ExprLoop { label, .. })
1771 | Expr::Block(ExprBlock { label, .. }) => *label = Some(the_label),
1772 _ => unreachable!(),
1773 }
1774 Ok(expr)
1775 } else {
1776 Err(input.error("expected expression"))
1777 }
1778 }
1779
1780 #[cfg(not(feature = "full"))]
atom_expr(input: ParseStream, _allow_struct: AllowStruct) -> Result<Expr>1781 fn atom_expr(input: ParseStream, _allow_struct: AllowStruct) -> Result<Expr> {
1782 if input.peek(Lit) {
1783 input.parse().map(Expr::Lit)
1784 } else if input.peek(token::Paren) {
1785 input.call(expr_paren).map(Expr::Paren)
1786 } else if input.peek(Ident)
1787 || input.peek(Token![::])
1788 || input.peek(Token![<])
1789 || input.peek(Token![self])
1790 || input.peek(Token![Self])
1791 || input.peek(Token![super])
1792 || input.peek(Token![crate])
1793 {
1794 input.parse().map(Expr::Path)
1795 } else {
1796 Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
1797 }
1798 }
1799
1800 #[cfg(feature = "full")]
path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr>1801 fn path_or_macro_or_struct(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1802 let expr: ExprPath = input.parse()?;
1803 if expr.qself.is_some() {
1804 return Ok(Expr::Path(expr));
1805 }
1806
1807 if input.peek(Token![!]) && !input.peek(Token![!=]) {
1808 let mut contains_arguments = false;
1809 for segment in &expr.path.segments {
1810 match segment.arguments {
1811 PathArguments::None => {}
1812 PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => {
1813 contains_arguments = true;
1814 }
1815 }
1816 }
1817
1818 if !contains_arguments {
1819 let bang_token: Token![!] = input.parse()?;
1820 let (delimiter, tokens) = mac::parse_delimiter(input)?;
1821 return Ok(Expr::Macro(ExprMacro {
1822 attrs: Vec::new(),
1823 mac: Macro {
1824 path: expr.path,
1825 bang_token,
1826 delimiter,
1827 tokens,
1828 },
1829 }));
1830 }
1831 }
1832
1833 if allow_struct.0 && input.peek(token::Brace) {
1834 let outer_attrs = Vec::new();
1835 expr_struct_helper(input, outer_attrs, expr.path).map(Expr::Struct)
1836 } else {
1837 Ok(Expr::Path(expr))
1838 }
1839 }
1840
1841 #[cfg(feature = "full")]
1842 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
1843 impl Parse for ExprMacro {
parse(input: ParseStream) -> Result<Self>1844 fn parse(input: ParseStream) -> Result<Self> {
1845 Ok(ExprMacro {
1846 attrs: Vec::new(),
1847 mac: input.parse()?,
1848 })
1849 }
1850 }
1851
1852 #[cfg(feature = "full")]
paren_or_tuple(input: ParseStream) -> Result<Expr>1853 fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
1854 let content;
1855 let paren_token = parenthesized!(content in input);
1856 let inner_attrs = content.call(Attribute::parse_inner)?;
1857 if content.is_empty() {
1858 return Ok(Expr::Tuple(ExprTuple {
1859 attrs: inner_attrs,
1860 paren_token,
1861 elems: Punctuated::new(),
1862 }));
1863 }
1864
1865 let first: Expr = content.parse()?;
1866 if content.is_empty() {
1867 return Ok(Expr::Paren(ExprParen {
1868 attrs: inner_attrs,
1869 paren_token,
1870 expr: Box::new(first),
1871 }));
1872 }
1873
1874 let mut elems = Punctuated::new();
1875 elems.push_value(first);
1876 while !content.is_empty() {
1877 let punct = content.parse()?;
1878 elems.push_punct(punct);
1879 if content.is_empty() {
1880 break;
1881 }
1882 let value = content.parse()?;
1883 elems.push_value(value);
1884 }
1885 Ok(Expr::Tuple(ExprTuple {
1886 attrs: inner_attrs,
1887 paren_token,
1888 elems,
1889 }))
1890 }
1891
1892 #[cfg(feature = "full")]
array_or_repeat(input: ParseStream) -> Result<Expr>1893 fn array_or_repeat(input: ParseStream) -> Result<Expr> {
1894 let content;
1895 let bracket_token = bracketed!(content in input);
1896 let inner_attrs = content.call(Attribute::parse_inner)?;
1897 if content.is_empty() {
1898 return Ok(Expr::Array(ExprArray {
1899 attrs: inner_attrs,
1900 bracket_token,
1901 elems: Punctuated::new(),
1902 }));
1903 }
1904
1905 let first: Expr = content.parse()?;
1906 if content.is_empty() || content.peek(Token![,]) {
1907 let mut elems = Punctuated::new();
1908 elems.push_value(first);
1909 while !content.is_empty() {
1910 let punct = content.parse()?;
1911 elems.push_punct(punct);
1912 if content.is_empty() {
1913 break;
1914 }
1915 let value = content.parse()?;
1916 elems.push_value(value);
1917 }
1918 Ok(Expr::Array(ExprArray {
1919 attrs: inner_attrs,
1920 bracket_token,
1921 elems,
1922 }))
1923 } else if content.peek(Token![;]) {
1924 let semi_token: Token![;] = content.parse()?;
1925 let len: Expr = content.parse()?;
1926 Ok(Expr::Repeat(ExprRepeat {
1927 attrs: inner_attrs,
1928 bracket_token,
1929 expr: Box::new(first),
1930 semi_token,
1931 len: Box::new(len),
1932 }))
1933 } else {
1934 Err(content.error("expected `,` or `;`"))
1935 }
1936 }
1937
1938 #[cfg(feature = "full")]
1939 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
1940 impl Parse for ExprArray {
parse(input: ParseStream) -> Result<Self>1941 fn parse(input: ParseStream) -> Result<Self> {
1942 let content;
1943 let bracket_token = bracketed!(content in input);
1944 let inner_attrs = content.call(Attribute::parse_inner)?;
1945 let mut elems = Punctuated::new();
1946
1947 while !content.is_empty() {
1948 let first: Expr = content.parse()?;
1949 elems.push_value(first);
1950 if content.is_empty() {
1951 break;
1952 }
1953 let punct = content.parse()?;
1954 elems.push_punct(punct);
1955 }
1956
1957 Ok(ExprArray {
1958 attrs: inner_attrs,
1959 bracket_token,
1960 elems,
1961 })
1962 }
1963 }
1964
1965 #[cfg(feature = "full")]
1966 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
1967 impl Parse for ExprRepeat {
parse(input: ParseStream) -> Result<Self>1968 fn parse(input: ParseStream) -> Result<Self> {
1969 let content;
1970 Ok(ExprRepeat {
1971 bracket_token: bracketed!(content in input),
1972 attrs: content.call(Attribute::parse_inner)?,
1973 expr: content.parse()?,
1974 semi_token: content.parse()?,
1975 len: content.parse()?,
1976 })
1977 }
1978 }
1979
1980 #[cfg(feature = "full")]
expr_early(input: ParseStream) -> Result<Expr>1981 pub(crate) fn expr_early(input: ParseStream) -> Result<Expr> {
1982 let mut attrs = input.call(expr_attrs)?;
1983 let mut expr = if input.peek(Token![if]) {
1984 Expr::If(input.parse()?)
1985 } else if input.peek(Token![while]) {
1986 Expr::While(input.parse()?)
1987 } else if input.peek(Token![for]) {
1988 Expr::ForLoop(input.parse()?)
1989 } else if input.peek(Token![loop]) {
1990 Expr::Loop(input.parse()?)
1991 } else if input.peek(Token![match]) {
1992 Expr::Match(input.parse()?)
1993 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
1994 Expr::TryBlock(input.parse()?)
1995 } else if input.peek(Token![unsafe]) {
1996 Expr::Unsafe(input.parse()?)
1997 } else if input.peek(Token![const]) {
1998 Expr::Verbatim(input.call(expr_const)?)
1999 } else if input.peek(token::Brace) {
2000 Expr::Block(input.parse()?)
2001 } else {
2002 let allow_struct = AllowStruct(true);
2003 let mut expr = unary_expr(input, allow_struct)?;
2004
2005 attrs.extend(expr.replace_attrs(Vec::new()));
2006 expr.replace_attrs(attrs);
2007
2008 return parse_expr(input, expr, allow_struct, Precedence::Any);
2009 };
2010
2011 if input.peek(Token![.]) && !input.peek(Token![..]) || input.peek(Token![?]) {
2012 expr = trailer_helper(input, expr)?;
2013
2014 attrs.extend(expr.replace_attrs(Vec::new()));
2015 expr.replace_attrs(attrs);
2016
2017 let allow_struct = AllowStruct(true);
2018 return parse_expr(input, expr, allow_struct, Precedence::Any);
2019 }
2020
2021 attrs.extend(expr.replace_attrs(Vec::new()));
2022 expr.replace_attrs(attrs);
2023 Ok(expr)
2024 }
2025
2026 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2027 impl Parse for ExprLit {
parse(input: ParseStream) -> Result<Self>2028 fn parse(input: ParseStream) -> Result<Self> {
2029 Ok(ExprLit {
2030 attrs: Vec::new(),
2031 lit: input.parse()?,
2032 })
2033 }
2034 }
2035
2036 #[cfg(feature = "full")]
expr_group(input: ParseStream) -> Result<ExprGroup>2037 fn expr_group(input: ParseStream) -> Result<ExprGroup> {
2038 let group = crate::group::parse_group(input)?;
2039 Ok(ExprGroup {
2040 attrs: Vec::new(),
2041 group_token: group.token,
2042 expr: group.content.parse()?,
2043 })
2044 }
2045
2046 #[cfg(feature = "full")]
2047 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2048 impl Parse for ExprParen {
parse(input: ParseStream) -> Result<Self>2049 fn parse(input: ParseStream) -> Result<Self> {
2050 expr_paren(input)
2051 }
2052 }
2053
expr_paren(input: ParseStream) -> Result<ExprParen>2054 fn expr_paren(input: ParseStream) -> Result<ExprParen> {
2055 let content;
2056 Ok(ExprParen {
2057 attrs: Vec::new(),
2058 paren_token: parenthesized!(content in input),
2059 expr: content.parse()?,
2060 })
2061 }
2062
2063 #[cfg(feature = "full")]
generic_method_argument(input: ParseStream) -> Result<GenericMethodArgument>2064 fn generic_method_argument(input: ParseStream) -> Result<GenericMethodArgument> {
2065 if input.peek(Lit) {
2066 let lit = input.parse()?;
2067 return Ok(GenericMethodArgument::Const(Expr::Lit(lit)));
2068 }
2069
2070 if input.peek(token::Brace) {
2071 let block: ExprBlock = input.parse()?;
2072 return Ok(GenericMethodArgument::Const(Expr::Block(block)));
2073 }
2074
2075 input.parse().map(GenericMethodArgument::Type)
2076 }
2077
2078 #[cfg(feature = "full")]
2079 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2080 impl Parse for ExprLet {
parse(input: ParseStream) -> Result<Self>2081 fn parse(input: ParseStream) -> Result<Self> {
2082 Ok(ExprLet {
2083 attrs: Vec::new(),
2084 let_token: input.parse()?,
2085 pat: pat::parsing::multi_pat_with_leading_vert(input)?,
2086 eq_token: input.parse()?,
2087 expr: Box::new(input.call(Expr::parse_without_eager_brace)?),
2088 })
2089 }
2090 }
2091
2092 #[cfg(feature = "full")]
2093 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2094 impl Parse for ExprIf {
parse(input: ParseStream) -> Result<Self>2095 fn parse(input: ParseStream) -> Result<Self> {
2096 let attrs = input.call(Attribute::parse_outer)?;
2097 Ok(ExprIf {
2098 attrs,
2099 if_token: input.parse()?,
2100 cond: Box::new(input.call(Expr::parse_without_eager_brace)?),
2101 then_branch: input.parse()?,
2102 else_branch: {
2103 if input.peek(Token![else]) {
2104 Some(input.call(else_block)?)
2105 } else {
2106 None
2107 }
2108 },
2109 })
2110 }
2111 }
2112
2113 #[cfg(feature = "full")]
else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)>2114 fn else_block(input: ParseStream) -> Result<(Token![else], Box<Expr>)> {
2115 let else_token: Token![else] = input.parse()?;
2116
2117 let lookahead = input.lookahead1();
2118 let else_branch = if input.peek(Token![if]) {
2119 input.parse().map(Expr::If)?
2120 } else if input.peek(token::Brace) {
2121 Expr::Block(ExprBlock {
2122 attrs: Vec::new(),
2123 label: None,
2124 block: input.parse()?,
2125 })
2126 } else {
2127 return Err(lookahead.error());
2128 };
2129
2130 Ok((else_token, Box::new(else_branch)))
2131 }
2132
2133 #[cfg(feature = "full")]
2134 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2135 impl Parse for ExprForLoop {
parse(input: ParseStream) -> Result<Self>2136 fn parse(input: ParseStream) -> Result<Self> {
2137 let outer_attrs = input.call(Attribute::parse_outer)?;
2138 let label: Option<Label> = input.parse()?;
2139 let for_token: Token![for] = input.parse()?;
2140
2141 let pat = pat::parsing::multi_pat_with_leading_vert(input)?;
2142
2143 let in_token: Token![in] = input.parse()?;
2144 let expr: Expr = input.call(Expr::parse_without_eager_brace)?;
2145
2146 let content;
2147 let brace_token = braced!(content in input);
2148 let inner_attrs = content.call(Attribute::parse_inner)?;
2149 let stmts = content.call(Block::parse_within)?;
2150
2151 Ok(ExprForLoop {
2152 attrs: private::attrs(outer_attrs, inner_attrs),
2153 label,
2154 for_token,
2155 pat,
2156 in_token,
2157 expr: Box::new(expr),
2158 body: Block { brace_token, stmts },
2159 })
2160 }
2161 }
2162
2163 #[cfg(feature = "full")]
2164 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2165 impl Parse for ExprLoop {
parse(input: ParseStream) -> Result<Self>2166 fn parse(input: ParseStream) -> Result<Self> {
2167 let outer_attrs = input.call(Attribute::parse_outer)?;
2168 let label: Option<Label> = input.parse()?;
2169 let loop_token: Token![loop] = input.parse()?;
2170
2171 let content;
2172 let brace_token = braced!(content in input);
2173 let inner_attrs = content.call(Attribute::parse_inner)?;
2174 let stmts = content.call(Block::parse_within)?;
2175
2176 Ok(ExprLoop {
2177 attrs: private::attrs(outer_attrs, inner_attrs),
2178 label,
2179 loop_token,
2180 body: Block { brace_token, stmts },
2181 })
2182 }
2183 }
2184
2185 #[cfg(feature = "full")]
2186 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2187 impl Parse for ExprMatch {
parse(input: ParseStream) -> Result<Self>2188 fn parse(input: ParseStream) -> Result<Self> {
2189 let outer_attrs = input.call(Attribute::parse_outer)?;
2190 let match_token: Token![match] = input.parse()?;
2191 let expr = Expr::parse_without_eager_brace(input)?;
2192
2193 let content;
2194 let brace_token = braced!(content in input);
2195 let inner_attrs = content.call(Attribute::parse_inner)?;
2196
2197 let mut arms = Vec::new();
2198 while !content.is_empty() {
2199 arms.push(content.call(Arm::parse)?);
2200 }
2201
2202 Ok(ExprMatch {
2203 attrs: private::attrs(outer_attrs, inner_attrs),
2204 match_token,
2205 expr: Box::new(expr),
2206 brace_token,
2207 arms,
2208 })
2209 }
2210 }
2211
2212 macro_rules! impl_by_parsing_expr {
2213 (
2214 $(
2215 $expr_type:ty, $variant:ident, $msg:expr,
2216 )*
2217 ) => {
2218 $(
2219 #[cfg(all(feature = "full", feature = "printing"))]
2220 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2221 impl Parse for $expr_type {
2222 fn parse(input: ParseStream) -> Result<Self> {
2223 let mut expr: Expr = input.parse()?;
2224 loop {
2225 match expr {
2226 Expr::$variant(inner) => return Ok(inner),
2227 Expr::Group(next) => expr = *next.expr,
2228 _ => return Err(Error::new_spanned(expr, $msg)),
2229 }
2230 }
2231 }
2232 }
2233 )*
2234 };
2235 }
2236
2237 impl_by_parsing_expr! {
2238 ExprCall, Call, "expected function call expression",
2239 ExprMethodCall, MethodCall, "expected method call expression",
2240 ExprTuple, Tuple, "expected tuple expression",
2241 ExprBinary, Binary, "expected binary operation",
2242 ExprCast, Cast, "expected cast expression",
2243 ExprType, Type, "expected type ascription expression",
2244 ExprAssign, Assign, "expected assignment expression",
2245 ExprAssignOp, AssignOp, "expected compound assignment expression",
2246 ExprField, Field, "expected struct field access",
2247 ExprIndex, Index, "expected indexing expression",
2248 ExprRange, Range, "expected range expression",
2249 ExprTry, Try, "expected try expression",
2250 }
2251
2252 #[cfg(feature = "full")]
2253 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2254 impl Parse for ExprBox {
parse(input: ParseStream) -> Result<Self>2255 fn parse(input: ParseStream) -> Result<Self> {
2256 let attrs = Vec::new();
2257 let allow_struct = AllowStruct(true);
2258 expr_box(input, attrs, allow_struct)
2259 }
2260 }
2261
2262 #[cfg(feature = "full")]
expr_box( input: ParseStream, attrs: Vec<Attribute>, allow_struct: AllowStruct, ) -> Result<ExprBox>2263 fn expr_box(
2264 input: ParseStream,
2265 attrs: Vec<Attribute>,
2266 allow_struct: AllowStruct,
2267 ) -> Result<ExprBox> {
2268 Ok(ExprBox {
2269 attrs,
2270 box_token: input.parse()?,
2271 expr: Box::new(unary_expr(input, allow_struct)?),
2272 })
2273 }
2274
2275 #[cfg(feature = "full")]
2276 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2277 impl Parse for ExprUnary {
parse(input: ParseStream) -> Result<Self>2278 fn parse(input: ParseStream) -> Result<Self> {
2279 let attrs = Vec::new();
2280 let allow_struct = AllowStruct(true);
2281 expr_unary(input, attrs, allow_struct)
2282 }
2283 }
2284
2285 #[cfg(feature = "full")]
expr_unary( input: ParseStream, attrs: Vec<Attribute>, allow_struct: AllowStruct, ) -> Result<ExprUnary>2286 fn expr_unary(
2287 input: ParseStream,
2288 attrs: Vec<Attribute>,
2289 allow_struct: AllowStruct,
2290 ) -> Result<ExprUnary> {
2291 Ok(ExprUnary {
2292 attrs,
2293 op: input.parse()?,
2294 expr: Box::new(unary_expr(input, allow_struct)?),
2295 })
2296 }
2297
2298 #[cfg(feature = "full")]
2299 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2300 impl Parse for ExprClosure {
parse(input: ParseStream) -> Result<Self>2301 fn parse(input: ParseStream) -> Result<Self> {
2302 let allow_struct = AllowStruct(true);
2303 expr_closure(input, allow_struct)
2304 }
2305 }
2306
2307 #[cfg(feature = "full")]
2308 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2309 impl Parse for ExprReference {
parse(input: ParseStream) -> Result<Self>2310 fn parse(input: ParseStream) -> Result<Self> {
2311 let allow_struct = AllowStruct(true);
2312 Ok(ExprReference {
2313 attrs: Vec::new(),
2314 and_token: input.parse()?,
2315 raw: Reserved::default(),
2316 mutability: input.parse()?,
2317 expr: Box::new(unary_expr(input, allow_struct)?),
2318 })
2319 }
2320 }
2321
2322 #[cfg(feature = "full")]
2323 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2324 impl Parse for ExprBreak {
parse(input: ParseStream) -> Result<Self>2325 fn parse(input: ParseStream) -> Result<Self> {
2326 let allow_struct = AllowStruct(true);
2327 expr_break(input, allow_struct)
2328 }
2329 }
2330
2331 #[cfg(feature = "full")]
2332 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2333 impl Parse for ExprReturn {
parse(input: ParseStream) -> Result<Self>2334 fn parse(input: ParseStream) -> Result<Self> {
2335 let allow_struct = AllowStruct(true);
2336 expr_ret(input, allow_struct)
2337 }
2338 }
2339
2340 #[cfg(feature = "full")]
2341 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2342 impl Parse for ExprTryBlock {
parse(input: ParseStream) -> Result<Self>2343 fn parse(input: ParseStream) -> Result<Self> {
2344 Ok(ExprTryBlock {
2345 attrs: Vec::new(),
2346 try_token: input.parse()?,
2347 block: input.parse()?,
2348 })
2349 }
2350 }
2351
2352 #[cfg(feature = "full")]
2353 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2354 impl Parse for ExprYield {
parse(input: ParseStream) -> Result<Self>2355 fn parse(input: ParseStream) -> Result<Self> {
2356 Ok(ExprYield {
2357 attrs: Vec::new(),
2358 yield_token: input.parse()?,
2359 expr: {
2360 if !input.is_empty() && !input.peek(Token![,]) && !input.peek(Token![;]) {
2361 Some(input.parse()?)
2362 } else {
2363 None
2364 }
2365 },
2366 })
2367 }
2368 }
2369
2370 #[cfg(feature = "full")]
expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure>2371 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
2372 let asyncness: Option<Token![async]> = input.parse()?;
2373 let movability: Option<Token![static]> = if asyncness.is_none() {
2374 input.parse()?
2375 } else {
2376 None
2377 };
2378 let capture: Option<Token![move]> = input.parse()?;
2379 let or1_token: Token![|] = input.parse()?;
2380
2381 let mut inputs = Punctuated::new();
2382 loop {
2383 if input.peek(Token![|]) {
2384 break;
2385 }
2386 let value = closure_arg(input)?;
2387 inputs.push_value(value);
2388 if input.peek(Token![|]) {
2389 break;
2390 }
2391 let punct: Token![,] = input.parse()?;
2392 inputs.push_punct(punct);
2393 }
2394
2395 let or2_token: Token![|] = input.parse()?;
2396
2397 let (output, body) = if input.peek(Token![->]) {
2398 let arrow_token: Token![->] = input.parse()?;
2399 let ty: Type = input.parse()?;
2400 let body: Block = input.parse()?;
2401 let output = ReturnType::Type(arrow_token, Box::new(ty));
2402 let block = Expr::Block(ExprBlock {
2403 attrs: Vec::new(),
2404 label: None,
2405 block: body,
2406 });
2407 (output, block)
2408 } else {
2409 let body = ambiguous_expr(input, allow_struct)?;
2410 (ReturnType::Default, body)
2411 };
2412
2413 Ok(ExprClosure {
2414 attrs: Vec::new(),
2415 asyncness,
2416 movability,
2417 capture,
2418 or1_token,
2419 inputs,
2420 or2_token,
2421 output,
2422 body: Box::new(body),
2423 })
2424 }
2425
2426 #[cfg(feature = "full")]
2427 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2428 impl Parse for ExprAsync {
parse(input: ParseStream) -> Result<Self>2429 fn parse(input: ParseStream) -> Result<Self> {
2430 Ok(ExprAsync {
2431 attrs: Vec::new(),
2432 async_token: input.parse()?,
2433 capture: input.parse()?,
2434 block: input.parse()?,
2435 })
2436 }
2437 }
2438
2439 #[cfg(feature = "full")]
closure_arg(input: ParseStream) -> Result<Pat>2440 fn closure_arg(input: ParseStream) -> Result<Pat> {
2441 let attrs = input.call(Attribute::parse_outer)?;
2442 let mut pat: Pat = input.parse()?;
2443
2444 if input.peek(Token![:]) {
2445 Ok(Pat::Type(PatType {
2446 attrs,
2447 pat: Box::new(pat),
2448 colon_token: input.parse()?,
2449 ty: input.parse()?,
2450 }))
2451 } else {
2452 match &mut pat {
2453 Pat::Box(pat) => pat.attrs = attrs,
2454 Pat::Ident(pat) => pat.attrs = attrs,
2455 Pat::Lit(pat) => pat.attrs = attrs,
2456 Pat::Macro(pat) => pat.attrs = attrs,
2457 Pat::Or(pat) => pat.attrs = attrs,
2458 Pat::Path(pat) => pat.attrs = attrs,
2459 Pat::Range(pat) => pat.attrs = attrs,
2460 Pat::Reference(pat) => pat.attrs = attrs,
2461 Pat::Rest(pat) => pat.attrs = attrs,
2462 Pat::Slice(pat) => pat.attrs = attrs,
2463 Pat::Struct(pat) => pat.attrs = attrs,
2464 Pat::Tuple(pat) => pat.attrs = attrs,
2465 Pat::TupleStruct(pat) => pat.attrs = attrs,
2466 Pat::Type(_) => unreachable!(),
2467 Pat::Verbatim(_) => {}
2468 Pat::Wild(pat) => pat.attrs = attrs,
2469
2470 #[cfg(test)]
2471 Pat::__TestExhaustive(_) => unimplemented!(),
2472 #[cfg(not(test))]
2473 _ => unreachable!(),
2474 }
2475 Ok(pat)
2476 }
2477 }
2478
2479 #[cfg(feature = "full")]
2480 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2481 impl Parse for ExprWhile {
parse(input: ParseStream) -> Result<Self>2482 fn parse(input: ParseStream) -> Result<Self> {
2483 let outer_attrs = input.call(Attribute::parse_outer)?;
2484 let label: Option<Label> = input.parse()?;
2485 let while_token: Token![while] = input.parse()?;
2486 let cond = Expr::parse_without_eager_brace(input)?;
2487
2488 let content;
2489 let brace_token = braced!(content in input);
2490 let inner_attrs = content.call(Attribute::parse_inner)?;
2491 let stmts = content.call(Block::parse_within)?;
2492
2493 Ok(ExprWhile {
2494 attrs: private::attrs(outer_attrs, inner_attrs),
2495 label,
2496 while_token,
2497 cond: Box::new(cond),
2498 body: Block { brace_token, stmts },
2499 })
2500 }
2501 }
2502
2503 #[cfg(feature = "full")]
2504 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2505 impl Parse for Label {
parse(input: ParseStream) -> Result<Self>2506 fn parse(input: ParseStream) -> Result<Self> {
2507 Ok(Label {
2508 name: input.parse()?,
2509 colon_token: input.parse()?,
2510 })
2511 }
2512 }
2513
2514 #[cfg(feature = "full")]
2515 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2516 impl Parse for Option<Label> {
parse(input: ParseStream) -> Result<Self>2517 fn parse(input: ParseStream) -> Result<Self> {
2518 if input.peek(Lifetime) {
2519 input.parse().map(Some)
2520 } else {
2521 Ok(None)
2522 }
2523 }
2524 }
2525
2526 #[cfg(feature = "full")]
2527 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2528 impl Parse for ExprContinue {
parse(input: ParseStream) -> Result<Self>2529 fn parse(input: ParseStream) -> Result<Self> {
2530 Ok(ExprContinue {
2531 attrs: Vec::new(),
2532 continue_token: input.parse()?,
2533 label: input.parse()?,
2534 })
2535 }
2536 }
2537
2538 #[cfg(feature = "full")]
expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak>2539 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2540 Ok(ExprBreak {
2541 attrs: Vec::new(),
2542 break_token: input.parse()?,
2543 label: input.parse()?,
2544 expr: {
2545 if input.is_empty()
2546 || input.peek(Token![,])
2547 || input.peek(Token![;])
2548 || !allow_struct.0 && input.peek(token::Brace)
2549 {
2550 None
2551 } else {
2552 let expr = ambiguous_expr(input, allow_struct)?;
2553 Some(Box::new(expr))
2554 }
2555 },
2556 })
2557 }
2558
2559 #[cfg(feature = "full")]
expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn>2560 fn expr_ret(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprReturn> {
2561 Ok(ExprReturn {
2562 attrs: Vec::new(),
2563 return_token: input.parse()?,
2564 expr: {
2565 if input.is_empty() || input.peek(Token![,]) || input.peek(Token![;]) {
2566 None
2567 } else {
2568 // NOTE: return is greedy and eats blocks after it even when in a
2569 // position where structs are not allowed, such as in if statement
2570 // conditions. For example:
2571 //
2572 // if return { println!("A") } {} // Prints "A"
2573 let expr = ambiguous_expr(input, allow_struct)?;
2574 Some(Box::new(expr))
2575 }
2576 },
2577 })
2578 }
2579
2580 #[cfg(feature = "full")]
2581 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2582 impl Parse for FieldValue {
parse(input: ParseStream) -> Result<Self>2583 fn parse(input: ParseStream) -> Result<Self> {
2584 let attrs = input.call(Attribute::parse_outer)?;
2585 let member: Member = input.parse()?;
2586 let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
2587 let colon_token: Token![:] = input.parse()?;
2588 let value: Expr = input.parse()?;
2589 (Some(colon_token), value)
2590 } else if let Member::Named(ident) = &member {
2591 let value = Expr::Path(ExprPath {
2592 attrs: Vec::new(),
2593 qself: None,
2594 path: Path::from(ident.clone()),
2595 });
2596 (None, value)
2597 } else {
2598 unreachable!()
2599 };
2600
2601 Ok(FieldValue {
2602 attrs,
2603 member,
2604 colon_token,
2605 expr: value,
2606 })
2607 }
2608 }
2609
2610 #[cfg(feature = "full")]
2611 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2612 impl Parse for ExprStruct {
parse(input: ParseStream) -> Result<Self>2613 fn parse(input: ParseStream) -> Result<Self> {
2614 let attrs = Vec::new();
2615 let path: Path = input.parse()?;
2616 expr_struct_helper(input, attrs, path)
2617 }
2618 }
2619
2620 #[cfg(feature = "full")]
expr_struct_helper( input: ParseStream, outer_attrs: Vec<Attribute>, path: Path, ) -> Result<ExprStruct>2621 fn expr_struct_helper(
2622 input: ParseStream,
2623 outer_attrs: Vec<Attribute>,
2624 path: Path,
2625 ) -> Result<ExprStruct> {
2626 let content;
2627 let brace_token = braced!(content in input);
2628 let inner_attrs = content.call(Attribute::parse_inner)?;
2629 let attrs = private::attrs(outer_attrs, inner_attrs);
2630
2631 let mut fields = Punctuated::new();
2632 while !content.is_empty() {
2633 if content.peek(Token![..]) {
2634 return Ok(ExprStruct {
2635 attrs,
2636 brace_token,
2637 path,
2638 fields,
2639 dot2_token: Some(content.parse()?),
2640 rest: if content.is_empty() {
2641 None
2642 } else {
2643 Some(Box::new(content.parse()?))
2644 },
2645 });
2646 }
2647
2648 fields.push(content.parse()?);
2649 if content.is_empty() {
2650 break;
2651 }
2652 let punct: Token![,] = content.parse()?;
2653 fields.push_punct(punct);
2654 }
2655
2656 Ok(ExprStruct {
2657 attrs,
2658 brace_token,
2659 path,
2660 fields,
2661 dot2_token: None,
2662 rest: None,
2663 })
2664 }
2665
2666 #[cfg(feature = "full")]
2667 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2668 impl Parse for ExprUnsafe {
parse(input: ParseStream) -> Result<Self>2669 fn parse(input: ParseStream) -> Result<Self> {
2670 let unsafe_token: Token![unsafe] = input.parse()?;
2671
2672 let content;
2673 let brace_token = braced!(content in input);
2674 let inner_attrs = content.call(Attribute::parse_inner)?;
2675 let stmts = content.call(Block::parse_within)?;
2676
2677 Ok(ExprUnsafe {
2678 attrs: inner_attrs,
2679 unsafe_token,
2680 block: Block { brace_token, stmts },
2681 })
2682 }
2683 }
2684
2685 #[cfg(feature = "full")]
expr_const(input: ParseStream) -> Result<TokenStream>2686 pub(crate) fn expr_const(input: ParseStream) -> Result<TokenStream> {
2687 let begin = input.fork();
2688 input.parse::<Token![const]>()?;
2689
2690 let content;
2691 braced!(content in input);
2692 content.call(Attribute::parse_inner)?;
2693 content.call(Block::parse_within)?;
2694
2695 Ok(verbatim::between(begin, input))
2696 }
2697
2698 #[cfg(feature = "full")]
2699 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2700 impl Parse for ExprBlock {
parse(input: ParseStream) -> Result<Self>2701 fn parse(input: ParseStream) -> Result<Self> {
2702 let outer_attrs = input.call(Attribute::parse_outer)?;
2703 let label: Option<Label> = input.parse()?;
2704
2705 let content;
2706 let brace_token = braced!(content in input);
2707 let inner_attrs = content.call(Attribute::parse_inner)?;
2708 let stmts = content.call(Block::parse_within)?;
2709
2710 Ok(ExprBlock {
2711 attrs: private::attrs(outer_attrs, inner_attrs),
2712 label,
2713 block: Block { brace_token, stmts },
2714 })
2715 }
2716 }
2717
2718 #[cfg(feature = "full")]
expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange>2719 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2720 Ok(ExprRange {
2721 attrs: Vec::new(),
2722 from: None,
2723 limits: input.parse()?,
2724 to: {
2725 if input.is_empty()
2726 || input.peek(Token![,])
2727 || input.peek(Token![;])
2728 || !allow_struct.0 && input.peek(token::Brace)
2729 {
2730 None
2731 } else {
2732 let to = ambiguous_expr(input, allow_struct)?;
2733 Some(Box::new(to))
2734 }
2735 },
2736 })
2737 }
2738
2739 #[cfg(feature = "full")]
2740 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2741 impl Parse for RangeLimits {
parse(input: ParseStream) -> Result<Self>2742 fn parse(input: ParseStream) -> Result<Self> {
2743 let lookahead = input.lookahead1();
2744 if lookahead.peek(Token![..=]) {
2745 input.parse().map(RangeLimits::Closed)
2746 } else if lookahead.peek(Token![...]) {
2747 let dot3: Token![...] = input.parse()?;
2748 Ok(RangeLimits::Closed(Token![..=](dot3.spans)))
2749 } else if lookahead.peek(Token![..]) {
2750 input.parse().map(RangeLimits::HalfOpen)
2751 } else {
2752 Err(lookahead.error())
2753 }
2754 }
2755 }
2756
2757 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2758 impl Parse for ExprPath {
parse(input: ParseStream) -> Result<Self>2759 fn parse(input: ParseStream) -> Result<Self> {
2760 #[cfg(not(feature = "full"))]
2761 let attrs = Vec::new();
2762 #[cfg(feature = "full")]
2763 let attrs = input.call(Attribute::parse_outer)?;
2764
2765 let (qself, path) = path::parsing::qpath(input, true)?;
2766
2767 Ok(ExprPath { attrs, qself, path })
2768 }
2769 }
2770
2771 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2772 impl Parse for Member {
parse(input: ParseStream) -> Result<Self>2773 fn parse(input: ParseStream) -> Result<Self> {
2774 if input.peek(Ident) {
2775 input.parse().map(Member::Named)
2776 } else if input.peek(LitInt) {
2777 input.parse().map(Member::Unnamed)
2778 } else {
2779 Err(input.error("expected identifier or integer"))
2780 }
2781 }
2782 }
2783
2784 #[cfg(feature = "full")]
2785 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2786 impl Parse for Arm {
parse(input: ParseStream) -> Result<Arm>2787 fn parse(input: ParseStream) -> Result<Arm> {
2788 let requires_comma;
2789 Ok(Arm {
2790 attrs: input.call(Attribute::parse_outer)?,
2791 pat: pat::parsing::multi_pat_with_leading_vert(input)?,
2792 guard: {
2793 if input.peek(Token![if]) {
2794 let if_token: Token![if] = input.parse()?;
2795 let guard: Expr = input.parse()?;
2796 Some((if_token, Box::new(guard)))
2797 } else {
2798 None
2799 }
2800 },
2801 fat_arrow_token: input.parse()?,
2802 body: {
2803 let body = input.call(expr_early)?;
2804 requires_comma = requires_terminator(&body);
2805 Box::new(body)
2806 },
2807 comma: {
2808 if requires_comma && !input.is_empty() {
2809 Some(input.parse()?)
2810 } else {
2811 input.parse()?
2812 }
2813 },
2814 })
2815 }
2816 }
2817
2818 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
2819 impl Parse for Index {
parse(input: ParseStream) -> Result<Self>2820 fn parse(input: ParseStream) -> Result<Self> {
2821 let lit: LitInt = input.parse()?;
2822 if lit.suffix().is_empty() {
2823 Ok(Index {
2824 index: lit
2825 .base10_digits()
2826 .parse()
2827 .map_err(|err| Error::new(lit.span(), err))?,
2828 span: lit.span(),
2829 })
2830 } else {
2831 Err(Error::new(lit.span(), "expected unsuffixed integer"))
2832 }
2833 }
2834 }
2835
multi_index(e: &mut Expr, dot_token: &mut Token![.], float: LitFloat) -> Result<bool>2836 fn multi_index(e: &mut Expr, dot_token: &mut Token![.], float: LitFloat) -> Result<bool> {
2837 let mut float_repr = float.to_string();
2838 let trailing_dot = float_repr.ends_with('.');
2839 if trailing_dot {
2840 float_repr.truncate(float_repr.len() - 1);
2841 }
2842 for part in float_repr.split('.') {
2843 let index = crate::parse_str(part).map_err(|err| Error::new(float.span(), err))?;
2844 let base = mem::replace(e, Expr::__TestExhaustive(crate::private(())));
2845 *e = Expr::Field(ExprField {
2846 attrs: Vec::new(),
2847 base: Box::new(base),
2848 dot_token: Token![.](dot_token.span),
2849 member: Member::Unnamed(index),
2850 });
2851 *dot_token = Token![.](float.span());
2852 }
2853 Ok(!trailing_dot)
2854 }
2855
2856 #[cfg(feature = "full")]
2857 impl Member {
is_named(&self) -> bool2858 fn is_named(&self) -> bool {
2859 match *self {
2860 Member::Named(_) => true,
2861 Member::Unnamed(_) => false,
2862 }
2863 }
2864 }
2865 }
2866
2867 #[cfg(feature = "printing")]
2868 pub(crate) mod printing {
2869 use super::*;
2870 #[cfg(feature = "full")]
2871 use crate::attr::FilterAttrs;
2872 use proc_macro2::{Literal, TokenStream};
2873 use quote::{ToTokens, TokenStreamExt};
2874
2875 // If the given expression is a bare `ExprStruct`, wraps it in parenthesis
2876 // before appending it to `TokenStream`.
2877 #[cfg(feature = "full")]
wrap_bare_struct(tokens: &mut TokenStream, e: &Expr)2878 fn wrap_bare_struct(tokens: &mut TokenStream, e: &Expr) {
2879 if let Expr::Struct(_) = *e {
2880 token::Paren::default().surround(tokens, |tokens| {
2881 e.to_tokens(tokens);
2882 });
2883 } else {
2884 e.to_tokens(tokens);
2885 }
2886 }
2887
2888 #[cfg(feature = "full")]
outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream)2889 pub(crate) fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
2890 tokens.append_all(attrs.outer());
2891 }
2892
2893 #[cfg(feature = "full")]
inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream)2894 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
2895 tokens.append_all(attrs.inner());
2896 }
2897
2898 #[cfg(not(feature = "full"))]
outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream)2899 pub(crate) fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
2900
2901 #[cfg(not(feature = "full"))]
inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream)2902 fn inner_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
2903
2904 #[cfg(feature = "full")]
2905 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
2906 impl ToTokens for ExprBox {
to_tokens(&self, tokens: &mut TokenStream)2907 fn to_tokens(&self, tokens: &mut TokenStream) {
2908 outer_attrs_to_tokens(&self.attrs, tokens);
2909 self.box_token.to_tokens(tokens);
2910 self.expr.to_tokens(tokens);
2911 }
2912 }
2913
2914 #[cfg(feature = "full")]
2915 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
2916 impl ToTokens for ExprArray {
to_tokens(&self, tokens: &mut TokenStream)2917 fn to_tokens(&self, tokens: &mut TokenStream) {
2918 outer_attrs_to_tokens(&self.attrs, tokens);
2919 self.bracket_token.surround(tokens, |tokens| {
2920 inner_attrs_to_tokens(&self.attrs, tokens);
2921 self.elems.to_tokens(tokens);
2922 })
2923 }
2924 }
2925
2926 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
2927 impl ToTokens for ExprCall {
to_tokens(&self, tokens: &mut TokenStream)2928 fn to_tokens(&self, tokens: &mut TokenStream) {
2929 outer_attrs_to_tokens(&self.attrs, tokens);
2930 self.func.to_tokens(tokens);
2931 self.paren_token.surround(tokens, |tokens| {
2932 self.args.to_tokens(tokens);
2933 })
2934 }
2935 }
2936
2937 #[cfg(feature = "full")]
2938 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
2939 impl ToTokens for ExprMethodCall {
to_tokens(&self, tokens: &mut TokenStream)2940 fn to_tokens(&self, tokens: &mut TokenStream) {
2941 outer_attrs_to_tokens(&self.attrs, tokens);
2942 self.receiver.to_tokens(tokens);
2943 self.dot_token.to_tokens(tokens);
2944 self.method.to_tokens(tokens);
2945 self.turbofish.to_tokens(tokens);
2946 self.paren_token.surround(tokens, |tokens| {
2947 self.args.to_tokens(tokens);
2948 });
2949 }
2950 }
2951
2952 #[cfg(feature = "full")]
2953 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
2954 impl ToTokens for MethodTurbofish {
to_tokens(&self, tokens: &mut TokenStream)2955 fn to_tokens(&self, tokens: &mut TokenStream) {
2956 self.colon2_token.to_tokens(tokens);
2957 self.lt_token.to_tokens(tokens);
2958 self.args.to_tokens(tokens);
2959 self.gt_token.to_tokens(tokens);
2960 }
2961 }
2962
2963 #[cfg(feature = "full")]
2964 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
2965 impl ToTokens for GenericMethodArgument {
to_tokens(&self, tokens: &mut TokenStream)2966 fn to_tokens(&self, tokens: &mut TokenStream) {
2967 match self {
2968 GenericMethodArgument::Type(t) => t.to_tokens(tokens),
2969 GenericMethodArgument::Const(c) => c.to_tokens(tokens),
2970 }
2971 }
2972 }
2973
2974 #[cfg(feature = "full")]
2975 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
2976 impl ToTokens for ExprTuple {
to_tokens(&self, tokens: &mut TokenStream)2977 fn to_tokens(&self, tokens: &mut TokenStream) {
2978 outer_attrs_to_tokens(&self.attrs, tokens);
2979 self.paren_token.surround(tokens, |tokens| {
2980 inner_attrs_to_tokens(&self.attrs, tokens);
2981 self.elems.to_tokens(tokens);
2982 // If we only have one argument, we need a trailing comma to
2983 // distinguish ExprTuple from ExprParen.
2984 if self.elems.len() == 1 && !self.elems.trailing_punct() {
2985 <Token![,]>::default().to_tokens(tokens);
2986 }
2987 })
2988 }
2989 }
2990
2991 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
2992 impl ToTokens for ExprBinary {
to_tokens(&self, tokens: &mut TokenStream)2993 fn to_tokens(&self, tokens: &mut TokenStream) {
2994 outer_attrs_to_tokens(&self.attrs, tokens);
2995 self.left.to_tokens(tokens);
2996 self.op.to_tokens(tokens);
2997 self.right.to_tokens(tokens);
2998 }
2999 }
3000
3001 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3002 impl ToTokens for ExprUnary {
to_tokens(&self, tokens: &mut TokenStream)3003 fn to_tokens(&self, tokens: &mut TokenStream) {
3004 outer_attrs_to_tokens(&self.attrs, tokens);
3005 self.op.to_tokens(tokens);
3006 self.expr.to_tokens(tokens);
3007 }
3008 }
3009
3010 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3011 impl ToTokens for ExprLit {
to_tokens(&self, tokens: &mut TokenStream)3012 fn to_tokens(&self, tokens: &mut TokenStream) {
3013 outer_attrs_to_tokens(&self.attrs, tokens);
3014 self.lit.to_tokens(tokens);
3015 }
3016 }
3017
3018 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3019 impl ToTokens for ExprCast {
to_tokens(&self, tokens: &mut TokenStream)3020 fn to_tokens(&self, tokens: &mut TokenStream) {
3021 outer_attrs_to_tokens(&self.attrs, tokens);
3022 self.expr.to_tokens(tokens);
3023 self.as_token.to_tokens(tokens);
3024 self.ty.to_tokens(tokens);
3025 }
3026 }
3027
3028 #[cfg(feature = "full")]
3029 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3030 impl ToTokens for ExprType {
to_tokens(&self, tokens: &mut TokenStream)3031 fn to_tokens(&self, tokens: &mut TokenStream) {
3032 outer_attrs_to_tokens(&self.attrs, tokens);
3033 self.expr.to_tokens(tokens);
3034 self.colon_token.to_tokens(tokens);
3035 self.ty.to_tokens(tokens);
3036 }
3037 }
3038
3039 #[cfg(feature = "full")]
maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>)3040 fn maybe_wrap_else(tokens: &mut TokenStream, else_: &Option<(Token![else], Box<Expr>)>) {
3041 if let Some((else_token, else_)) = else_ {
3042 else_token.to_tokens(tokens);
3043
3044 // If we are not one of the valid expressions to exist in an else
3045 // clause, wrap ourselves in a block.
3046 match **else_ {
3047 Expr::If(_) | Expr::Block(_) => {
3048 else_.to_tokens(tokens);
3049 }
3050 _ => {
3051 token::Brace::default().surround(tokens, |tokens| {
3052 else_.to_tokens(tokens);
3053 });
3054 }
3055 }
3056 }
3057 }
3058
3059 #[cfg(feature = "full")]
3060 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3061 impl ToTokens for ExprLet {
to_tokens(&self, tokens: &mut TokenStream)3062 fn to_tokens(&self, tokens: &mut TokenStream) {
3063 outer_attrs_to_tokens(&self.attrs, tokens);
3064 self.let_token.to_tokens(tokens);
3065 self.pat.to_tokens(tokens);
3066 self.eq_token.to_tokens(tokens);
3067 wrap_bare_struct(tokens, &self.expr);
3068 }
3069 }
3070
3071 #[cfg(feature = "full")]
3072 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3073 impl ToTokens for ExprIf {
to_tokens(&self, tokens: &mut TokenStream)3074 fn to_tokens(&self, tokens: &mut TokenStream) {
3075 outer_attrs_to_tokens(&self.attrs, tokens);
3076 self.if_token.to_tokens(tokens);
3077 wrap_bare_struct(tokens, &self.cond);
3078 self.then_branch.to_tokens(tokens);
3079 maybe_wrap_else(tokens, &self.else_branch);
3080 }
3081 }
3082
3083 #[cfg(feature = "full")]
3084 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3085 impl ToTokens for ExprWhile {
to_tokens(&self, tokens: &mut TokenStream)3086 fn to_tokens(&self, tokens: &mut TokenStream) {
3087 outer_attrs_to_tokens(&self.attrs, tokens);
3088 self.label.to_tokens(tokens);
3089 self.while_token.to_tokens(tokens);
3090 wrap_bare_struct(tokens, &self.cond);
3091 self.body.brace_token.surround(tokens, |tokens| {
3092 inner_attrs_to_tokens(&self.attrs, tokens);
3093 tokens.append_all(&self.body.stmts);
3094 });
3095 }
3096 }
3097
3098 #[cfg(feature = "full")]
3099 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3100 impl ToTokens for ExprForLoop {
to_tokens(&self, tokens: &mut TokenStream)3101 fn to_tokens(&self, tokens: &mut TokenStream) {
3102 outer_attrs_to_tokens(&self.attrs, tokens);
3103 self.label.to_tokens(tokens);
3104 self.for_token.to_tokens(tokens);
3105 self.pat.to_tokens(tokens);
3106 self.in_token.to_tokens(tokens);
3107 wrap_bare_struct(tokens, &self.expr);
3108 self.body.brace_token.surround(tokens, |tokens| {
3109 inner_attrs_to_tokens(&self.attrs, tokens);
3110 tokens.append_all(&self.body.stmts);
3111 });
3112 }
3113 }
3114
3115 #[cfg(feature = "full")]
3116 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3117 impl ToTokens for ExprLoop {
to_tokens(&self, tokens: &mut TokenStream)3118 fn to_tokens(&self, tokens: &mut TokenStream) {
3119 outer_attrs_to_tokens(&self.attrs, tokens);
3120 self.label.to_tokens(tokens);
3121 self.loop_token.to_tokens(tokens);
3122 self.body.brace_token.surround(tokens, |tokens| {
3123 inner_attrs_to_tokens(&self.attrs, tokens);
3124 tokens.append_all(&self.body.stmts);
3125 });
3126 }
3127 }
3128
3129 #[cfg(feature = "full")]
3130 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3131 impl ToTokens for ExprMatch {
to_tokens(&self, tokens: &mut TokenStream)3132 fn to_tokens(&self, tokens: &mut TokenStream) {
3133 outer_attrs_to_tokens(&self.attrs, tokens);
3134 self.match_token.to_tokens(tokens);
3135 wrap_bare_struct(tokens, &self.expr);
3136 self.brace_token.surround(tokens, |tokens| {
3137 inner_attrs_to_tokens(&self.attrs, tokens);
3138 for (i, arm) in self.arms.iter().enumerate() {
3139 arm.to_tokens(tokens);
3140 // Ensure that we have a comma after a non-block arm, except
3141 // for the last one.
3142 let is_last = i == self.arms.len() - 1;
3143 if !is_last && requires_terminator(&arm.body) && arm.comma.is_none() {
3144 <Token![,]>::default().to_tokens(tokens);
3145 }
3146 }
3147 });
3148 }
3149 }
3150
3151 #[cfg(feature = "full")]
3152 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3153 impl ToTokens for ExprAsync {
to_tokens(&self, tokens: &mut TokenStream)3154 fn to_tokens(&self, tokens: &mut TokenStream) {
3155 outer_attrs_to_tokens(&self.attrs, tokens);
3156 self.async_token.to_tokens(tokens);
3157 self.capture.to_tokens(tokens);
3158 self.block.to_tokens(tokens);
3159 }
3160 }
3161
3162 #[cfg(feature = "full")]
3163 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3164 impl ToTokens for ExprAwait {
to_tokens(&self, tokens: &mut TokenStream)3165 fn to_tokens(&self, tokens: &mut TokenStream) {
3166 outer_attrs_to_tokens(&self.attrs, tokens);
3167 self.base.to_tokens(tokens);
3168 self.dot_token.to_tokens(tokens);
3169 self.await_token.to_tokens(tokens);
3170 }
3171 }
3172
3173 #[cfg(feature = "full")]
3174 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3175 impl ToTokens for ExprTryBlock {
to_tokens(&self, tokens: &mut TokenStream)3176 fn to_tokens(&self, tokens: &mut TokenStream) {
3177 outer_attrs_to_tokens(&self.attrs, tokens);
3178 self.try_token.to_tokens(tokens);
3179 self.block.to_tokens(tokens);
3180 }
3181 }
3182
3183 #[cfg(feature = "full")]
3184 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3185 impl ToTokens for ExprYield {
to_tokens(&self, tokens: &mut TokenStream)3186 fn to_tokens(&self, tokens: &mut TokenStream) {
3187 outer_attrs_to_tokens(&self.attrs, tokens);
3188 self.yield_token.to_tokens(tokens);
3189 self.expr.to_tokens(tokens);
3190 }
3191 }
3192
3193 #[cfg(feature = "full")]
3194 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3195 impl ToTokens for ExprClosure {
to_tokens(&self, tokens: &mut TokenStream)3196 fn to_tokens(&self, tokens: &mut TokenStream) {
3197 outer_attrs_to_tokens(&self.attrs, tokens);
3198 self.asyncness.to_tokens(tokens);
3199 self.movability.to_tokens(tokens);
3200 self.capture.to_tokens(tokens);
3201 self.or1_token.to_tokens(tokens);
3202 self.inputs.to_tokens(tokens);
3203 self.or2_token.to_tokens(tokens);
3204 self.output.to_tokens(tokens);
3205 self.body.to_tokens(tokens);
3206 }
3207 }
3208
3209 #[cfg(feature = "full")]
3210 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3211 impl ToTokens for ExprUnsafe {
to_tokens(&self, tokens: &mut TokenStream)3212 fn to_tokens(&self, tokens: &mut TokenStream) {
3213 outer_attrs_to_tokens(&self.attrs, tokens);
3214 self.unsafe_token.to_tokens(tokens);
3215 self.block.brace_token.surround(tokens, |tokens| {
3216 inner_attrs_to_tokens(&self.attrs, tokens);
3217 tokens.append_all(&self.block.stmts);
3218 });
3219 }
3220 }
3221
3222 #[cfg(feature = "full")]
3223 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3224 impl ToTokens for ExprBlock {
to_tokens(&self, tokens: &mut TokenStream)3225 fn to_tokens(&self, tokens: &mut TokenStream) {
3226 outer_attrs_to_tokens(&self.attrs, tokens);
3227 self.label.to_tokens(tokens);
3228 self.block.brace_token.surround(tokens, |tokens| {
3229 inner_attrs_to_tokens(&self.attrs, tokens);
3230 tokens.append_all(&self.block.stmts);
3231 });
3232 }
3233 }
3234
3235 #[cfg(feature = "full")]
3236 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3237 impl ToTokens for ExprAssign {
to_tokens(&self, tokens: &mut TokenStream)3238 fn to_tokens(&self, tokens: &mut TokenStream) {
3239 outer_attrs_to_tokens(&self.attrs, tokens);
3240 self.left.to_tokens(tokens);
3241 self.eq_token.to_tokens(tokens);
3242 self.right.to_tokens(tokens);
3243 }
3244 }
3245
3246 #[cfg(feature = "full")]
3247 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3248 impl ToTokens for ExprAssignOp {
to_tokens(&self, tokens: &mut TokenStream)3249 fn to_tokens(&self, tokens: &mut TokenStream) {
3250 outer_attrs_to_tokens(&self.attrs, tokens);
3251 self.left.to_tokens(tokens);
3252 self.op.to_tokens(tokens);
3253 self.right.to_tokens(tokens);
3254 }
3255 }
3256
3257 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3258 impl ToTokens for ExprField {
to_tokens(&self, tokens: &mut TokenStream)3259 fn to_tokens(&self, tokens: &mut TokenStream) {
3260 outer_attrs_to_tokens(&self.attrs, tokens);
3261 self.base.to_tokens(tokens);
3262 self.dot_token.to_tokens(tokens);
3263 self.member.to_tokens(tokens);
3264 }
3265 }
3266
3267 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3268 impl ToTokens for Member {
to_tokens(&self, tokens: &mut TokenStream)3269 fn to_tokens(&self, tokens: &mut TokenStream) {
3270 match self {
3271 Member::Named(ident) => ident.to_tokens(tokens),
3272 Member::Unnamed(index) => index.to_tokens(tokens),
3273 }
3274 }
3275 }
3276
3277 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3278 impl ToTokens for Index {
to_tokens(&self, tokens: &mut TokenStream)3279 fn to_tokens(&self, tokens: &mut TokenStream) {
3280 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
3281 lit.set_span(self.span);
3282 tokens.append(lit);
3283 }
3284 }
3285
3286 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3287 impl ToTokens for ExprIndex {
to_tokens(&self, tokens: &mut TokenStream)3288 fn to_tokens(&self, tokens: &mut TokenStream) {
3289 outer_attrs_to_tokens(&self.attrs, tokens);
3290 self.expr.to_tokens(tokens);
3291 self.bracket_token.surround(tokens, |tokens| {
3292 self.index.to_tokens(tokens);
3293 });
3294 }
3295 }
3296
3297 #[cfg(feature = "full")]
3298 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3299 impl ToTokens for ExprRange {
to_tokens(&self, tokens: &mut TokenStream)3300 fn to_tokens(&self, tokens: &mut TokenStream) {
3301 outer_attrs_to_tokens(&self.attrs, tokens);
3302 self.from.to_tokens(tokens);
3303 match &self.limits {
3304 RangeLimits::HalfOpen(t) => t.to_tokens(tokens),
3305 RangeLimits::Closed(t) => t.to_tokens(tokens),
3306 }
3307 self.to.to_tokens(tokens);
3308 }
3309 }
3310
3311 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3312 impl ToTokens for ExprPath {
to_tokens(&self, tokens: &mut TokenStream)3313 fn to_tokens(&self, tokens: &mut TokenStream) {
3314 outer_attrs_to_tokens(&self.attrs, tokens);
3315 private::print_path(tokens, &self.qself, &self.path);
3316 }
3317 }
3318
3319 #[cfg(feature = "full")]
3320 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3321 impl ToTokens for ExprReference {
to_tokens(&self, tokens: &mut TokenStream)3322 fn to_tokens(&self, tokens: &mut TokenStream) {
3323 outer_attrs_to_tokens(&self.attrs, tokens);
3324 self.and_token.to_tokens(tokens);
3325 self.mutability.to_tokens(tokens);
3326 self.expr.to_tokens(tokens);
3327 }
3328 }
3329
3330 #[cfg(feature = "full")]
3331 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3332 impl ToTokens for ExprBreak {
to_tokens(&self, tokens: &mut TokenStream)3333 fn to_tokens(&self, tokens: &mut TokenStream) {
3334 outer_attrs_to_tokens(&self.attrs, tokens);
3335 self.break_token.to_tokens(tokens);
3336 self.label.to_tokens(tokens);
3337 self.expr.to_tokens(tokens);
3338 }
3339 }
3340
3341 #[cfg(feature = "full")]
3342 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3343 impl ToTokens for ExprContinue {
to_tokens(&self, tokens: &mut TokenStream)3344 fn to_tokens(&self, tokens: &mut TokenStream) {
3345 outer_attrs_to_tokens(&self.attrs, tokens);
3346 self.continue_token.to_tokens(tokens);
3347 self.label.to_tokens(tokens);
3348 }
3349 }
3350
3351 #[cfg(feature = "full")]
3352 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3353 impl ToTokens for ExprReturn {
to_tokens(&self, tokens: &mut TokenStream)3354 fn to_tokens(&self, tokens: &mut TokenStream) {
3355 outer_attrs_to_tokens(&self.attrs, tokens);
3356 self.return_token.to_tokens(tokens);
3357 self.expr.to_tokens(tokens);
3358 }
3359 }
3360
3361 #[cfg(feature = "full")]
3362 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3363 impl ToTokens for ExprMacro {
to_tokens(&self, tokens: &mut TokenStream)3364 fn to_tokens(&self, tokens: &mut TokenStream) {
3365 outer_attrs_to_tokens(&self.attrs, tokens);
3366 self.mac.to_tokens(tokens);
3367 }
3368 }
3369
3370 #[cfg(feature = "full")]
3371 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3372 impl ToTokens for ExprStruct {
to_tokens(&self, tokens: &mut TokenStream)3373 fn to_tokens(&self, tokens: &mut TokenStream) {
3374 outer_attrs_to_tokens(&self.attrs, tokens);
3375 self.path.to_tokens(tokens);
3376 self.brace_token.surround(tokens, |tokens| {
3377 inner_attrs_to_tokens(&self.attrs, tokens);
3378 self.fields.to_tokens(tokens);
3379 if let Some(dot2_token) = &self.dot2_token {
3380 dot2_token.to_tokens(tokens);
3381 } else if self.rest.is_some() {
3382 Token![..](Span::call_site()).to_tokens(tokens);
3383 }
3384 self.rest.to_tokens(tokens);
3385 })
3386 }
3387 }
3388
3389 #[cfg(feature = "full")]
3390 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3391 impl ToTokens for ExprRepeat {
to_tokens(&self, tokens: &mut TokenStream)3392 fn to_tokens(&self, tokens: &mut TokenStream) {
3393 outer_attrs_to_tokens(&self.attrs, tokens);
3394 self.bracket_token.surround(tokens, |tokens| {
3395 inner_attrs_to_tokens(&self.attrs, tokens);
3396 self.expr.to_tokens(tokens);
3397 self.semi_token.to_tokens(tokens);
3398 self.len.to_tokens(tokens);
3399 })
3400 }
3401 }
3402
3403 #[cfg(feature = "full")]
3404 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3405 impl ToTokens for ExprGroup {
to_tokens(&self, tokens: &mut TokenStream)3406 fn to_tokens(&self, tokens: &mut TokenStream) {
3407 outer_attrs_to_tokens(&self.attrs, tokens);
3408 self.group_token.surround(tokens, |tokens| {
3409 self.expr.to_tokens(tokens);
3410 });
3411 }
3412 }
3413
3414 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3415 impl ToTokens for ExprParen {
to_tokens(&self, tokens: &mut TokenStream)3416 fn to_tokens(&self, tokens: &mut TokenStream) {
3417 outer_attrs_to_tokens(&self.attrs, tokens);
3418 self.paren_token.surround(tokens, |tokens| {
3419 inner_attrs_to_tokens(&self.attrs, tokens);
3420 self.expr.to_tokens(tokens);
3421 });
3422 }
3423 }
3424
3425 #[cfg(feature = "full")]
3426 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3427 impl ToTokens for ExprTry {
to_tokens(&self, tokens: &mut TokenStream)3428 fn to_tokens(&self, tokens: &mut TokenStream) {
3429 outer_attrs_to_tokens(&self.attrs, tokens);
3430 self.expr.to_tokens(tokens);
3431 self.question_token.to_tokens(tokens);
3432 }
3433 }
3434
3435 #[cfg(feature = "full")]
3436 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3437 impl ToTokens for Label {
to_tokens(&self, tokens: &mut TokenStream)3438 fn to_tokens(&self, tokens: &mut TokenStream) {
3439 self.name.to_tokens(tokens);
3440 self.colon_token.to_tokens(tokens);
3441 }
3442 }
3443
3444 #[cfg(feature = "full")]
3445 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3446 impl ToTokens for FieldValue {
to_tokens(&self, tokens: &mut TokenStream)3447 fn to_tokens(&self, tokens: &mut TokenStream) {
3448 outer_attrs_to_tokens(&self.attrs, tokens);
3449 self.member.to_tokens(tokens);
3450 if let Some(colon_token) = &self.colon_token {
3451 colon_token.to_tokens(tokens);
3452 self.expr.to_tokens(tokens);
3453 }
3454 }
3455 }
3456
3457 #[cfg(feature = "full")]
3458 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
3459 impl ToTokens for Arm {
to_tokens(&self, tokens: &mut TokenStream)3460 fn to_tokens(&self, tokens: &mut TokenStream) {
3461 tokens.append_all(&self.attrs);
3462 self.pat.to_tokens(tokens);
3463 if let Some((if_token, guard)) = &self.guard {
3464 if_token.to_tokens(tokens);
3465 guard.to_tokens(tokens);
3466 }
3467 self.fat_arrow_token.to_tokens(tokens);
3468 self.body.to_tokens(tokens);
3469 self.comma.to_tokens(tokens);
3470 }
3471 }
3472 }
3473