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