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