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