1use crate::attr::Attribute;
2#[cfg(all(feature = "parsing", feature = "full"))]
3use crate::error::Result;
4#[cfg(feature = "parsing")]
5use crate::ext::IdentExt as _;
6#[cfg(feature = "full")]
7use crate::generics::BoundLifetimes;
8use crate::ident::Ident;
9#[cfg(any(feature = "parsing", feature = "full"))]
10use crate::lifetime::Lifetime;
11use crate::lit::Lit;
12use crate::mac::Macro;
13use crate::op::{BinOp, UnOp};
14#[cfg(feature = "parsing")]
15use crate::parse::ParseStream;
16#[cfg(feature = "full")]
17use crate::pat::Pat;
18use crate::path::{AngleBracketedGenericArguments, Path, QSelf};
19use crate::punctuated::Punctuated;
20#[cfg(feature = "full")]
21use crate::stmt::Block;
22use crate::token;
23use crate::ty::Type;
24#[cfg(feature = "full")]
25use crate::ty::{PointerMutability, ReturnType};
26use alloc::boxed::Box;
27use alloc::vec::Vec;
28#[cfg(feature = "printing")]
29use core::fmt::{self, Display};
30use core::hash::{Hash, Hasher};
31#[cfg(all(feature = "parsing", feature = "full"))]
32use core::mem;
33use proc_macro2::{Span, TokenStream};
34#[cfg(feature = "printing")]
35use quote::IdentFragment;
36
37ast_enum_of_structs! {
38 #[cfg_attr(not(doctest), doc = " ...")]
127 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
139 #[non_exhaustive]
140 pub enum Expr {
141 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
143 Array(ExprArray),
144
145 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
147 Assign(ExprAssign),
148
149 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
151 Async(ExprAsync),
152
153 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
155 Await(ExprAwait),
156
157 Binary(ExprBinary),
159
160 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
162 Block(ExprBlock),
163
164 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
167 Break(ExprBreak),
168
169 Call(ExprCall),
171
172 Cast(ExprCast),
174
175 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
177 Closure(ExprClosure),
178
179 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
181 Const(ExprConst),
182
183 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
185 Continue(ExprContinue),
186
187 Field(ExprField),
190
191 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
193 ForLoop(ExprForLoop),
194
195 Group(ExprGroup),
201
202 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
208 If(ExprIf),
209
210 Index(ExprIndex),
212
213 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
215 Infer(ExprInfer),
216
217 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
219 Let(ExprLet),
220
221 Lit(ExprLit),
223
224 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
226 Loop(ExprLoop),
227
228 Macro(ExprMacro),
230
231 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
233 Match(ExprMatch),
234
235 MethodCall(ExprMethodCall),
237
238 Paren(ExprParen),
240
241 Path(ExprPath),
246
247 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
249 Range(ExprRange),
250
251 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
253 RawAddr(ExprRawAddr),
254
255 Reference(ExprReference),
257
258 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
260 Repeat(ExprRepeat),
261
262 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
264 Return(ExprReturn),
265
266 Struct(ExprStruct),
271
272 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
274 Try(ExprTry),
275
276 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
278 TryBlock(ExprTryBlock),
279
280 Tuple(ExprTuple),
282
283 Unary(ExprUnary),
285
286 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
288 Unsafe(ExprUnsafe),
289
290 Verbatim(TokenStream),
298
299 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
301 While(ExprWhile),
302
303 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
305 Yield(ExprYield),
306 }
307}
308
309ast_struct! {
310 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
312 pub struct ExprArray #full {
313 pub attrs: Vec<Attribute>,
314 pub bracket_token: token::Bracket,
315 pub elems: Punctuated<Expr, Token![,]>,
316 }
317}
318
319ast_struct! {
320 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
322 pub struct ExprAssign #full {
323 pub attrs: Vec<Attribute>,
324 pub left: Box<Expr>,
325 pub eq_token: Token![=],
326 pub right: Box<Expr>,
327 }
328}
329
330ast_struct! {
331 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
333 pub struct ExprAsync #full {
334 pub attrs: Vec<Attribute>,
335 pub async_token: Token![async],
336 pub capture: Option<Token![move]>,
337 pub modifiers: BlockModifiers,
339 pub block: Block,
340 }
341}
342
343ast_struct! {
344 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
346 pub struct ExprAwait #full {
347 pub attrs: Vec<Attribute>,
348 pub base: Box<Expr>,
349 pub dot_token: Token![.],
350 pub await_token: Token![await],
351 }
352}
353
354ast_struct! {
355 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
357 pub struct ExprBinary {
358 pub attrs: Vec<Attribute>,
359 pub left: Box<Expr>,
360 pub op: BinOp,
361 pub right: Box<Expr>,
362 }
363}
364
365ast_struct! {
366 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
368 pub struct ExprBlock #full {
369 pub attrs: Vec<Attribute>,
370 pub label: Option<Label>,
371 pub block: Block,
372 }
373}
374
375ast_struct! {
376 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
379 pub struct ExprBreak #full {
380 pub attrs: Vec<Attribute>,
381 pub break_token: Token![break],
382 pub label: Option<Lifetime>,
383 pub expr: Option<Box<Expr>>,
384 }
385}
386
387ast_struct! {
388 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
390 pub struct ExprCall {
391 pub attrs: Vec<Attribute>,
392 pub func: Box<Expr>,
393 pub paren_token: token::Paren,
394 pub args: Punctuated<Expr, Token![,]>,
395 }
396}
397
398ast_struct! {
399 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
401 pub struct ExprCast {
402 pub attrs: Vec<Attribute>,
403 pub expr: Box<Expr>,
404 pub as_token: Token![as],
405 pub ty: Box<Type>,
406 }
407}
408
409ast_struct! {
410 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
412 pub struct ExprClosure #full {
413 pub attrs: Vec<Attribute>,
414 pub lifetimes: Option<BoundLifetimes>,
415 pub modifiers: ClosureModifiers,
417 pub constness: Option<Token![const]>,
418 pub asyncness: Option<Token![async]>,
419 pub capture: Option<Token![move]>,
420 pub inputs_begin: Token![|],
421 pub inputs: Punctuated<Pat, Token![,]>,
422 pub inputs_end: Token![|],
423 pub output: ReturnType,
424 pub body: Box<Expr>,
425 }
426}
427
428#[cfg(feature = "full")]
429ast_struct! {
430 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
441 #[non_exhaustive]
442 pub struct ClosureModifiers {}
443}
444
445#[cfg(feature = "full")]
446impl Default for ClosureModifiers {
447 fn default() -> Self {
448 ClosureModifiers {}
449 }
450}
451
452#[cfg(feature = "full")]
453impl ClosureModifiers {
454 #[cfg(feature = "parsing")]
455 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
456 pub fn require_empty(&self) -> Result<()> {
457 Ok(())
458 }
459}
460
461ast_struct! {
462 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
464 pub struct ExprConst #full {
465 pub attrs: Vec<Attribute>,
466 pub const_token: Token![const],
467 pub modifiers: BlockModifiers,
469 pub block: Block,
470 }
471}
472
473ast_struct! {
474 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
476 pub struct ExprContinue #full {
477 pub attrs: Vec<Attribute>,
478 pub continue_token: Token![continue],
479 pub label: Option<Lifetime>,
480 }
481}
482
483ast_struct! {
484 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
487 pub struct ExprField {
488 pub attrs: Vec<Attribute>,
489 pub base: Box<Expr>,
490 pub dot_token: Token![.],
491 pub member: Member,
492 }
493}
494
495ast_struct! {
496 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
498 pub struct ExprForLoop #full {
499 pub attrs: Vec<Attribute>,
500 pub label: Option<Label>,
501 pub for_token: Token![for],
502 pub pat: Box<Pat>,
503 pub in_token: Token![in],
504 pub expr: Box<Expr>,
505 pub body: Block,
506 }
507}
508
509ast_struct! {
510 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
516 pub struct ExprGroup {
517 pub attrs: Vec<Attribute>,
518 pub group_token: token::Group,
519 pub expr: Box<Expr>,
520 }
521}
522
523ast_struct! {
524 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
530 pub struct ExprIf #full {
531 pub attrs: Vec<Attribute>,
532 pub if_token: Token![if],
533 pub cond: Box<Expr>,
534 pub then_branch: Block,
535 pub else_branch: Option<(Token![else], Box<Expr>)>,
536 }
537}
538
539ast_struct! {
540 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
542 pub struct ExprIndex {
543 pub attrs: Vec<Attribute>,
544 pub expr: Box<Expr>,
545 pub bracket_token: token::Bracket,
546 pub index: Box<Expr>,
547 }
548}
549
550ast_struct! {
551 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
553 pub struct ExprInfer #full {
554 pub attrs: Vec<Attribute>,
555 pub underscore_token: Token![_],
556 }
557}
558
559ast_struct! {
560 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
562 pub struct ExprLet #full {
563 pub attrs: Vec<Attribute>,
564 pub let_token: Token![let],
565 pub pat: Box<Pat>,
566 pub eq_token: Token![=],
567 pub expr: Box<Expr>,
568 }
569}
570
571ast_struct! {
572 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
574 pub struct ExprLit {
575 pub attrs: Vec<Attribute>,
576 pub lit: Lit,
577 }
578}
579
580ast_struct! {
581 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
583 pub struct ExprLoop #full {
584 pub attrs: Vec<Attribute>,
585 pub label: Option<Label>,
586 pub loop_token: Token![loop],
587 pub body: Block,
588 }
589}
590
591ast_struct! {
592 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
594 pub struct ExprMacro {
595 pub attrs: Vec<Attribute>,
596 pub mac: Macro,
597 }
598}
599
600ast_struct! {
601 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
603 pub struct ExprMatch #full {
604 pub attrs: Vec<Attribute>,
605 pub match_token: Token![match],
606 pub expr: Box<Expr>,
607 pub brace_token: token::Brace,
608 pub arms: Vec<Arm>,
609 }
610}
611
612ast_struct! {
613 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
615 pub struct ExprMethodCall {
616 pub attrs: Vec<Attribute>,
617 pub receiver: Box<Expr>,
618 pub dot_token: Token![.],
619 pub method: Ident,
620 pub turbofish: Option<AngleBracketedGenericArguments>,
621 pub paren_token: token::Paren,
622 pub args: Punctuated<Expr, Token![,]>,
623 }
624}
625
626ast_struct! {
627 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
629 pub struct ExprParen {
630 pub attrs: Vec<Attribute>,
631 pub paren_token: token::Paren,
632 pub expr: Box<Expr>,
633 }
634}
635
636ast_struct! {
637 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
642 pub struct ExprPath {
643 pub attrs: Vec<Attribute>,
644 pub qself: Option<QSelf>,
645 pub path: Path,
646 }
647}
648
649ast_struct! {
650 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
652 pub struct ExprRange #full {
653 pub attrs: Vec<Attribute>,
654 pub start: Option<Box<Expr>>,
655 pub limits: RangeLimits,
656 pub end: Option<Box<Expr>>,
657 }
658}
659
660ast_struct! {
661 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
663 pub struct ExprRawAddr #full {
664 pub attrs: Vec<Attribute>,
665 pub and_token: Token![&],
666 pub raw: Token![raw],
667 pub mutability: PointerMutability,
668 pub expr: Box<Expr>,
669 }
670}
671
672ast_struct! {
673 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
675 pub struct ExprReference {
676 pub attrs: Vec<Attribute>,
677 pub and_token: Token![&],
678 pub mutability: Option<Token![mut]>,
679 pub expr: Box<Expr>,
680 }
681}
682
683ast_struct! {
684 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
686 pub struct ExprRepeat #full {
687 pub attrs: Vec<Attribute>,
688 pub bracket_token: token::Bracket,
689 pub expr: Box<Expr>,
690 pub semi_token: Token![;],
691 pub len: Box<Expr>,
692 }
693}
694
695ast_struct! {
696 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
698 pub struct ExprReturn #full {
699 pub attrs: Vec<Attribute>,
700 pub return_token: Token![return],
701 pub expr: Option<Box<Expr>>,
702 }
703}
704
705ast_struct! {
706 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
711 pub struct ExprStruct {
712 pub attrs: Vec<Attribute>,
713 pub qself: Option<QSelf>,
714 pub path: Path,
715 pub brace_token: token::Brace,
716 pub fields: Punctuated<FieldValue, Token![,]>,
717 pub dot2_token: Option<Token![..]>,
718 pub rest: Option<Box<Expr>>,
719 }
720}
721
722ast_struct! {
723 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
725 pub struct ExprTry #full {
726 pub attrs: Vec<Attribute>,
727 pub expr: Box<Expr>,
728 pub question_token: Token![?],
729 }
730}
731
732ast_struct! {
733 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
735 pub struct ExprTryBlock #full {
736 pub attrs: Vec<Attribute>,
737 pub try_token: Token![try],
738 pub modifiers: BlockModifiers,
740 pub block: Block,
741 }
742}
743
744ast_struct! {
745 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
747 pub struct ExprTuple {
748 pub attrs: Vec<Attribute>,
749 pub paren_token: token::Paren,
750 pub elems: Punctuated<Expr, Token![,]>,
751 }
752}
753
754ast_struct! {
755 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
757 pub struct ExprUnary {
758 pub attrs: Vec<Attribute>,
759 pub op: UnOp,
760 pub expr: Box<Expr>,
761 }
762}
763
764ast_struct! {
765 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
767 pub struct ExprUnsafe #full {
768 pub attrs: Vec<Attribute>,
769 pub unsafe_token: Token![unsafe],
770 pub block: Block,
771 }
772}
773
774ast_struct! {
775 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
777 pub struct ExprWhile #full {
778 pub attrs: Vec<Attribute>,
779 pub label: Option<Label>,
780 pub while_token: Token![while],
781 pub cond: Box<Expr>,
782 pub body: Block,
783 }
784}
785
786ast_struct! {
787 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
789 pub struct ExprYield #full {
790 pub attrs: Vec<Attribute>,
791 pub yield_token: Token![yield],
792 pub expr: Option<Box<Expr>>,
793 }
794}
795
796impl Expr {
797 pub const PLACEHOLDER: Self = Expr::Path(ExprPath {
817 attrs: Vec::new(),
818 qself: None,
819 path: Path {
820 leading_colon: None,
821 segments: Punctuated::new(),
822 },
823 });
824
825 #[cfg(all(feature = "full", feature = "parsing"))]
907 #[cfg_attr(docsrs, doc(cfg(all(feature = "full", feature = "parsing"))))]
908 pub fn parse_without_eager_brace(input: ParseStream) -> Result<Expr> {
909 parsing::ambiguous_expr(input, parsing::AllowStruct(false))
910 }
911
912 #[cfg(all(feature = "full", feature = "parsing"))]
969 #[cfg_attr(docsrs, doc(cfg(all(feature = "full", feature = "parsing"))))]
970 pub fn parse_with_earlier_boundary_rule(input: ParseStream) -> Result<Expr> {
971 parsing::parse_with_earlier_boundary_rule(input)
972 }
973
974 #[cfg(feature = "parsing")]
985 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
986 pub fn peek(input: ParseStream) -> bool {
987 input.peek(Ident::peek_any) && !input.peek(Token![as]) || input.peek(token::Paren) || input.peek(token::Bracket) || input.peek(token::Brace) || input.peek(Lit) || input.peek(Token![!]) && !input.peek(Token![!=]) || input.peek(Token![-]) && !input.peek(Token![-=]) && !input.peek(Token![->]) || input.peek(Token![*]) && !input.peek(Token![*=]) || input.peek(Token![|]) && !input.peek(Token![|=]) || input.peek(Token![&]) && !input.peek(Token![&=]) || input.peek(Token![..]) || input.peek(Token![<]) && !input.peek(Token![<=]) && !input.peek(Token![<<=]) || input.peek(Token![::]) || input.peek(Lifetime) || input.peek(Token![#]) }
1003
1004 #[cfg(all(feature = "parsing", feature = "full"))]
1005 pub(crate) fn replace_attrs(&mut self, new: Vec<Attribute>) -> Vec<Attribute> {
1006 match self {
1007 Expr::Array(ExprArray { attrs, .. })
1008 | Expr::Assign(ExprAssign { attrs, .. })
1009 | Expr::Async(ExprAsync { attrs, .. })
1010 | Expr::Await(ExprAwait { attrs, .. })
1011 | Expr::Binary(ExprBinary { attrs, .. })
1012 | Expr::Block(ExprBlock { attrs, .. })
1013 | Expr::Break(ExprBreak { attrs, .. })
1014 | Expr::Call(ExprCall { attrs, .. })
1015 | Expr::Cast(ExprCast { attrs, .. })
1016 | Expr::Closure(ExprClosure { attrs, .. })
1017 | Expr::Const(ExprConst { attrs, .. })
1018 | Expr::Continue(ExprContinue { attrs, .. })
1019 | Expr::Field(ExprField { attrs, .. })
1020 | Expr::ForLoop(ExprForLoop { attrs, .. })
1021 | Expr::Group(ExprGroup { attrs, .. })
1022 | Expr::If(ExprIf { attrs, .. })
1023 | Expr::Index(ExprIndex { attrs, .. })
1024 | Expr::Infer(ExprInfer { attrs, .. })
1025 | Expr::Let(ExprLet { attrs, .. })
1026 | Expr::Lit(ExprLit { attrs, .. })
1027 | Expr::Loop(ExprLoop { attrs, .. })
1028 | Expr::Macro(ExprMacro { attrs, .. })
1029 | Expr::Match(ExprMatch { attrs, .. })
1030 | Expr::MethodCall(ExprMethodCall { attrs, .. })
1031 | Expr::Paren(ExprParen { attrs, .. })
1032 | Expr::Path(ExprPath { attrs, .. })
1033 | Expr::Range(ExprRange { attrs, .. })
1034 | Expr::RawAddr(ExprRawAddr { attrs, .. })
1035 | Expr::Reference(ExprReference { attrs, .. })
1036 | Expr::Repeat(ExprRepeat { attrs, .. })
1037 | Expr::Return(ExprReturn { attrs, .. })
1038 | Expr::Struct(ExprStruct { attrs, .. })
1039 | Expr::Try(ExprTry { attrs, .. })
1040 | Expr::TryBlock(ExprTryBlock { attrs, .. })
1041 | Expr::Tuple(ExprTuple { attrs, .. })
1042 | Expr::Unary(ExprUnary { attrs, .. })
1043 | Expr::Unsafe(ExprUnsafe { attrs, .. })
1044 | Expr::While(ExprWhile { attrs, .. })
1045 | Expr::Yield(ExprYield { attrs, .. }) => mem::replace(attrs, new),
1046 Expr::Verbatim(_) => Vec::new(),
1047 }
1048 }
1049}
1050
1051ast_enum! {
1052 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
1055 pub enum Member {
1056 Named(Ident),
1058 Unnamed(Index),
1060 }
1061}
1062
1063impl From<Ident> for Member {
1064 fn from(ident: Ident) -> Member {
1065 Member::Named(ident)
1066 }
1067}
1068
1069impl From<Index> for Member {
1070 fn from(index: Index) -> Member {
1071 Member::Unnamed(index)
1072 }
1073}
1074
1075impl From<usize> for Member {
1076 fn from(index: usize) -> Member {
1077 Member::Unnamed(Index::from(index))
1078 }
1079}
1080
1081impl Eq for Member {}
1082
1083impl PartialEq for Member {
1084 fn eq(&self, other: &Self) -> bool {
1085 match (self, other) {
1086 (Member::Named(this), Member::Named(other)) => this == other,
1087 (Member::Unnamed(this), Member::Unnamed(other)) => this == other,
1088 _ => false,
1089 }
1090 }
1091}
1092
1093impl Hash for Member {
1094 fn hash<H: Hasher>(&self, state: &mut H) {
1095 match self {
1096 Member::Named(m) => m.hash(state),
1097 Member::Unnamed(m) => m.hash(state),
1098 }
1099 }
1100}
1101
1102#[cfg(feature = "printing")]
1103impl IdentFragment for Member {
1104 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1105 match self {
1106 Member::Named(m) => Display::fmt(m, formatter),
1107 Member::Unnamed(m) => Display::fmt(&m.index, formatter),
1108 }
1109 }
1110
1111 fn span(&self) -> Option<Span> {
1112 match self {
1113 Member::Named(m) => Some(m.span()),
1114 Member::Unnamed(m) => Some(m.span),
1115 }
1116 }
1117}
1118
1119#[cfg(any(feature = "parsing", feature = "printing"))]
1120impl Member {
1121 pub(crate) fn is_named(&self) -> bool {
1122 match self {
1123 Member::Named(_) => true,
1124 Member::Unnamed(_) => false,
1125 }
1126 }
1127}
1128
1129ast_struct! {
1130 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
1132 pub struct Index {
1133 pub index: u32,
1134 pub span: Span,
1135 }
1136}
1137
1138impl From<usize> for Index {
1139 fn from(index: usize) -> Index {
1140 assert!(index < u32::MAX as usize);
1141 Index {
1142 index: index as u32,
1143 span: Span::call_site(),
1144 }
1145 }
1146}
1147
1148impl Eq for Index {}
1149
1150impl PartialEq for Index {
1151 fn eq(&self, other: &Self) -> bool {
1152 self.index == other.index
1153 }
1154}
1155
1156impl Hash for Index {
1157 fn hash<H: Hasher>(&self, state: &mut H) {
1158 self.index.hash(state);
1159 }
1160}
1161
1162#[cfg(feature = "printing")]
1163impl IdentFragment for Index {
1164 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1165 Display::fmt(&self.index, formatter)
1166 }
1167
1168 fn span(&self) -> Option<Span> {
1169 Some(self.span)
1170 }
1171}
1172
1173ast_struct! {
1174 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
1176 pub struct FieldValue {
1177 pub attrs: Vec<Attribute>,
1178 pub member: Member,
1179
1180 pub colon_token: Option<Token![:]>,
1183
1184 pub expr: Expr,
1185 }
1186}
1187
1188#[cfg(feature = "full")]
1189ast_struct! {
1190 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
1192 pub struct Label {
1193 pub name: Lifetime,
1194 pub colon_token: Token![:],
1195 }
1196}
1197
1198#[cfg(feature = "full")]
1199ast_struct! {
1200 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
1218 pub struct Arm {
1219 pub attrs: Vec<Attribute>,
1220 pub pat: Pat,
1221 pub fat_arrow_token: Token![=>],
1222 pub body: Box<Expr>,
1223 pub comma: Option<Token![,]>,
1224 }
1225}
1226
1227#[cfg(feature = "full")]
1228ast_struct! {
1229 #[non_exhaustive]
1240 pub struct BlockModifiers {}
1241}
1242
1243#[cfg(feature = "full")]
1244impl Default for BlockModifiers {
1245 fn default() -> Self {
1246 BlockModifiers {}
1247 }
1248}
1249
1250#[cfg(feature = "full")]
1251impl BlockModifiers {
1252 #[cfg(feature = "parsing")]
1253 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1254 pub fn require_empty(&self) -> Result<()> {
1255 Ok(())
1256 }
1257}
1258
1259#[cfg(feature = "full")]
1260ast_enum! {
1261 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
1263 pub enum RangeLimits {
1264 HalfOpen(Token![..]),
1266 Closed(Token![..=]),
1268 }
1269}
1270
1271#[cfg(feature = "parsing")]
1272pub(crate) mod parsing {
1273 #[cfg(feature = "full")]
1274 use crate::attr;
1275 use crate::attr::Attribute;
1276 #[cfg(feature = "full")]
1277 use crate::buffer::Cursor;
1278 #[cfg(feature = "full")]
1279 use crate::classify;
1280 use crate::error::{Error, Result};
1281 #[cfg(feature = "full")]
1282 use crate::expr::{
1283 Arm, BlockModifiers, ClosureModifiers, ExprArray, ExprAssign, ExprAsync, ExprAwait,
1284 ExprBlock, ExprBreak, ExprClosure, ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer,
1285 ExprLet, ExprLoop, ExprMatch, ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry,
1286 ExprTryBlock, ExprUnsafe, ExprWhile, ExprYield, Label, RangeLimits,
1287 };
1288 use crate::expr::{
1289 Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro,
1290 ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprTuple, ExprUnary,
1291 FieldValue, Index, Member,
1292 };
1293 #[cfg(feature = "full")]
1294 use crate::generics::{self, BoundLifetimes};
1295 use crate::ident::Ident;
1296 use crate::lifetime::Lifetime;
1297 use crate::lit::{Lit, LitFloat, LitInt};
1298 use crate::mac::{self, Macro};
1299 use crate::op::BinOp;
1300 use crate::parse::discouraged::Speculative as _;
1301 use crate::parse::{End, Parse, ParseStream};
1302 #[cfg(feature = "full")]
1303 use crate::pat::{Pat, PatType};
1304 use crate::path::{self, AngleBracketedGenericArguments, Path, QSelf};
1305 use crate::precedence::Precedence;
1306 use crate::punctuated::Punctuated;
1307 #[cfg(feature = "full")]
1308 use crate::stmt::Block;
1309 use crate::token;
1310 use crate::ty;
1311 #[cfg(feature = "full")]
1312 use crate::ty::{PointerMutability, ReturnType, Type};
1313 use crate::verbatim;
1314 use alloc::boxed::Box;
1315 use alloc::format;
1316 use alloc::string::ToString;
1317 use alloc::vec::Vec;
1318 use core::mem;
1319 #[cfg(feature = "full")]
1320 use proc_macro2::{Span, TokenStream};
1321
1322 #[cfg(feature = "full")]
1328 pub(super) struct AllowStruct(pub bool);
1329
1330 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1331 impl Parse for Expr {
1332 fn parse(input: ParseStream) -> Result<Self> {
1333 ambiguous_expr(
1334 input,
1335 #[cfg(feature = "full")]
1336 AllowStruct(true),
1337 )
1338 }
1339 }
1340
1341 #[cfg(feature = "full")]
1342 pub(super) fn parse_with_earlier_boundary_rule(input: ParseStream) -> Result<Expr> {
1343 let mut attrs = input.call(expr_attrs)?;
1344 let mut expr = if input.peek(token::Group) && {
1345 let group = crate::group::parse_group(&input.fork())?;
1346 !(group.content.peek(Lifetime) && group.content.peek2(End))
1347 } {
1348 let allow_struct = AllowStruct(true);
1349 let atom = expr_group(input, allow_struct)?;
1350 if continue_parsing_early(&atom) {
1351 trailer_helper(input, atom)?
1352 } else {
1353 atom
1354 }
1355 } else if input.peek(Token![if]) {
1356 Expr::If(input.parse()?)
1357 } else if input.peek(Token![while]) {
1358 Expr::While(input.parse()?)
1359 } else if input.peek(Token![for])
1360 && !generics::parsing::choose_generics_over_qpath_after_keyword(input)
1361 {
1362 Expr::ForLoop(input.parse()?)
1363 } else if input.peek(Token![loop]) {
1364 Expr::Loop(input.parse()?)
1365 } else if input.peek(Token![match]) {
1366 Expr::Match(input.parse()?)
1367 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
1368 Expr::TryBlock(input.parse()?)
1369 } else if input.peek(Token![unsafe]) {
1370 Expr::Unsafe(input.parse()?)
1371 } else if input.peek(Token![const]) && input.peek2(token::Brace) {
1372 Expr::Const(input.parse()?)
1373 } else if input.peek(token::Brace) {
1374 Expr::Block(input.parse()?)
1375 } else if input.peek(Lifetime) {
1376 atom_labeled(input)?
1377 } else {
1378 let allow_struct = AllowStruct(true);
1379 unary_expr(input, allow_struct)?
1380 };
1381
1382 if continue_parsing_early(&expr) {
1383 attrs.extend(expr.replace_attrs(Vec::new()));
1384 expr.replace_attrs(attrs);
1385
1386 let allow_struct = AllowStruct(true);
1387 return parse_expr(input, expr, allow_struct, Precedence::MIN);
1388 }
1389
1390 if input.peek(Token![.]) && !input.peek(Token![..]) || input.peek(Token![?]) {
1391 expr = trailer_helper(input, expr)?;
1392
1393 attrs.extend(expr.replace_attrs(Vec::new()));
1394 expr.replace_attrs(attrs);
1395
1396 let allow_struct = AllowStruct(true);
1397 return parse_expr(input, expr, allow_struct, Precedence::MIN);
1398 }
1399
1400 attrs.extend(expr.replace_attrs(Vec::new()));
1401 expr.replace_attrs(attrs);
1402 Ok(expr)
1403 }
1404
1405 #[cfg(feature = "full")]
1406 impl Copy for AllowStruct {}
1407
1408 #[cfg(feature = "full")]
1409 impl Clone for AllowStruct {
1410 fn clone(&self) -> Self {
1411 *self
1412 }
1413 }
1414
1415 #[cfg(feature = "full")]
1416 fn parse_expr(
1417 input: ParseStream,
1418 mut lhs: Expr,
1419 allow_struct: AllowStruct,
1420 base: Precedence,
1421 ) -> Result<Expr> {
1422 loop {
1423 let ahead = input.fork();
1424 if let Expr::Range(_) = lhs {
1425 break;
1427 } else if let Ok(op) = ahead.parse::<BinOp>() {
1428 let precedence = Precedence::of_binop(&op);
1429 if precedence < base {
1430 break;
1431 }
1432 if precedence == Precedence::Assign {
1433 if let Expr::Range(_) = lhs {
1434 break;
1435 }
1436 }
1437 if precedence == Precedence::Compare {
1438 if let Expr::Binary(lhs) = &lhs {
1439 if Precedence::of_binop(&lhs.op) == Precedence::Compare {
1440 return Err(input.error("comparison operators cannot be chained"));
1441 }
1442 }
1443 }
1444 input.advance_to(&ahead);
1445 let right = parse_binop_rhs(input, allow_struct, precedence)?;
1446 lhs = Expr::Binary(ExprBinary {
1447 attrs: Vec::new(),
1448 left: Box::new(lhs),
1449 op,
1450 right,
1451 });
1452 } else if Precedence::Assign >= base
1453 && input.peek(Token![=])
1454 && !input.peek(Token![=>])
1455 && match lhs {
1456 Expr::Range(_) => false,
1457 _ => true,
1458 }
1459 {
1460 let eq_token: Token![=] = input.parse()?;
1461 let right = parse_binop_rhs(input, allow_struct, Precedence::Assign)?;
1462 lhs = Expr::Assign(ExprAssign {
1463 attrs: Vec::new(),
1464 left: Box::new(lhs),
1465 eq_token,
1466 right,
1467 });
1468 } else if Precedence::Range >= base && input.peek(Token![..]) {
1469 let limits: RangeLimits = input.parse()?;
1470 let end = parse_range_end(input, &limits, allow_struct)?;
1471 lhs = Expr::Range(ExprRange {
1472 attrs: Vec::new(),
1473 start: Some(Box::new(lhs)),
1474 limits,
1475 end,
1476 });
1477 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1478 let as_token: Token![as] = input.parse()?;
1479 let allow_plus = false;
1480 let allow_group_generic = false;
1481 let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
1482 check_cast(input)?;
1483 lhs = Expr::Cast(ExprCast {
1484 attrs: Vec::new(),
1485 expr: Box::new(lhs),
1486 as_token,
1487 ty: Box::new(ty),
1488 });
1489 } else if input.peek(Token![<-]) {
1490 return Err(input.error("unexpected operator `<-`, if this is intended to be a comparison against a negative then a space is required: `< -`"));
1491 } else {
1492 break;
1493 }
1494 }
1495 Ok(lhs)
1496 }
1497
1498 #[cfg(not(feature = "full"))]
1499 fn parse_expr(input: ParseStream, mut lhs: Expr, base: Precedence) -> Result<Expr> {
1500 loop {
1501 let ahead = input.fork();
1502 if let Ok(op) = ahead.parse::<BinOp>() {
1503 let precedence = Precedence::of_binop(&op);
1504 if precedence < base {
1505 break;
1506 }
1507 if precedence == Precedence::Compare {
1508 if let Expr::Binary(lhs) = &lhs {
1509 if Precedence::of_binop(&lhs.op) == Precedence::Compare {
1510 return Err(input.error("comparison operators cannot be chained"));
1511 }
1512 }
1513 }
1514 input.advance_to(&ahead);
1515 let right = parse_binop_rhs(input, precedence)?;
1516 lhs = Expr::Binary(ExprBinary {
1517 attrs: Vec::new(),
1518 left: Box::new(lhs),
1519 op,
1520 right,
1521 });
1522 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1523 let as_token: Token![as] = input.parse()?;
1524 let allow_plus = false;
1525 let allow_group_generic = false;
1526 let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
1527 check_cast(input)?;
1528 lhs = Expr::Cast(ExprCast {
1529 attrs: Vec::new(),
1530 expr: Box::new(lhs),
1531 as_token,
1532 ty: Box::new(ty),
1533 });
1534 } else if input.peek(Token![<-]) {
1535 return Err(input.error("unexpected operator `<-`, if this is intended to be a comparison against a negative then a space is required: `< -`"));
1536 } else {
1537 break;
1538 }
1539 }
1540 Ok(lhs)
1541 }
1542
1543 fn parse_binop_rhs(
1544 input: ParseStream,
1545 #[cfg(feature = "full")] allow_struct: AllowStruct,
1546 precedence: Precedence,
1547 ) -> Result<Box<Expr>> {
1548 let mut rhs = unary_expr(
1549 input,
1550 #[cfg(feature = "full")]
1551 allow_struct,
1552 )?;
1553 loop {
1554 let next = peek_precedence(input);
1555 if next > precedence || next == precedence && precedence == Precedence::Assign {
1556 let cursor = input.cursor();
1557 rhs = parse_expr(
1558 input,
1559 rhs,
1560 #[cfg(feature = "full")]
1561 allow_struct,
1562 next,
1563 )?;
1564 if cursor == input.cursor() {
1565 break;
1570 }
1571 } else {
1572 break;
1573 }
1574 }
1575 Ok(Box::new(rhs))
1576 }
1577
1578 fn peek_precedence(input: ParseStream) -> Precedence {
1579 if let Ok(op) = input.fork().parse() {
1580 Precedence::of_binop(&op)
1581 } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
1582 Precedence::Assign
1583 } else if input.peek(Token![..]) {
1584 Precedence::Range
1585 } else if input.peek(Token![as]) {
1586 Precedence::Cast
1587 } else {
1588 Precedence::MIN
1589 }
1590 }
1591
1592 pub(super) fn ambiguous_expr(
1594 input: ParseStream,
1595 #[cfg(feature = "full")] allow_struct: AllowStruct,
1596 ) -> Result<Expr> {
1597 let lhs = unary_expr(
1598 input,
1599 #[cfg(feature = "full")]
1600 allow_struct,
1601 )?;
1602 parse_expr(
1603 input,
1604 lhs,
1605 #[cfg(feature = "full")]
1606 allow_struct,
1607 Precedence::MIN,
1608 )
1609 }
1610
1611 #[cfg(feature = "full")]
1612 fn expr_attrs(input: ParseStream) -> Result<Vec<Attribute>> {
1613 let mut attrs = Vec::new();
1614 while !input.peek(token::Group) && input.peek(Token![#]) {
1615 attrs.push(input.call(attr::parsing::single_parse_outer)?);
1616 }
1617 Ok(attrs)
1618 }
1619
1620 #[cfg(feature = "full")]
1625 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1626 let begin = input.cursor();
1627 let attrs = input.call(expr_attrs)?;
1628 if input.peek(token::Group) {
1629 return trailer_expr(begin, attrs, input, allow_struct);
1630 }
1631
1632 if input.peek(Token![&]) {
1633 let and_token: Token![&] = input.parse()?;
1634 let raw: Option<Token![raw]> = if input.peek(Token![raw])
1635 && (input.peek2(Token![mut]) || input.peek2(Token![const]))
1636 {
1637 Some(input.parse()?)
1638 } else {
1639 None
1640 };
1641 let mutability: Option<Token![mut]> = input.parse()?;
1642 let const_token: Option<Token![const]> = if raw.is_some() && mutability.is_none() {
1643 Some(input.parse()?)
1644 } else {
1645 None
1646 };
1647 let expr = Box::new(unary_expr(input, allow_struct)?);
1648 if let Some(raw) = raw {
1649 Ok(Expr::RawAddr(ExprRawAddr {
1650 attrs,
1651 and_token,
1652 raw,
1653 mutability: match mutability {
1654 Some(mut_token) => PointerMutability::Mut(mut_token),
1655 None => PointerMutability::Const(const_token.unwrap()),
1656 },
1657 expr,
1658 }))
1659 } else {
1660 Ok(Expr::Reference(ExprReference {
1661 attrs,
1662 and_token,
1663 mutability,
1664 expr,
1665 }))
1666 }
1667 } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
1668 expr_unary(input, attrs, allow_struct).map(Expr::Unary)
1669 } else {
1670 trailer_expr(begin, attrs, input, allow_struct)
1671 }
1672 }
1673
1674 #[cfg(not(feature = "full"))]
1675 fn unary_expr(input: ParseStream) -> Result<Expr> {
1676 if input.peek(Token![&]) {
1677 Ok(Expr::Reference(ExprReference {
1678 attrs: Vec::new(),
1679 and_token: input.parse()?,
1680 mutability: input.parse()?,
1681 expr: Box::new(unary_expr(input)?),
1682 }))
1683 } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
1684 Ok(Expr::Unary(ExprUnary {
1685 attrs: Vec::new(),
1686 op: input.parse()?,
1687 expr: Box::new(unary_expr(input)?),
1688 }))
1689 } else {
1690 trailer_expr(input)
1691 }
1692 }
1693
1694 #[cfg(feature = "full")]
1701 fn trailer_expr(
1702 begin: Cursor,
1703 mut attrs: Vec<Attribute>,
1704 input: ParseStream,
1705 allow_struct: AllowStruct,
1706 ) -> Result<Expr> {
1707 let atom = atom_expr(input, allow_struct)?;
1708 let mut e = trailer_helper(input, atom)?;
1709
1710 if let Expr::Verbatim(tokens) = &mut e {
1711 *tokens = verbatim::between(begin, input.cursor());
1712 } else if !attrs.is_empty() {
1713 if let Expr::Range(range) = e {
1714 let spans: &[Span] = match &range.limits {
1715 RangeLimits::HalfOpen(limits) => &limits.spans,
1716 RangeLimits::Closed(limits) => &limits.spans,
1717 };
1718 return Err(crate::error::new2(
1719 spans[0],
1720 *spans.last().unwrap(),
1721 "attributes are not allowed on range expressions starting with `..`",
1722 ));
1723 }
1724 let inner_attrs = e.replace_attrs(Vec::new());
1725 attrs.extend(inner_attrs);
1726 e.replace_attrs(attrs);
1727 }
1728
1729 Ok(e)
1730 }
1731
1732 #[cfg(feature = "full")]
1733 fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
1734 loop {
1735 if input.peek(token::Paren) {
1736 let content;
1737 e = Expr::Call(ExprCall {
1738 attrs: Vec::new(),
1739 func: Box::new(e),
1740 paren_token: parenthesized!(content in input),
1741 args: content.parse_terminated(Expr::parse, Token![,])?,
1742 });
1743 } else if input.peek(Token![.])
1744 && !input.peek(Token![..])
1745 && match e {
1746 Expr::Range(_) => false,
1747 _ => true,
1748 }
1749 {
1750 let mut dot_token: Token![.] = input.parse()?;
1751
1752 let float_token: Option<LitFloat> = input.parse()?;
1753 if let Some(float_token) = float_token {
1754 if multi_index(&mut e, &mut dot_token, float_token)? {
1755 continue;
1756 }
1757 }
1758
1759 let await_token: Option<Token![await]> = input.parse()?;
1760 if let Some(await_token) = await_token {
1761 e = Expr::Await(ExprAwait {
1762 attrs: Vec::new(),
1763 base: Box::new(e),
1764 dot_token,
1765 await_token,
1766 });
1767 continue;
1768 }
1769
1770 let member: Member = input.parse()?;
1771 let turbofish = if member.is_named() && input.peek(Token![::]) {
1772 Some(AngleBracketedGenericArguments::parse_turbofish(input)?)
1773 } else {
1774 None
1775 };
1776
1777 if turbofish.is_some() || input.peek(token::Paren) {
1778 if let Member::Named(method) = member {
1779 let content;
1780 e = Expr::MethodCall(ExprMethodCall {
1781 attrs: Vec::new(),
1782 receiver: Box::new(e),
1783 dot_token,
1784 method,
1785 turbofish,
1786 paren_token: parenthesized!(content in input),
1787 args: content.parse_terminated(Expr::parse, Token![,])?,
1788 });
1789 continue;
1790 }
1791 }
1792
1793 e = Expr::Field(ExprField {
1794 attrs: Vec::new(),
1795 base: Box::new(e),
1796 dot_token,
1797 member,
1798 });
1799 } else if input.peek(token::Bracket) {
1800 let content;
1801 e = Expr::Index(ExprIndex {
1802 attrs: Vec::new(),
1803 expr: Box::new(e),
1804 bracket_token: bracketed!(content in input),
1805 index: content.parse()?,
1806 });
1807 } else if input.peek(Token![?])
1808 && match e {
1809 Expr::Range(_) => false,
1810 _ => true,
1811 }
1812 {
1813 e = Expr::Try(ExprTry {
1814 attrs: Vec::new(),
1815 expr: Box::new(e),
1816 question_token: input.parse()?,
1817 });
1818 } else {
1819 break;
1820 }
1821 }
1822 Ok(e)
1823 }
1824
1825 #[cfg(not(feature = "full"))]
1826 fn trailer_expr(input: ParseStream) -> Result<Expr> {
1827 let mut e = atom_expr(input)?;
1828
1829 loop {
1830 if input.peek(token::Paren) {
1831 let content;
1832 e = Expr::Call(ExprCall {
1833 attrs: Vec::new(),
1834 func: Box::new(e),
1835 paren_token: parenthesized!(content in input),
1836 args: content.parse_terminated(Expr::parse, Token![,])?,
1837 });
1838 } else if input.peek(Token![.])
1839 && !input.peek(Token![..])
1840 && !input.peek2(Token![await])
1841 {
1842 let mut dot_token: Token![.] = input.parse()?;
1843
1844 let float_token: Option<LitFloat> = input.parse()?;
1845 if let Some(float_token) = float_token {
1846 if multi_index(&mut e, &mut dot_token, float_token)? {
1847 continue;
1848 }
1849 }
1850
1851 let member: Member = input.parse()?;
1852 let turbofish = if member.is_named() && input.peek(Token![::]) {
1853 let colon2_token: Token![::] = input.parse()?;
1854 let turbofish =
1855 AngleBracketedGenericArguments::do_parse(Some(colon2_token), input)?;
1856 Some(turbofish)
1857 } else {
1858 None
1859 };
1860
1861 if turbofish.is_some() || input.peek(token::Paren) {
1862 if let Member::Named(method) = member {
1863 let content;
1864 e = Expr::MethodCall(ExprMethodCall {
1865 attrs: Vec::new(),
1866 receiver: Box::new(e),
1867 dot_token,
1868 method,
1869 turbofish,
1870 paren_token: parenthesized!(content in input),
1871 args: content.parse_terminated(Expr::parse, Token![,])?,
1872 });
1873 continue;
1874 }
1875 }
1876
1877 e = Expr::Field(ExprField {
1878 attrs: Vec::new(),
1879 base: Box::new(e),
1880 dot_token,
1881 member,
1882 });
1883 } else if input.peek(token::Bracket) {
1884 let content;
1885 e = Expr::Index(ExprIndex {
1886 attrs: Vec::new(),
1887 expr: Box::new(e),
1888 bracket_token: bracketed!(content in input),
1889 index: content.parse()?,
1890 });
1891 } else {
1892 break;
1893 }
1894 }
1895
1896 Ok(e)
1897 }
1898
1899 #[cfg(feature = "full")]
1902 fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1903 if input.peek(token::Group) && {
1904 let group = crate::group::parse_group(&input.fork())?;
1905 !(group.content.peek(Lifetime) && group.content.peek2(End))
1906 } {
1907 expr_group(input, allow_struct)
1908 } else if input.peek(Lit) {
1909 input.parse().map(Expr::Lit)
1910 } else if input.peek(Token![async])
1911 && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
1912 {
1913 input.parse().map(Expr::Async)
1914 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
1915 input.parse().map(Expr::TryBlock)
1916 } else if input.peek(Token![|])
1917 || input.peek(Token![move])
1918 || input.peek(Token![for])
1919 && generics::parsing::choose_generics_over_qpath_after_keyword(input)
1920 || input.peek(Token![const]) && !input.peek2(token::Brace)
1921 || input.peek(Token![static])
1922 || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1923 {
1924 expr_closure(input, allow_struct).map(Expr::Closure)
1925 } else if input.cursor().peek_keyword("builtin") && input.peek2(Token![#]) {
1926 expr_builtin(input)
1927 } else if input.peek(Ident)
1928 || input.peek(Token![::])
1929 || input.peek(Token![<])
1930 || input.peek(Token![self])
1931 || input.peek(Token![Self])
1932 || input.peek(Token![super])
1933 || input.peek(Token![crate])
1934 || input.peek(Token![try]) && (input.peek2(Token![!]) || input.peek2(Token![::]))
1935 {
1936 path_or_macro_or_struct(input, allow_struct)
1937 } else if input.peek(token::Paren) {
1938 paren_or_tuple(input)
1939 } else if input.peek(Token![break]) {
1940 expr_break(input, allow_struct).map(Expr::Break)
1941 } else if input.peek(Token![continue]) {
1942 input.parse().map(Expr::Continue)
1943 } else if input.peek(Token![return]) {
1944 input.parse().map(Expr::Return)
1945 } else if input.peek(Token![become]) {
1946 expr_become(input)
1947 } else if input.peek(token::Bracket) {
1948 array_or_repeat(input)
1949 } else if input.peek(Token![let]) {
1950 expr_let(input, allow_struct).map(Expr::Let)
1951 } else if input.peek(Token![if]) {
1952 input.parse().map(Expr::If)
1953 } else if input.peek(Token![while]) {
1954 input.parse().map(Expr::While)
1955 } else if input.peek(Token![for]) {
1956 input.parse().map(Expr::ForLoop)
1957 } else if input.peek(Token![loop]) {
1958 input.parse().map(Expr::Loop)
1959 } else if input.peek(Token![match]) {
1960 input.parse().map(Expr::Match)
1961 } else if input.peek(Token![yield]) {
1962 input.parse().map(Expr::Yield)
1963 } else if input.peek(Token![unsafe]) {
1964 input.parse().map(Expr::Unsafe)
1965 } else if input.peek(Token![const]) {
1966 input.parse().map(Expr::Const)
1967 } else if input.peek(token::Brace) {
1968 input.parse().map(Expr::Block)
1969 } else if input.peek(Token![..]) {
1970 expr_range(input, allow_struct).map(Expr::Range)
1971 } else if input.peek(Token![_]) {
1972 input.parse().map(Expr::Infer)
1973 } else if input.peek(Lifetime) {
1974 atom_labeled(input)
1975 } else {
1976 Err(input.error("expected an expression"))
1977 }
1978 }
1979
1980 #[cfg(feature = "full")]
1981 fn atom_labeled(input: ParseStream) -> Result<Expr> {
1982 let the_label: Label = input.parse()?;
1983 let mut expr = if input.peek(Token![while]) {
1984 Expr::While(input.parse()?)
1985 } else if input.peek(Token![for]) {
1986 Expr::ForLoop(input.parse()?)
1987 } else if input.peek(Token![loop]) {
1988 Expr::Loop(input.parse()?)
1989 } else if input.peek(token::Brace) {
1990 Expr::Block(input.parse()?)
1991 } else {
1992 return Err(input.error("expected loop or block expression"));
1993 };
1994 match &mut expr {
1995 Expr::While(ExprWhile { label, .. })
1996 | Expr::ForLoop(ExprForLoop { label, .. })
1997 | Expr::Loop(ExprLoop { label, .. })
1998 | Expr::Block(ExprBlock { label, .. }) => *label = Some(the_label),
1999 _ => unreachable!(),
2000 }
2001 Ok(expr)
2002 }
2003
2004 #[cfg(not(feature = "full"))]
2005 fn atom_expr(input: ParseStream) -> Result<Expr> {
2006 if input.peek(token::Group) && {
2007 let group = crate::group::parse_group(&input.fork())?;
2008 !(group.content.peek(Lifetime) && group.content.peek2(End))
2009 } {
2010 expr_group(input)
2011 } else if input.peek(Lit) {
2012 input.parse().map(Expr::Lit)
2013 } else if input.peek(token::Paren) {
2014 paren_or_tuple(input)
2015 } else if input.peek(Ident)
2016 || input.peek(Token![::])
2017 || input.peek(Token![<])
2018 || input.peek(Token![self])
2019 || input.peek(Token![Self])
2020 || input.peek(Token![super])
2021 || input.peek(Token![crate])
2022 {
2023 path_or_macro_or_struct(input)
2024 } else if input.is_empty() {
2025 Err(input.error("expected an expression"))
2026 } else {
2027 if input.peek(token::Brace) {
2028 let scan = input.fork();
2029 let content;
2030 braced!(content in scan);
2031 if content.parse::<Expr>().is_ok() && content.is_empty() {
2032 let expr_block = verbatim::between(input.cursor(), scan.cursor());
2033 input.advance_to(&scan);
2034 return Ok(Expr::Verbatim(expr_block));
2035 }
2036 }
2037 Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
2038 }
2039 }
2040
2041 #[cfg(feature = "full")]
2042 fn expr_builtin(input: ParseStream) -> Result<Expr> {
2043 let begin = input.cursor();
2044
2045 token::parsing::keyword(input, "builtin")?;
2046 input.parse::<Token![#]>()?;
2047 input.parse::<Ident>()?;
2048
2049 let args;
2050 parenthesized!(args in input);
2051 args.parse::<TokenStream>()?;
2052
2053 Ok(Expr::Verbatim(verbatim::between(begin, input.cursor())))
2054 }
2055
2056 fn path_or_macro_or_struct(
2057 input: ParseStream,
2058 #[cfg(feature = "full")] allow_struct: AllowStruct,
2059 ) -> Result<Expr> {
2060 let expr_style = true;
2061 let (qself, path) = path::parsing::qpath(input, expr_style)?;
2062 rest_of_path_or_macro_or_struct(
2063 qself,
2064 path,
2065 input,
2066 #[cfg(feature = "full")]
2067 allow_struct,
2068 )
2069 }
2070
2071 fn rest_of_path_or_macro_or_struct(
2072 qself: Option<QSelf>,
2073 path: Path,
2074 input: ParseStream,
2075 #[cfg(feature = "full")] allow_struct: AllowStruct,
2076 ) -> Result<Expr> {
2077 if qself.is_none()
2078 && input.peek(Token![!])
2079 && !input.peek(Token![!=])
2080 && path.is_mod_style()
2081 {
2082 let bang_token: Token![!] = input.parse()?;
2083 let (delimiter, tokens) = mac::parse_delimiter(input)?;
2084 return Ok(Expr::Macro(ExprMacro {
2085 attrs: Vec::new(),
2086 mac: Macro {
2087 path,
2088 bang_token,
2089 delimiter,
2090 tokens,
2091 },
2092 }));
2093 }
2094
2095 #[cfg(not(feature = "full"))]
2096 let allow_struct = (true,);
2097 if allow_struct.0 && input.peek(token::Brace) {
2098 return expr_struct_helper(input, qself, path).map(Expr::Struct);
2099 }
2100
2101 Ok(Expr::Path(ExprPath {
2102 attrs: Vec::new(),
2103 qself,
2104 path,
2105 }))
2106 }
2107
2108 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2109 impl Parse for ExprMacro {
2110 fn parse(input: ParseStream) -> Result<Self> {
2111 Ok(ExprMacro {
2112 attrs: Vec::new(),
2113 mac: input.parse()?,
2114 })
2115 }
2116 }
2117
2118 fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
2119 let content;
2120 let paren_token = parenthesized!(content in input);
2121 if content.is_empty() {
2122 return Ok(Expr::Tuple(ExprTuple {
2123 attrs: Vec::new(),
2124 paren_token,
2125 elems: Punctuated::new(),
2126 }));
2127 }
2128
2129 let first: Expr = content.parse()?;
2130 if content.is_empty() {
2131 return Ok(Expr::Paren(ExprParen {
2132 attrs: Vec::new(),
2133 paren_token,
2134 expr: Box::new(first),
2135 }));
2136 }
2137
2138 let mut elems = Punctuated::new();
2139 elems.push_value(first);
2140 while !content.is_empty() {
2141 let punct = content.parse()?;
2142 elems.push_punct(punct);
2143 if content.is_empty() {
2144 break;
2145 }
2146 let value = content.parse()?;
2147 elems.push_value(value);
2148 }
2149 Ok(Expr::Tuple(ExprTuple {
2150 attrs: Vec::new(),
2151 paren_token,
2152 elems,
2153 }))
2154 }
2155
2156 #[cfg(feature = "full")]
2157 fn array_or_repeat(input: ParseStream) -> Result<Expr> {
2158 let content;
2159 let bracket_token = bracketed!(content in input);
2160 if content.is_empty() {
2161 return Ok(Expr::Array(ExprArray {
2162 attrs: Vec::new(),
2163 bracket_token,
2164 elems: Punctuated::new(),
2165 }));
2166 }
2167
2168 let first: Expr = content.parse()?;
2169 if content.is_empty() || content.peek(Token![,]) {
2170 let mut elems = Punctuated::new();
2171 elems.push_value(first);
2172 while !content.is_empty() {
2173 let punct = content.parse()?;
2174 elems.push_punct(punct);
2175 if content.is_empty() {
2176 break;
2177 }
2178 let value = content.parse()?;
2179 elems.push_value(value);
2180 }
2181 Ok(Expr::Array(ExprArray {
2182 attrs: Vec::new(),
2183 bracket_token,
2184 elems,
2185 }))
2186 } else if content.peek(Token![;]) {
2187 let semi_token: Token![;] = content.parse()?;
2188 let len: Expr = content.parse()?;
2189 Ok(Expr::Repeat(ExprRepeat {
2190 attrs: Vec::new(),
2191 bracket_token,
2192 expr: Box::new(first),
2193 semi_token,
2194 len: Box::new(len),
2195 }))
2196 } else {
2197 Err(content.error("expected `,` or `;`"))
2198 }
2199 }
2200
2201 #[cfg(feature = "full")]
2202 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2203 impl Parse for ExprArray {
2204 fn parse(input: ParseStream) -> Result<Self> {
2205 let content;
2206 let bracket_token = bracketed!(content in input);
2207 let mut elems = Punctuated::new();
2208
2209 while !content.is_empty() {
2210 let first: Expr = content.parse()?;
2211 elems.push_value(first);
2212 if content.is_empty() {
2213 break;
2214 }
2215 let punct = content.parse()?;
2216 elems.push_punct(punct);
2217 }
2218
2219 Ok(ExprArray {
2220 attrs: Vec::new(),
2221 bracket_token,
2222 elems,
2223 })
2224 }
2225 }
2226
2227 #[cfg(feature = "full")]
2228 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2229 impl Parse for ExprRepeat {
2230 fn parse(input: ParseStream) -> Result<Self> {
2231 let content;
2232 Ok(ExprRepeat {
2233 bracket_token: bracketed!(content in input),
2234 attrs: Vec::new(),
2235 expr: content.parse()?,
2236 semi_token: content.parse()?,
2237 len: content.parse()?,
2238 })
2239 }
2240 }
2241
2242 #[cfg(feature = "full")]
2243 fn continue_parsing_early(mut expr: &Expr) -> bool {
2244 while let Expr::Group(group) = expr {
2245 expr = &group.expr;
2246 }
2247 match expr {
2248 Expr::If(_)
2249 | Expr::While(_)
2250 | Expr::ForLoop(_)
2251 | Expr::Loop(_)
2252 | Expr::Match(_)
2253 | Expr::TryBlock(_)
2254 | Expr::Unsafe(_)
2255 | Expr::Const(_)
2256 | Expr::Block(_) => false,
2257 _ => true,
2258 }
2259 }
2260
2261 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2262 impl Parse for ExprLit {
2263 fn parse(input: ParseStream) -> Result<Self> {
2264 Ok(ExprLit {
2265 attrs: Vec::new(),
2266 lit: input.parse()?,
2267 })
2268 }
2269 }
2270
2271 fn expr_group(
2272 input: ParseStream,
2273 #[cfg(feature = "full")] allow_struct: AllowStruct,
2274 ) -> Result<Expr> {
2275 let group = crate::group::parse_group(input)?;
2276 let mut inner: Expr = group.content.parse()?;
2277
2278 match inner {
2279 Expr::Path(mut expr) if expr.attrs.is_empty() => {
2280 let grouped_len = expr.path.segments.len();
2281 Path::parse_rest(input, &mut expr.path, true)?;
2282 match rest_of_path_or_macro_or_struct(
2283 expr.qself,
2284 expr.path,
2285 input,
2286 #[cfg(feature = "full")]
2287 allow_struct,
2288 )? {
2289 Expr::Path(expr) if expr.path.segments.len() == grouped_len => {
2290 inner = Expr::Path(expr);
2291 }
2292 extended => return Ok(extended),
2293 }
2294 }
2295 _ => {}
2296 }
2297
2298 Ok(Expr::Group(ExprGroup {
2299 attrs: Vec::new(),
2300 group_token: group.token,
2301 expr: Box::new(inner),
2302 }))
2303 }
2304
2305 #[cfg(feature = "full")]
2306 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2307 impl Parse for ExprParen {
2308 fn parse(input: ParseStream) -> Result<Self> {
2309 let content;
2310 Ok(ExprParen {
2311 attrs: Vec::new(),
2312 paren_token: parenthesized!(content in input),
2313 expr: content.parse()?,
2314 })
2315 }
2316 }
2317
2318 #[cfg(feature = "full")]
2319 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2320 impl Parse for ExprLet {
2321 fn parse(input: ParseStream) -> Result<Self> {
2322 let allow_struct = AllowStruct(true);
2323 expr_let(input, allow_struct)
2324 }
2325 }
2326
2327 #[cfg(feature = "full")]
2328 fn expr_let(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprLet> {
2329 Ok(ExprLet {
2330 attrs: Vec::new(),
2331 let_token: input.parse()?,
2332 pat: Box::new(Pat::parse_multi_with_leading_vert(input)?),
2333 eq_token: input.parse()?,
2334 expr: Box::new({
2335 let lhs = unary_expr(input, allow_struct)?;
2336 parse_expr(input, lhs, allow_struct, Precedence::Compare)?
2337 }),
2338 })
2339 }
2340
2341 #[cfg(feature = "full")]
2342 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2343 impl Parse for ExprIf {
2344 fn parse(input: ParseStream) -> Result<Self> {
2345 let attrs = input.call(Attribute::parse_outer)?;
2346
2347 let mut clauses = Vec::new();
2348 let mut expr;
2349 loop {
2350 let if_token: Token![if] = input.parse()?;
2351 let cond = input.call(Expr::parse_without_eager_brace)?;
2352 let then_branch: Block = input.parse()?;
2353
2354 expr = ExprIf {
2355 attrs: Vec::new(),
2356 if_token,
2357 cond: Box::new(cond),
2358 then_branch,
2359 else_branch: None,
2360 };
2361
2362 if !input.peek(Token![else]) {
2363 break;
2364 }
2365
2366 let else_token: Token![else] = input.parse()?;
2367 let lookahead = input.lookahead1();
2368 if lookahead.peek(Token![if]) {
2369 expr.else_branch = Some((else_token, Box::new(Expr::PLACEHOLDER)));
2370 clauses.push(expr);
2371 } else if lookahead.peek(token::Brace) {
2372 expr.else_branch = Some((
2373 else_token,
2374 Box::new(Expr::Block(ExprBlock {
2375 attrs: Vec::new(),
2376 label: None,
2377 block: input.parse()?,
2378 })),
2379 ));
2380 break;
2381 } else {
2382 return Err(lookahead.error());
2383 }
2384 }
2385
2386 while let Some(mut prev) = clauses.pop() {
2387 *prev.else_branch.as_mut().unwrap().1 = Expr::If(expr);
2388 expr = prev;
2389 }
2390 expr.attrs = attrs;
2391 Ok(expr)
2392 }
2393 }
2394
2395 #[cfg(feature = "full")]
2396 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2397 impl Parse for ExprInfer {
2398 fn parse(input: ParseStream) -> Result<Self> {
2399 Ok(ExprInfer {
2400 attrs: input.call(Attribute::parse_outer)?,
2401 underscore_token: input.parse()?,
2402 })
2403 }
2404 }
2405
2406 #[cfg(feature = "full")]
2407 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2408 impl Parse for ExprForLoop {
2409 fn parse(input: ParseStream) -> Result<Self> {
2410 let mut attrs = input.call(Attribute::parse_outer)?;
2411 let label: Option<Label> = input.parse()?;
2412 let for_token: Token![for] = input.parse()?;
2413
2414 let pat = Pat::parse_multi_with_leading_vert(input)?;
2415
2416 let in_token: Token![in] = input.parse()?;
2417 let expr: Expr = input.call(Expr::parse_without_eager_brace)?;
2418
2419 let content;
2420 let brace_token = braced!(content in input);
2421 attr::parsing::parse_inner(&content, &mut attrs)?;
2422 let stmts = content.call(Block::parse_within)?;
2423
2424 Ok(ExprForLoop {
2425 attrs,
2426 label,
2427 for_token,
2428 pat: Box::new(pat),
2429 in_token,
2430 expr: Box::new(expr),
2431 body: Block { brace_token, stmts },
2432 })
2433 }
2434 }
2435
2436 #[cfg(feature = "full")]
2437 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2438 impl Parse for ExprLoop {
2439 fn parse(input: ParseStream) -> Result<Self> {
2440 let mut attrs = input.call(Attribute::parse_outer)?;
2441 let label: Option<Label> = input.parse()?;
2442 let loop_token: Token![loop] = input.parse()?;
2443
2444 let content;
2445 let brace_token = braced!(content in input);
2446 attr::parsing::parse_inner(&content, &mut attrs)?;
2447 let stmts = content.call(Block::parse_within)?;
2448
2449 Ok(ExprLoop {
2450 attrs,
2451 label,
2452 loop_token,
2453 body: Block { brace_token, stmts },
2454 })
2455 }
2456 }
2457
2458 #[cfg(feature = "full")]
2459 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2460 impl Parse for ExprMatch {
2461 fn parse(input: ParseStream) -> Result<Self> {
2462 let mut attrs = input.call(Attribute::parse_outer)?;
2463 let match_token: Token![match] = input.parse()?;
2464 let expr = Expr::parse_without_eager_brace(input)?;
2465
2466 let content;
2467 let brace_token = braced!(content in input);
2468 attr::parsing::parse_inner(&content, &mut attrs)?;
2469
2470 let arms = Arm::parse_multiple(&content)?;
2471
2472 Ok(ExprMatch {
2473 attrs,
2474 match_token,
2475 expr: Box::new(expr),
2476 brace_token,
2477 arms,
2478 })
2479 }
2480 }
2481
2482 macro_rules! impl_by_parsing_expr {
2483 (
2484 $(
2485 $expr_type:ty, $variant:ident, $msg:expr,
2486 )*
2487 ) => {
2488 $(
2489 #[cfg(all(feature = "full", feature = "printing"))]
2490 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2491 impl Parse for $expr_type {
2492 fn parse(input: ParseStream) -> Result<Self> {
2493 let mut expr: Expr = input.parse()?;
2494 loop {
2495 match expr {
2496 Expr::$variant(inner) => return Ok(inner),
2497 Expr::Group(next) => expr = *next.expr,
2498 _ => return Err(Error::new_spanned(expr, $msg)),
2499 }
2500 }
2501 }
2502 }
2503 )*
2504 };
2505 }
2506
2507 impl_by_parsing_expr! {
2508 ExprAssign, Assign, "expected assignment expression",
2509 ExprAwait, Await, "expected await expression",
2510 ExprBinary, Binary, "expected binary operation",
2511 ExprCall, Call, "expected function call expression",
2512 ExprCast, Cast, "expected cast expression",
2513 ExprField, Field, "expected struct field access",
2514 ExprIndex, Index, "expected indexing expression",
2515 ExprMethodCall, MethodCall, "expected method call expression",
2516 ExprRange, Range, "expected range expression",
2517 ExprTry, Try, "expected try expression",
2518 ExprTuple, Tuple, "expected tuple expression",
2519 }
2520
2521 #[cfg(feature = "full")]
2522 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2523 impl Parse for ExprUnary {
2524 fn parse(input: ParseStream) -> Result<Self> {
2525 let attrs = Vec::new();
2526 let allow_struct = AllowStruct(true);
2527 expr_unary(input, attrs, allow_struct)
2528 }
2529 }
2530
2531 #[cfg(feature = "full")]
2532 fn expr_unary(
2533 input: ParseStream,
2534 attrs: Vec<Attribute>,
2535 allow_struct: AllowStruct,
2536 ) -> Result<ExprUnary> {
2537 Ok(ExprUnary {
2538 attrs,
2539 op: input.parse()?,
2540 expr: Box::new(unary_expr(input, allow_struct)?),
2541 })
2542 }
2543
2544 #[cfg(feature = "full")]
2545 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2546 impl Parse for ExprClosure {
2547 fn parse(input: ParseStream) -> Result<Self> {
2548 let allow_struct = AllowStruct(true);
2549 expr_closure(input, allow_struct)
2550 }
2551 }
2552
2553 #[cfg(feature = "full")]
2554 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2555 impl Parse for ExprRawAddr {
2556 fn parse(input: ParseStream) -> Result<Self> {
2557 let allow_struct = AllowStruct(true);
2558 Ok(ExprRawAddr {
2559 attrs: Vec::new(),
2560 and_token: input.parse()?,
2561 raw: input.parse()?,
2562 mutability: input.parse()?,
2563 expr: Box::new(unary_expr(input, allow_struct)?),
2564 })
2565 }
2566 }
2567
2568 #[cfg(feature = "full")]
2569 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2570 impl Parse for ExprReference {
2571 fn parse(input: ParseStream) -> Result<Self> {
2572 let allow_struct = AllowStruct(true);
2573 Ok(ExprReference {
2574 attrs: Vec::new(),
2575 and_token: input.parse()?,
2576 mutability: input.parse()?,
2577 expr: Box::new(unary_expr(input, allow_struct)?),
2578 })
2579 }
2580 }
2581
2582 #[cfg(feature = "full")]
2583 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2584 impl Parse for ExprBreak {
2585 fn parse(input: ParseStream) -> Result<Self> {
2586 let allow_struct = AllowStruct(true);
2587 expr_break(input, allow_struct)
2588 }
2589 }
2590
2591 #[cfg(feature = "full")]
2592 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2593 impl Parse for ExprReturn {
2594 fn parse(input: ParseStream) -> Result<Self> {
2595 Ok(ExprReturn {
2596 attrs: Vec::new(),
2597 return_token: input.parse()?,
2598 expr: {
2599 if Expr::peek(input) {
2600 Some(input.parse()?)
2601 } else {
2602 None
2603 }
2604 },
2605 })
2606 }
2607 }
2608
2609 #[cfg(feature = "full")]
2610 fn expr_become(input: ParseStream) -> Result<Expr> {
2611 let begin = input.cursor();
2612 input.parse::<Token![become]>()?;
2613 input.parse::<Expr>()?;
2614 Ok(Expr::Verbatim(verbatim::between(begin, input.cursor())))
2615 }
2616
2617 #[cfg(feature = "full")]
2618 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2619 impl Parse for ExprTryBlock {
2620 fn parse(input: ParseStream) -> Result<Self> {
2621 Ok(ExprTryBlock {
2622 attrs: Vec::new(),
2623 try_token: input.parse()?,
2624 modifiers: BlockModifiers {},
2625 block: input.parse()?,
2626 })
2627 }
2628 }
2629
2630 #[cfg(feature = "full")]
2631 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2632 impl Parse for ExprYield {
2633 fn parse(input: ParseStream) -> Result<Self> {
2634 Ok(ExprYield {
2635 attrs: Vec::new(),
2636 yield_token: input.parse()?,
2637 expr: {
2638 if Expr::peek(input) {
2639 Some(input.parse()?)
2640 } else {
2641 None
2642 }
2643 },
2644 })
2645 }
2646 }
2647
2648 #[cfg(feature = "full")]
2649 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
2650 let lifetimes: Option<BoundLifetimes> = input.parse()?;
2651 let constness: Option<Token![const]> = input.parse()?;
2652 let asyncness: Option<Token![async]> = input.parse()?;
2653 let capture: Option<Token![move]> = input.parse()?;
2654 let inputs_begin: Token![|] = input.parse()?;
2655
2656 let mut inputs = Punctuated::new();
2657 loop {
2658 if input.peek(Token![|]) {
2659 break;
2660 }
2661 let value = closure_arg(input)?;
2662 inputs.push_value(value);
2663 if input.peek(Token![|]) {
2664 break;
2665 }
2666 let punct: Token![,] = input.parse()?;
2667 inputs.push_punct(punct);
2668 }
2669
2670 let inputs_end: Token![|] = input.parse()?;
2671
2672 let (output, body) = if input.peek(Token![->]) {
2673 let arrow_token: Token![->] = input.parse()?;
2674 let ty: Type = input.parse()?;
2675 let body: Block = input.parse()?;
2676 let output = ReturnType::Type(arrow_token, Box::new(ty));
2677 let block = Expr::Block(ExprBlock {
2678 attrs: Vec::new(),
2679 label: None,
2680 block: body,
2681 });
2682 (output, block)
2683 } else {
2684 let body = ambiguous_expr(input, allow_struct)?;
2685 (ReturnType::Default, body)
2686 };
2687
2688 Ok(ExprClosure {
2689 attrs: Vec::new(),
2690 lifetimes,
2691 modifiers: ClosureModifiers {},
2692 constness,
2693 asyncness,
2694 capture,
2695 inputs_begin,
2696 inputs,
2697 inputs_end,
2698 output,
2699 body: Box::new(body),
2700 })
2701 }
2702
2703 #[cfg(feature = "full")]
2704 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2705 impl Parse for ExprAsync {
2706 fn parse(input: ParseStream) -> Result<Self> {
2707 Ok(ExprAsync {
2708 attrs: Vec::new(),
2709 async_token: input.parse()?,
2710 capture: input.parse()?,
2711 modifiers: BlockModifiers {},
2712 block: input.parse()?,
2713 })
2714 }
2715 }
2716
2717 #[cfg(feature = "full")]
2718 fn closure_arg(input: ParseStream) -> Result<Pat> {
2719 let attrs = input.call(Attribute::parse_outer)?;
2720 let mut pat = Pat::parse_single(input)?;
2721
2722 if input.peek(Token![:]) {
2723 Ok(Pat::Type(PatType {
2724 attrs,
2725 pat: Box::new(pat),
2726 colon_token: input.parse()?,
2727 ty: input.parse()?,
2728 }))
2729 } else {
2730 match &mut pat {
2731 Pat::Const(pat) => pat.attrs = attrs,
2732 Pat::Guard(_) => unreachable!(),
2733 Pat::Ident(pat) => pat.attrs = attrs,
2734 Pat::Lit(pat) => pat.attrs = attrs,
2735 Pat::Macro(pat) => pat.attrs = attrs,
2736 Pat::Or(pat) => pat.attrs = attrs,
2737 Pat::Paren(pat) => pat.attrs = attrs,
2738 Pat::Path(pat) => pat.attrs = attrs,
2739 Pat::Range(pat) => pat.attrs = attrs,
2740 Pat::Reference(pat) => pat.attrs = attrs,
2741 Pat::Rest(pat) => pat.attrs = attrs,
2742 Pat::Slice(pat) => pat.attrs = attrs,
2743 Pat::Struct(pat) => pat.attrs = attrs,
2744 Pat::Tuple(pat) => pat.attrs = attrs,
2745 Pat::TupleStruct(pat) => pat.attrs = attrs,
2746 Pat::Type(_) => unreachable!(),
2747 Pat::Verbatim(_) => {}
2748 Pat::Wild(pat) => pat.attrs = attrs,
2749 }
2750 Ok(pat)
2751 }
2752 }
2753
2754 #[cfg(feature = "full")]
2755 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2756 impl Parse for ExprWhile {
2757 fn parse(input: ParseStream) -> Result<Self> {
2758 let mut attrs = input.call(Attribute::parse_outer)?;
2759 let label: Option<Label> = input.parse()?;
2760 let while_token: Token![while] = input.parse()?;
2761 let cond = Expr::parse_without_eager_brace(input)?;
2762
2763 let content;
2764 let brace_token = braced!(content in input);
2765 attr::parsing::parse_inner(&content, &mut attrs)?;
2766 let stmts = content.call(Block::parse_within)?;
2767
2768 Ok(ExprWhile {
2769 attrs,
2770 label,
2771 while_token,
2772 cond: Box::new(cond),
2773 body: Block { brace_token, stmts },
2774 })
2775 }
2776 }
2777
2778 #[cfg(feature = "full")]
2779 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2780 impl Parse for ExprConst {
2781 fn parse(input: ParseStream) -> Result<Self> {
2782 let const_token: Token![const] = input.parse()?;
2783
2784 let content;
2785 let brace_token = braced!(content in input);
2786 let inner_attrs = content.call(Attribute::parse_inner)?;
2787 let stmts = content.call(Block::parse_within)?;
2788
2789 Ok(ExprConst {
2790 attrs: inner_attrs,
2791 const_token,
2792 modifiers: BlockModifiers {},
2793 block: Block { brace_token, stmts },
2794 })
2795 }
2796 }
2797
2798 #[cfg(feature = "full")]
2799 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2800 impl Parse for Label {
2801 fn parse(input: ParseStream) -> Result<Self> {
2802 Ok(Label {
2803 name: Lifetime::parse_any(input)?,
2804 colon_token: input.parse()?,
2805 })
2806 }
2807 }
2808
2809 #[cfg(feature = "full")]
2810 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2811 impl Parse for Option<Label> {
2812 fn parse(input: ParseStream) -> Result<Self> {
2813 if input.peek(Lifetime) {
2814 input.parse().map(Some)
2815 } else {
2816 Ok(None)
2817 }
2818 }
2819 }
2820
2821 #[cfg(feature = "full")]
2822 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2823 impl Parse for ExprContinue {
2824 fn parse(input: ParseStream) -> Result<Self> {
2825 Ok(ExprContinue {
2826 attrs: Vec::new(),
2827 continue_token: input.parse()?,
2828 label: Lifetime::parse_optional_any(input),
2829 })
2830 }
2831 }
2832
2833 #[cfg(feature = "full")]
2834 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2835 let break_token: Token![break] = input.parse()?;
2836
2837 let ahead = input.fork();
2838 let label_begin = ahead.cursor();
2839 let label = Lifetime::parse_optional_any(&ahead);
2840 if label.is_some() && ahead.peek(Token![:]) && !ahead.peek(Token![::]) {
2841 let _: Expr = input.parse()?;
2844 return Err(Error::new_range(
2845 label_begin..input.cursor(),
2846 "parentheses required",
2847 ));
2848 }
2849
2850 input.advance_to(&ahead);
2851 let expr = if Expr::peek(input) && (allow_struct.0 || !input.peek(token::Brace)) {
2852 Some(input.parse()?)
2853 } else {
2854 None
2855 };
2856
2857 Ok(ExprBreak {
2858 attrs: Vec::new(),
2859 break_token,
2860 label,
2861 expr,
2862 })
2863 }
2864
2865 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2866 impl Parse for FieldValue {
2867 fn parse(input: ParseStream) -> Result<Self> {
2868 let attrs = input.call(Attribute::parse_outer)?;
2869 let member: Member = input.parse()?;
2870 let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
2871 let colon_token: Token![:] = input.parse()?;
2872 let value: Expr = input.parse()?;
2873 (Some(colon_token), value)
2874 } else if let Member::Named(ident) = &member {
2875 let value = Expr::Path(ExprPath {
2876 attrs: Vec::new(),
2877 qself: None,
2878 path: Path::from(ident.clone()),
2879 });
2880 (None, value)
2881 } else {
2882 unreachable!()
2883 };
2884
2885 Ok(FieldValue {
2886 attrs,
2887 member,
2888 colon_token,
2889 expr: value,
2890 })
2891 }
2892 }
2893
2894 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2895 impl Parse for ExprStruct {
2896 fn parse(input: ParseStream) -> Result<Self> {
2897 let expr_style = true;
2898 let (qself, path) = path::parsing::qpath(input, expr_style)?;
2899 expr_struct_helper(input, qself, path)
2900 }
2901 }
2902
2903 fn expr_struct_helper(
2904 input: ParseStream,
2905 qself: Option<QSelf>,
2906 path: Path,
2907 ) -> Result<ExprStruct> {
2908 let content;
2909 let brace_token = braced!(content in input);
2910
2911 let mut fields = Punctuated::new();
2912 while !content.is_empty() {
2913 if content.peek(Token![..]) {
2914 return Ok(ExprStruct {
2915 attrs: Vec::new(),
2916 qself,
2917 path,
2918 brace_token,
2919 fields,
2920 dot2_token: Some(content.parse()?),
2921 rest: if content.is_empty() {
2922 None
2923 } else {
2924 Some(Box::new(content.parse()?))
2925 },
2926 });
2927 }
2928
2929 fields.push(content.parse()?);
2930 if content.is_empty() {
2931 break;
2932 }
2933 let punct: Token![,] = content.parse()?;
2934 fields.push_punct(punct);
2935 }
2936
2937 Ok(ExprStruct {
2938 attrs: Vec::new(),
2939 qself,
2940 path,
2941 brace_token,
2942 fields,
2943 dot2_token: None,
2944 rest: None,
2945 })
2946 }
2947
2948 #[cfg(feature = "full")]
2949 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2950 impl Parse for ExprUnsafe {
2951 fn parse(input: ParseStream) -> Result<Self> {
2952 let unsafe_token: Token![unsafe] = input.parse()?;
2953
2954 let content;
2955 let brace_token = braced!(content in input);
2956 let inner_attrs = content.call(Attribute::parse_inner)?;
2957 let stmts = content.call(Block::parse_within)?;
2958
2959 Ok(ExprUnsafe {
2960 attrs: inner_attrs,
2961 unsafe_token,
2962 block: Block { brace_token, stmts },
2963 })
2964 }
2965 }
2966
2967 #[cfg(feature = "full")]
2968 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2969 impl Parse for ExprBlock {
2970 fn parse(input: ParseStream) -> Result<Self> {
2971 let mut attrs = input.call(Attribute::parse_outer)?;
2972 let label: Option<Label> = input.parse()?;
2973
2974 let content;
2975 let brace_token = braced!(content in input);
2976 attr::parsing::parse_inner(&content, &mut attrs)?;
2977 let stmts = content.call(Block::parse_within)?;
2978
2979 Ok(ExprBlock {
2980 attrs,
2981 label,
2982 block: Block { brace_token, stmts },
2983 })
2984 }
2985 }
2986
2987 #[cfg(feature = "full")]
2988 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2989 let limits: RangeLimits = input.parse()?;
2990 let end = parse_range_end(input, &limits, allow_struct)?;
2991 Ok(ExprRange {
2992 attrs: Vec::new(),
2993 start: None,
2994 limits,
2995 end,
2996 })
2997 }
2998
2999 #[cfg(feature = "full")]
3000 fn parse_range_end(
3001 input: ParseStream,
3002 limits: &RangeLimits,
3003 allow_struct: AllowStruct,
3004 ) -> Result<Option<Box<Expr>>> {
3005 if matches!(limits, RangeLimits::HalfOpen(_))
3006 && (input.is_empty()
3007 || input.peek(Token![,])
3008 || input.peek(Token![;])
3009 || input.peek(Token![.]) && !input.peek(Token![..])
3010 || input.peek(Token![?])
3011 || input.peek(Token![=>])
3012 || !allow_struct.0 && input.peek(token::Brace)
3013 || input.peek(Token![=])
3014 || input.peek(Token![+])
3015 || input.peek(Token![/])
3016 || input.peek(Token![%])
3017 || input.peek(Token![^])
3018 || input.peek(Token![>])
3019 || input.peek(Token![<=])
3020 || input.peek(Token![!=])
3021 || input.peek(Token![-=])
3022 || input.peek(Token![*=])
3023 || input.peek(Token![&=])
3024 || input.peek(Token![|=])
3025 || input.peek(Token![<<=])
3026 || input.peek(Token![as]))
3027 {
3028 Ok(None)
3029 } else {
3030 let end = parse_binop_rhs(input, allow_struct, Precedence::Range)?;
3031 Ok(Some(end))
3032 }
3033 }
3034
3035 #[cfg(feature = "full")]
3036 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3037 impl Parse for RangeLimits {
3038 fn parse(input: ParseStream) -> Result<Self> {
3039 let lookahead = input.lookahead1();
3040 let dot_dot = lookahead.peek(Token![..]);
3041 let dot_dot_eq = dot_dot && lookahead.peek(Token![..=]);
3042 let dot_dot_dot = dot_dot && input.peek(Token![...]);
3043 if dot_dot_eq {
3044 input.parse().map(RangeLimits::Closed)
3045 } else if dot_dot && !dot_dot_dot {
3046 input.parse().map(RangeLimits::HalfOpen)
3047 } else {
3048 Err(lookahead.error())
3049 }
3050 }
3051 }
3052
3053 #[cfg(feature = "full")]
3054 impl RangeLimits {
3055 pub(crate) fn parse_obsolete(input: ParseStream) -> Result<Self> {
3056 let lookahead = input.lookahead1();
3057 let dot_dot = lookahead.peek(Token![..]);
3058 let dot_dot_eq = dot_dot && lookahead.peek(Token![..=]);
3059 let dot_dot_dot = dot_dot && input.peek(Token![...]);
3060 if dot_dot_eq {
3061 input.parse().map(RangeLimits::Closed)
3062 } else if dot_dot_dot {
3063 let dot3: Token![...] = input.parse()?;
3064 Ok(RangeLimits::Closed(Token))
3065 } else if dot_dot {
3066 input.parse().map(RangeLimits::HalfOpen)
3067 } else {
3068 Err(lookahead.error())
3069 }
3070 }
3071 }
3072
3073 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3074 impl Parse for ExprPath {
3075 fn parse(input: ParseStream) -> Result<Self> {
3076 #[cfg(not(feature = "full"))]
3077 let attrs = Vec::new();
3078 #[cfg(feature = "full")]
3079 let attrs = input.call(Attribute::parse_outer)?;
3080
3081 let expr_style = true;
3082 let (qself, path) = path::parsing::qpath(input, expr_style)?;
3083
3084 Ok(ExprPath { attrs, qself, path })
3085 }
3086 }
3087
3088 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3089 impl Parse for Member {
3090 fn parse(input: ParseStream) -> Result<Self> {
3091 if input.peek(Ident) {
3092 input.parse().map(Member::Named)
3093 } else if input.peek(LitInt) {
3094 input.parse().map(Member::Unnamed)
3095 } else {
3096 Err(input.error("expected identifier or integer"))
3097 }
3098 }
3099 }
3100
3101 #[cfg(feature = "full")]
3102 impl Arm {
3103 pub(crate) fn parse_multiple(input: ParseStream) -> Result<Vec<Self>> {
3104 let mut arms = Vec::new();
3105 while !input.is_empty() {
3106 arms.push(input.call(Arm::parse)?);
3107 }
3108 Ok(arms)
3109 }
3110 }
3111
3112 #[cfg(feature = "full")]
3113 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3114 impl Parse for Arm {
3115 fn parse(input: ParseStream) -> Result<Arm> {
3116 let requires_comma;
3117 Ok(Arm {
3118 attrs: input.call(Attribute::parse_outer)?,
3119 pat: Pat::parse_multi_with_leading_vert_and_guard(input)?,
3120 fat_arrow_token: input.parse()?,
3121 body: {
3122 let body = Expr::parse_with_earlier_boundary_rule(input)?;
3123 requires_comma = classify::requires_comma_to_be_match_arm(&body);
3124 Box::new(body)
3125 },
3126 comma: {
3127 if requires_comma && !input.is_empty() {
3128 Some(input.parse()?)
3129 } else {
3130 input.parse()?
3131 }
3132 },
3133 })
3134 }
3135 }
3136
3137 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3138 impl Parse for Index {
3139 fn parse(input: ParseStream) -> Result<Self> {
3140 let lit: LitInt = input.parse()?;
3141 if lit.suffix().is_empty() {
3142 Ok(Index {
3143 index: lit
3144 .base10_digits()
3145 .parse()
3146 .map_err(|err| Error::new(lit.span(), err))?,
3147 span: lit.span(),
3148 })
3149 } else {
3150 Err(Error::new(lit.span(), "expected unsuffixed integer"))
3151 }
3152 }
3153 }
3154
3155 fn multi_index(e: &mut Expr, dot_token: &mut Token![.], float: LitFloat) -> Result<bool> {
3156 let float_token = float.token();
3157 let float_span = float_token.span();
3158 let mut float_repr = float_token.to_string();
3159 let trailing_dot = float_repr.ends_with('.');
3160 if trailing_dot {
3161 float_repr.truncate(float_repr.len() - 1);
3162 }
3163
3164 let mut offset = 0;
3165 for part in float_repr.split('.') {
3166 let mut index: Index =
3167 crate::parse_str(part).map_err(|err| Error::new(float_span, err))?;
3168 let part_end = offset + part.len();
3169 index.span = float_token.subspan(offset..part_end).unwrap_or(float_span);
3170
3171 let base = mem::replace(e, Expr::PLACEHOLDER);
3172 *e = Expr::Field(ExprField {
3173 attrs: Vec::new(),
3174 base: Box::new(base),
3175 dot_token: Token,
3176 member: Member::Unnamed(index),
3177 });
3178
3179 let dot_span = float_token
3180 .subspan(part_end..part_end + 1)
3181 .unwrap_or(float_span);
3182 *dot_token = Token;
3183 offset = part_end + 1;
3184 }
3185
3186 Ok(!trailing_dot)
3187 }
3188
3189 fn check_cast(input: ParseStream) -> Result<()> {
3190 let kind = if input.peek(Token![.]) && !input.peek(Token![..]) {
3191 if input.peek2(Token![await]) {
3192 "`.await`"
3193 } else if input.peek2(Ident) && (input.peek3(token::Paren) || input.peek3(Token![::])) {
3194 "a method call"
3195 } else {
3196 "a field access"
3197 }
3198 } else if input.peek(Token![?]) {
3199 "`?`"
3200 } else if input.peek(token::Bracket) {
3201 "indexing"
3202 } else if input.peek(token::Paren) {
3203 "a function call"
3204 } else {
3205 return Ok(());
3206 };
3207 let msg = format!("casts cannot be followed by {}", kind);
3208 Err(input.error(msg))
3209 }
3210}
3211
3212#[cfg(feature = "printing")]
3213pub(crate) mod printing {
3214 use crate::attr::Attribute;
3215 #[cfg(feature = "full")]
3216 use crate::attr::FilterAttrs;
3217 #[cfg(feature = "full")]
3218 use crate::classify;
3219 #[cfg(feature = "full")]
3220 use crate::expr::{
3221 Arm, ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure,
3222 ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch,
3223 ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprUnsafe,
3224 ExprWhile, ExprYield, Label, RangeLimits,
3225 };
3226 use crate::expr::{
3227 Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro,
3228 ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprTuple, ExprUnary,
3229 FieldValue, Index, Member,
3230 };
3231 use crate::fixup::FixupContext;
3232 use crate::op::BinOp;
3233 use crate::path;
3234 use crate::path::printing::PathStyle;
3235 use crate::precedence::Precedence;
3236 use crate::token;
3237 #[cfg(feature = "full")]
3238 use crate::ty::ReturnType;
3239 use proc_macro2::{Literal, Span, TokenStream};
3240 use quote::{ToTokens, TokenStreamExt as _};
3241
3242 #[cfg(feature = "full")]
3243 pub(crate) fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3244 tokens.append_all(attrs.outer());
3245 }
3246
3247 #[cfg(feature = "full")]
3248 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3249 tokens.append_all(attrs.inner());
3250 }
3251
3252 #[cfg(not(feature = "full"))]
3253 pub(crate) fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3254
3255 pub(crate) fn print_subexpression(
3256 expr: &Expr,
3257 needs_group: bool,
3258 tokens: &mut TokenStream,
3259 mut fixup: FixupContext,
3260 ) {
3261 if needs_group {
3262 fixup = FixupContext::NONE;
3274 }
3275
3276 let do_print_expr = |tokens: &mut TokenStream| print_expr(expr, tokens, fixup);
3277
3278 if needs_group {
3279 token::Paren::default().surround(tokens, do_print_expr);
3280 } else {
3281 do_print_expr(tokens);
3282 }
3283 }
3284
3285 pub(crate) fn print_expr(expr: &Expr, tokens: &mut TokenStream, mut fixup: FixupContext) {
3286 #[cfg(feature = "full")]
3287 let needs_group = fixup.parenthesize(expr);
3288 #[cfg(not(feature = "full"))]
3289 let needs_group = false;
3290
3291 if needs_group {
3292 fixup = FixupContext::NONE;
3293 }
3294
3295 let do_print_expr = |tokens: &mut TokenStream| match expr {
3296 #[cfg(feature = "full")]
3297 Expr::Array(e) => e.to_tokens(tokens),
3298 #[cfg(feature = "full")]
3299 Expr::Assign(e) => print_expr_assign(e, tokens, fixup),
3300 #[cfg(feature = "full")]
3301 Expr::Async(e) => e.to_tokens(tokens),
3302 #[cfg(feature = "full")]
3303 Expr::Await(e) => print_expr_await(e, tokens, fixup),
3304 Expr::Binary(e) => print_expr_binary(e, tokens, fixup),
3305 #[cfg(feature = "full")]
3306 Expr::Block(e) => e.to_tokens(tokens),
3307 #[cfg(feature = "full")]
3308 Expr::Break(e) => print_expr_break(e, tokens, fixup),
3309 Expr::Call(e) => print_expr_call(e, tokens, fixup),
3310 Expr::Cast(e) => print_expr_cast(e, tokens, fixup),
3311 #[cfg(feature = "full")]
3312 Expr::Closure(e) => print_expr_closure(e, tokens, fixup),
3313 #[cfg(feature = "full")]
3314 Expr::Const(e) => e.to_tokens(tokens),
3315 #[cfg(feature = "full")]
3316 Expr::Continue(e) => e.to_tokens(tokens),
3317 Expr::Field(e) => print_expr_field(e, tokens, fixup),
3318 #[cfg(feature = "full")]
3319 Expr::ForLoop(e) => e.to_tokens(tokens),
3320 Expr::Group(e) => e.to_tokens(tokens),
3321 #[cfg(feature = "full")]
3322 Expr::If(e) => e.to_tokens(tokens),
3323 Expr::Index(e) => print_expr_index(e, tokens, fixup),
3324 #[cfg(feature = "full")]
3325 Expr::Infer(e) => e.to_tokens(tokens),
3326 #[cfg(feature = "full")]
3327 Expr::Let(e) => print_expr_let(e, tokens, fixup),
3328 Expr::Lit(e) => e.to_tokens(tokens),
3329 #[cfg(feature = "full")]
3330 Expr::Loop(e) => e.to_tokens(tokens),
3331 Expr::Macro(e) => e.to_tokens(tokens),
3332 #[cfg(feature = "full")]
3333 Expr::Match(e) => e.to_tokens(tokens),
3334 Expr::MethodCall(e) => print_expr_method_call(e, tokens, fixup),
3335 Expr::Paren(e) => e.to_tokens(tokens),
3336 Expr::Path(e) => e.to_tokens(tokens),
3337 #[cfg(feature = "full")]
3338 Expr::Range(e) => print_expr_range(e, tokens, fixup),
3339 #[cfg(feature = "full")]
3340 Expr::RawAddr(e) => print_expr_raw_addr(e, tokens, fixup),
3341 Expr::Reference(e) => print_expr_reference(e, tokens, fixup),
3342 #[cfg(feature = "full")]
3343 Expr::Repeat(e) => e.to_tokens(tokens),
3344 #[cfg(feature = "full")]
3345 Expr::Return(e) => print_expr_return(e, tokens, fixup),
3346 Expr::Struct(e) => e.to_tokens(tokens),
3347 #[cfg(feature = "full")]
3348 Expr::Try(e) => print_expr_try(e, tokens, fixup),
3349 #[cfg(feature = "full")]
3350 Expr::TryBlock(e) => e.to_tokens(tokens),
3351 Expr::Tuple(e) => e.to_tokens(tokens),
3352 Expr::Unary(e) => print_expr_unary(e, tokens, fixup),
3353 #[cfg(feature = "full")]
3354 Expr::Unsafe(e) => e.to_tokens(tokens),
3355 Expr::Verbatim(e) => e.to_tokens(tokens),
3356 #[cfg(feature = "full")]
3357 Expr::While(e) => e.to_tokens(tokens),
3358 #[cfg(feature = "full")]
3359 Expr::Yield(e) => print_expr_yield(e, tokens, fixup),
3360
3361 #[cfg(not(feature = "full"))]
3362 _ => unreachable!(),
3363 };
3364
3365 if needs_group {
3366 token::Paren::default().surround(tokens, do_print_expr);
3367 } else {
3368 do_print_expr(tokens);
3369 }
3370 }
3371
3372 #[cfg(feature = "full")]
3373 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3374 impl ToTokens for ExprArray {
3375 fn to_tokens(&self, tokens: &mut TokenStream) {
3376 outer_attrs_to_tokens(&self.attrs, tokens);
3377 self.bracket_token.surround(tokens, |tokens| {
3378 self.elems.to_tokens(tokens);
3379 });
3380 }
3381 }
3382
3383 #[cfg(feature = "full")]
3384 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3385 impl ToTokens for ExprAssign {
3386 fn to_tokens(&self, tokens: &mut TokenStream) {
3387 print_expr_assign(self, tokens, FixupContext::NONE);
3388 }
3389 }
3390
3391 #[cfg(feature = "full")]
3392 fn print_expr_assign(e: &ExprAssign, tokens: &mut TokenStream, mut fixup: FixupContext) {
3393 outer_attrs_to_tokens(&e.attrs, tokens);
3394
3395 let needs_group = !e.attrs.is_empty();
3396 if needs_group {
3397 fixup = FixupContext::NONE;
3398 }
3399
3400 let do_print_expr = |tokens: &mut TokenStream| {
3401 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3402 &e.left,
3403 false,
3404 false,
3405 Precedence::Assign,
3406 );
3407 print_subexpression(&e.left, left_prec <= Precedence::Range, tokens, left_fixup);
3408 e.eq_token.to_tokens(tokens);
3409 print_expr(
3410 &e.right,
3411 tokens,
3412 fixup.rightmost_subexpression_fixup(false, false, Precedence::Assign),
3413 );
3414 };
3415
3416 if needs_group {
3417 token::Paren::default().surround(tokens, do_print_expr);
3418 } else {
3419 do_print_expr(tokens);
3420 }
3421 }
3422
3423 #[cfg(feature = "full")]
3424 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3425 impl ToTokens for ExprAsync {
3426 fn to_tokens(&self, tokens: &mut TokenStream) {
3427 outer_attrs_to_tokens(&self.attrs, tokens);
3428 self.async_token.to_tokens(tokens);
3429 self.capture.to_tokens(tokens);
3430 self.block.to_tokens(tokens);
3431 }
3432 }
3433
3434 #[cfg(feature = "full")]
3435 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3436 impl ToTokens for ExprAwait {
3437 fn to_tokens(&self, tokens: &mut TokenStream) {
3438 print_expr_await(self, tokens, FixupContext::NONE);
3439 }
3440 }
3441
3442 #[cfg(feature = "full")]
3443 fn print_expr_await(e: &ExprAwait, tokens: &mut TokenStream, fixup: FixupContext) {
3444 outer_attrs_to_tokens(&e.attrs, tokens);
3445 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.base);
3446 print_subexpression(
3447 &e.base,
3448 left_prec < Precedence::Unambiguous,
3449 tokens,
3450 left_fixup,
3451 );
3452 e.dot_token.to_tokens(tokens);
3453 e.await_token.to_tokens(tokens);
3454 }
3455
3456 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3457 impl ToTokens for ExprBinary {
3458 fn to_tokens(&self, tokens: &mut TokenStream) {
3459 print_expr_binary(self, tokens, FixupContext::NONE);
3460 }
3461 }
3462
3463 fn print_expr_binary(e: &ExprBinary, tokens: &mut TokenStream, mut fixup: FixupContext) {
3464 outer_attrs_to_tokens(&e.attrs, tokens);
3465
3466 let needs_group = !e.attrs.is_empty();
3467 if needs_group {
3468 fixup = FixupContext::NONE;
3469 }
3470
3471 let do_print_expr = |tokens: &mut TokenStream| {
3472 let binop_prec = Precedence::of_binop(&e.op);
3473 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3474 &e.left,
3475 #[cfg(feature = "full")]
3476 match &e.op {
3477 BinOp::Sub(_)
3478 | BinOp::Mul(_)
3479 | BinOp::And(_)
3480 | BinOp::Or(_)
3481 | BinOp::BitAnd(_)
3482 | BinOp::BitOr(_)
3483 | BinOp::Shl(_)
3484 | BinOp::Lt(_) => true,
3485 _ => false,
3486 },
3487 match &e.op {
3488 BinOp::Shl(_) | BinOp::Lt(_) => true,
3489 _ => false,
3490 },
3491 #[cfg(feature = "full")]
3492 binop_prec,
3493 );
3494 let left_needs_group = match binop_prec {
3495 Precedence::Assign => left_prec <= Precedence::Range,
3496 Precedence::Compare => left_prec <= binop_prec,
3497 _ => left_prec < binop_prec,
3498 };
3499
3500 let right_fixup = fixup.rightmost_subexpression_fixup(
3501 #[cfg(feature = "full")]
3502 false,
3503 #[cfg(feature = "full")]
3504 false,
3505 #[cfg(feature = "full")]
3506 binop_prec,
3507 );
3508 let right_needs_group = binop_prec != Precedence::Assign
3509 && right_fixup.rightmost_subexpression_precedence(&e.right) <= binop_prec;
3510
3511 print_subexpression(&e.left, left_needs_group, tokens, left_fixup);
3512 e.op.to_tokens(tokens);
3513 print_subexpression(&e.right, right_needs_group, tokens, right_fixup);
3514 };
3515
3516 if needs_group {
3517 token::Paren::default().surround(tokens, do_print_expr);
3518 } else {
3519 do_print_expr(tokens);
3520 }
3521 }
3522
3523 #[cfg(feature = "full")]
3524 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3525 impl ToTokens for ExprBlock {
3526 fn to_tokens(&self, tokens: &mut TokenStream) {
3527 outer_attrs_to_tokens(&self.attrs, tokens);
3528 self.label.to_tokens(tokens);
3529 self.block.brace_token.surround(tokens, |tokens| {
3530 inner_attrs_to_tokens(&self.attrs, tokens);
3531 tokens.append_all(&self.block.stmts);
3532 });
3533 }
3534 }
3535
3536 #[cfg(feature = "full")]
3537 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3538 impl ToTokens for ExprBreak {
3539 fn to_tokens(&self, tokens: &mut TokenStream) {
3540 print_expr_break(self, tokens, FixupContext::NONE);
3541 }
3542 }
3543
3544 #[cfg(feature = "full")]
3545 fn print_expr_break(e: &ExprBreak, tokens: &mut TokenStream, fixup: FixupContext) {
3546 outer_attrs_to_tokens(&e.attrs, tokens);
3547 e.break_token.to_tokens(tokens);
3548 e.label.to_tokens(tokens);
3549 if let Some(value) = &e.expr {
3550 print_subexpression(
3551 value,
3552 e.label.is_none() && classify::expr_leading_label(value),
3555 tokens,
3556 fixup.rightmost_subexpression_fixup(true, true, Precedence::Jump),
3557 );
3558 }
3559 }
3560
3561 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3562 impl ToTokens for ExprCall {
3563 fn to_tokens(&self, tokens: &mut TokenStream) {
3564 print_expr_call(self, tokens, FixupContext::NONE);
3565 }
3566 }
3567
3568 fn print_expr_call(e: &ExprCall, tokens: &mut TokenStream, fixup: FixupContext) {
3569 outer_attrs_to_tokens(&e.attrs, tokens);
3570
3571 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3572 &e.func,
3573 #[cfg(feature = "full")]
3574 true,
3575 false,
3576 #[cfg(feature = "full")]
3577 Precedence::Unambiguous,
3578 );
3579 let needs_group = if let Expr::Field(func) = &*e.func {
3580 func.member.is_named()
3581 } else {
3582 left_prec < Precedence::Unambiguous
3583 };
3584 print_subexpression(&e.func, needs_group, tokens, left_fixup);
3585
3586 e.paren_token.surround(tokens, |tokens| {
3587 e.args.to_tokens(tokens);
3588 });
3589 }
3590
3591 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3592 impl ToTokens for ExprCast {
3593 fn to_tokens(&self, tokens: &mut TokenStream) {
3594 print_expr_cast(self, tokens, FixupContext::NONE);
3595 }
3596 }
3597
3598 fn print_expr_cast(e: &ExprCast, tokens: &mut TokenStream, mut fixup: FixupContext) {
3599 outer_attrs_to_tokens(&e.attrs, tokens);
3600
3601 let needs_group = !e.attrs.is_empty();
3602 if needs_group {
3603 fixup = FixupContext::NONE;
3604 }
3605
3606 let do_print_expr = |tokens: &mut TokenStream| {
3607 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3608 &e.expr,
3609 #[cfg(feature = "full")]
3610 false,
3611 false,
3612 #[cfg(feature = "full")]
3613 Precedence::Cast,
3614 );
3615 print_subexpression(&e.expr, left_prec < Precedence::Cast, tokens, left_fixup);
3616 e.as_token.to_tokens(tokens);
3617 e.ty.to_tokens(tokens);
3618 };
3619
3620 if needs_group {
3621 token::Paren::default().surround(tokens, do_print_expr);
3622 } else {
3623 do_print_expr(tokens);
3624 }
3625 }
3626
3627 #[cfg(feature = "full")]
3628 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3629 impl ToTokens for ExprClosure {
3630 fn to_tokens(&self, tokens: &mut TokenStream) {
3631 print_expr_closure(self, tokens, FixupContext::NONE);
3632 }
3633 }
3634
3635 #[cfg(feature = "full")]
3636 fn print_expr_closure(e: &ExprClosure, tokens: &mut TokenStream, fixup: FixupContext) {
3637 outer_attrs_to_tokens(&e.attrs, tokens);
3638 e.lifetimes.to_tokens(tokens);
3639 e.constness.to_tokens(tokens);
3640 e.asyncness.to_tokens(tokens);
3641 e.capture.to_tokens(tokens);
3642 e.inputs_begin.to_tokens(tokens);
3643 e.inputs.to_tokens(tokens);
3644 e.inputs_end.to_tokens(tokens);
3645 e.output.to_tokens(tokens);
3646 if matches!(e.output, ReturnType::Default)
3647 || matches!(&*e.body, Expr::Block(body) if body.attrs.is_empty() && body.label.is_none())
3648 {
3649 print_expr(
3650 &e.body,
3651 tokens,
3652 fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump),
3653 );
3654 } else {
3655 token::Brace::default().surround(tokens, |tokens| {
3656 print_expr(&e.body, tokens, FixupContext::new_stmt());
3657 });
3658 }
3659 }
3660
3661 #[cfg(feature = "full")]
3662 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3663 impl ToTokens for ExprConst {
3664 fn to_tokens(&self, tokens: &mut TokenStream) {
3665 outer_attrs_to_tokens(&self.attrs, tokens);
3666 self.const_token.to_tokens(tokens);
3667 self.block.brace_token.surround(tokens, |tokens| {
3668 inner_attrs_to_tokens(&self.attrs, tokens);
3669 tokens.append_all(&self.block.stmts);
3670 });
3671 }
3672 }
3673
3674 #[cfg(feature = "full")]
3675 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3676 impl ToTokens for ExprContinue {
3677 fn to_tokens(&self, tokens: &mut TokenStream) {
3678 outer_attrs_to_tokens(&self.attrs, tokens);
3679 self.continue_token.to_tokens(tokens);
3680 self.label.to_tokens(tokens);
3681 }
3682 }
3683
3684 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3685 impl ToTokens for ExprField {
3686 fn to_tokens(&self, tokens: &mut TokenStream) {
3687 print_expr_field(self, tokens, FixupContext::NONE);
3688 }
3689 }
3690
3691 fn print_expr_field(e: &ExprField, tokens: &mut TokenStream, fixup: FixupContext) {
3692 outer_attrs_to_tokens(&e.attrs, tokens);
3693 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.base);
3694 print_subexpression(
3695 &e.base,
3696 left_prec < Precedence::Unambiguous,
3697 tokens,
3698 left_fixup,
3699 );
3700 e.dot_token.to_tokens(tokens);
3701 e.member.to_tokens(tokens);
3702 }
3703
3704 #[cfg(feature = "full")]
3705 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3706 impl ToTokens for ExprForLoop {
3707 fn to_tokens(&self, tokens: &mut TokenStream) {
3708 outer_attrs_to_tokens(&self.attrs, tokens);
3709 self.label.to_tokens(tokens);
3710 self.for_token.to_tokens(tokens);
3711 self.pat.to_tokens(tokens);
3712 self.in_token.to_tokens(tokens);
3713 print_expr(&self.expr, tokens, FixupContext::new_condition());
3714 self.body.brace_token.surround(tokens, |tokens| {
3715 inner_attrs_to_tokens(&self.attrs, tokens);
3716 tokens.append_all(&self.body.stmts);
3717 });
3718 }
3719 }
3720
3721 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3722 impl ToTokens for ExprGroup {
3723 fn to_tokens(&self, tokens: &mut TokenStream) {
3724 outer_attrs_to_tokens(&self.attrs, tokens);
3725 self.group_token.surround(tokens, |tokens| {
3726 self.expr.to_tokens(tokens);
3727 });
3728 }
3729 }
3730
3731 #[cfg(feature = "full")]
3732 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3733 impl ToTokens for ExprIf {
3734 fn to_tokens(&self, tokens: &mut TokenStream) {
3735 outer_attrs_to_tokens(&self.attrs, tokens);
3736
3737 let mut expr = self;
3738 loop {
3739 expr.if_token.to_tokens(tokens);
3740 print_expr(&expr.cond, tokens, FixupContext::new_condition());
3741 expr.then_branch.to_tokens(tokens);
3742
3743 let (else_token, else_) = match &expr.else_branch {
3744 Some(else_branch) => else_branch,
3745 None => break,
3746 };
3747
3748 else_token.to_tokens(tokens);
3749 match &**else_ {
3750 Expr::If(next) => {
3751 expr = next;
3752 }
3753 Expr::Block(last) => {
3754 last.to_tokens(tokens);
3755 break;
3756 }
3757 other => {
3760 token::Brace::default().surround(tokens, |tokens| {
3761 print_expr(other, tokens, FixupContext::new_stmt());
3762 });
3763 break;
3764 }
3765 }
3766 }
3767 }
3768 }
3769
3770 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3771 impl ToTokens for ExprIndex {
3772 fn to_tokens(&self, tokens: &mut TokenStream) {
3773 print_expr_index(self, tokens, FixupContext::NONE);
3774 }
3775 }
3776
3777 fn print_expr_index(e: &ExprIndex, tokens: &mut TokenStream, fixup: FixupContext) {
3778 outer_attrs_to_tokens(&e.attrs, tokens);
3779 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3780 &e.expr,
3781 #[cfg(feature = "full")]
3782 true,
3783 false,
3784 #[cfg(feature = "full")]
3785 Precedence::Unambiguous,
3786 );
3787 print_subexpression(
3788 &e.expr,
3789 left_prec < Precedence::Unambiguous,
3790 tokens,
3791 left_fixup,
3792 );
3793 e.bracket_token.surround(tokens, |tokens| {
3794 e.index.to_tokens(tokens);
3795 });
3796 }
3797
3798 #[cfg(feature = "full")]
3799 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3800 impl ToTokens for ExprInfer {
3801 fn to_tokens(&self, tokens: &mut TokenStream) {
3802 outer_attrs_to_tokens(&self.attrs, tokens);
3803 self.underscore_token.to_tokens(tokens);
3804 }
3805 }
3806
3807 #[cfg(feature = "full")]
3808 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3809 impl ToTokens for ExprLet {
3810 fn to_tokens(&self, tokens: &mut TokenStream) {
3811 print_expr_let(self, tokens, FixupContext::NONE);
3812 }
3813 }
3814
3815 #[cfg(feature = "full")]
3816 fn print_expr_let(e: &ExprLet, tokens: &mut TokenStream, fixup: FixupContext) {
3817 outer_attrs_to_tokens(&e.attrs, tokens);
3818 e.let_token.to_tokens(tokens);
3819 e.pat.to_tokens(tokens);
3820 e.eq_token.to_tokens(tokens);
3821 let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Let);
3822 print_subexpression(&e.expr, right_prec < Precedence::Let, tokens, right_fixup);
3823 }
3824
3825 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3826 impl ToTokens for ExprLit {
3827 fn to_tokens(&self, tokens: &mut TokenStream) {
3828 outer_attrs_to_tokens(&self.attrs, tokens);
3829 self.lit.to_tokens(tokens);
3830 }
3831 }
3832
3833 #[cfg(feature = "full")]
3834 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3835 impl ToTokens for ExprLoop {
3836 fn to_tokens(&self, tokens: &mut TokenStream) {
3837 outer_attrs_to_tokens(&self.attrs, tokens);
3838 self.label.to_tokens(tokens);
3839 self.loop_token.to_tokens(tokens);
3840 self.body.brace_token.surround(tokens, |tokens| {
3841 inner_attrs_to_tokens(&self.attrs, tokens);
3842 tokens.append_all(&self.body.stmts);
3843 });
3844 }
3845 }
3846
3847 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3848 impl ToTokens for ExprMacro {
3849 fn to_tokens(&self, tokens: &mut TokenStream) {
3850 outer_attrs_to_tokens(&self.attrs, tokens);
3851 self.mac.to_tokens(tokens);
3852 }
3853 }
3854
3855 #[cfg(feature = "full")]
3856 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3857 impl ToTokens for ExprMatch {
3858 fn to_tokens(&self, tokens: &mut TokenStream) {
3859 outer_attrs_to_tokens(&self.attrs, tokens);
3860 self.match_token.to_tokens(tokens);
3861 print_expr(&self.expr, tokens, FixupContext::new_condition());
3862 self.brace_token.surround(tokens, |tokens| {
3863 inner_attrs_to_tokens(&self.attrs, tokens);
3864 for (i, arm) in self.arms.iter().enumerate() {
3865 arm.to_tokens(tokens);
3866 let is_last = i == self.arms.len() - 1;
3869 if !is_last
3870 && classify::requires_comma_to_be_match_arm(&arm.body)
3871 && arm.comma.is_none()
3872 {
3873 <Token![,]>::default().to_tokens(tokens);
3874 }
3875 }
3876 });
3877 }
3878 }
3879
3880 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3881 impl ToTokens for ExprMethodCall {
3882 fn to_tokens(&self, tokens: &mut TokenStream) {
3883 print_expr_method_call(self, tokens, FixupContext::NONE);
3884 }
3885 }
3886
3887 fn print_expr_method_call(e: &ExprMethodCall, tokens: &mut TokenStream, fixup: FixupContext) {
3888 outer_attrs_to_tokens(&e.attrs, tokens);
3889 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.receiver);
3890 print_subexpression(
3891 &e.receiver,
3892 left_prec < Precedence::Unambiguous,
3893 tokens,
3894 left_fixup,
3895 );
3896 e.dot_token.to_tokens(tokens);
3897 e.method.to_tokens(tokens);
3898 if let Some(turbofish) = &e.turbofish {
3899 path::printing::print_angle_bracketed_generic_arguments(
3900 tokens,
3901 turbofish,
3902 PathStyle::Expr,
3903 );
3904 }
3905 e.paren_token.surround(tokens, |tokens| {
3906 e.args.to_tokens(tokens);
3907 });
3908 }
3909
3910 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3911 impl ToTokens for ExprParen {
3912 fn to_tokens(&self, tokens: &mut TokenStream) {
3913 outer_attrs_to_tokens(&self.attrs, tokens);
3914 self.paren_token.surround(tokens, |tokens| {
3915 self.expr.to_tokens(tokens);
3916 });
3917 }
3918 }
3919
3920 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3921 impl ToTokens for ExprPath {
3922 fn to_tokens(&self, tokens: &mut TokenStream) {
3923 outer_attrs_to_tokens(&self.attrs, tokens);
3924 path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
3925 }
3926 }
3927
3928 #[cfg(feature = "full")]
3929 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3930 impl ToTokens for ExprRange {
3931 fn to_tokens(&self, tokens: &mut TokenStream) {
3932 print_expr_range(self, tokens, FixupContext::NONE);
3933 }
3934 }
3935
3936 #[cfg(feature = "full")]
3937 fn print_expr_range(e: &ExprRange, tokens: &mut TokenStream, mut fixup: FixupContext) {
3938 outer_attrs_to_tokens(&e.attrs, tokens);
3939
3940 let needs_group = !e.attrs.is_empty();
3941 if needs_group {
3942 fixup = FixupContext::NONE;
3943 }
3944
3945 let do_print_expr = |tokens: &mut TokenStream| {
3946 if let Some(start) = &e.start {
3947 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3948 start,
3949 true,
3950 false,
3951 Precedence::Range,
3952 );
3953 print_subexpression(start, left_prec <= Precedence::Range, tokens, left_fixup);
3954 }
3955 e.limits.to_tokens(tokens);
3956 if let Some(end) = &e.end {
3957 let right_fixup =
3958 fixup.rightmost_subexpression_fixup(false, true, Precedence::Range);
3959 let right_prec = right_fixup.rightmost_subexpression_precedence(end);
3960 print_subexpression(end, right_prec <= Precedence::Range, tokens, right_fixup);
3961 }
3962 };
3963
3964 if needs_group {
3965 token::Paren::default().surround(tokens, do_print_expr);
3966 } else {
3967 do_print_expr(tokens);
3968 }
3969 }
3970
3971 #[cfg(feature = "full")]
3972 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3973 impl ToTokens for ExprRawAddr {
3974 fn to_tokens(&self, tokens: &mut TokenStream) {
3975 print_expr_raw_addr(self, tokens, FixupContext::NONE);
3976 }
3977 }
3978
3979 #[cfg(feature = "full")]
3980 fn print_expr_raw_addr(e: &ExprRawAddr, tokens: &mut TokenStream, fixup: FixupContext) {
3981 outer_attrs_to_tokens(&e.attrs, tokens);
3982 e.and_token.to_tokens(tokens);
3983 e.raw.to_tokens(tokens);
3984 e.mutability.to_tokens(tokens);
3985 let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Prefix);
3986 print_subexpression(
3987 &e.expr,
3988 right_prec < Precedence::Prefix,
3989 tokens,
3990 right_fixup,
3991 );
3992 }
3993
3994 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3995 impl ToTokens for ExprReference {
3996 fn to_tokens(&self, tokens: &mut TokenStream) {
3997 print_expr_reference(self, tokens, FixupContext::NONE);
3998 }
3999 }
4000
4001 fn print_expr_reference(e: &ExprReference, tokens: &mut TokenStream, fixup: FixupContext) {
4002 outer_attrs_to_tokens(&e.attrs, tokens);
4003 e.and_token.to_tokens(tokens);
4004 e.mutability.to_tokens(tokens);
4005 let (right_prec, right_fixup) = fixup.rightmost_subexpression(
4006 &e.expr,
4007 #[cfg(feature = "full")]
4008 Precedence::Prefix,
4009 );
4010 print_subexpression(
4011 &e.expr,
4012 right_prec < Precedence::Prefix,
4013 tokens,
4014 right_fixup,
4015 );
4016 }
4017
4018 #[cfg(feature = "full")]
4019 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4020 impl ToTokens for ExprRepeat {
4021 fn to_tokens(&self, tokens: &mut TokenStream) {
4022 outer_attrs_to_tokens(&self.attrs, tokens);
4023 self.bracket_token.surround(tokens, |tokens| {
4024 self.expr.to_tokens(tokens);
4025 self.semi_token.to_tokens(tokens);
4026 self.len.to_tokens(tokens);
4027 });
4028 }
4029 }
4030
4031 #[cfg(feature = "full")]
4032 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4033 impl ToTokens for ExprReturn {
4034 fn to_tokens(&self, tokens: &mut TokenStream) {
4035 print_expr_return(self, tokens, FixupContext::NONE);
4036 }
4037 }
4038
4039 #[cfg(feature = "full")]
4040 fn print_expr_return(e: &ExprReturn, tokens: &mut TokenStream, fixup: FixupContext) {
4041 outer_attrs_to_tokens(&e.attrs, tokens);
4042 e.return_token.to_tokens(tokens);
4043 if let Some(expr) = &e.expr {
4044 print_expr(
4045 expr,
4046 tokens,
4047 fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
4048 );
4049 }
4050 }
4051
4052 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4053 impl ToTokens for ExprStruct {
4054 fn to_tokens(&self, tokens: &mut TokenStream) {
4055 outer_attrs_to_tokens(&self.attrs, tokens);
4056 path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
4057 self.brace_token.surround(tokens, |tokens| {
4058 self.fields.to_tokens(tokens);
4059 if let Some(dot2_token) = &self.dot2_token {
4060 dot2_token.to_tokens(tokens);
4061 } else if self.rest.is_some() {
4062 Token).to_tokens(tokens);
4063 }
4064 self.rest.to_tokens(tokens);
4065 });
4066 }
4067 }
4068
4069 #[cfg(feature = "full")]
4070 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4071 impl ToTokens for ExprTry {
4072 fn to_tokens(&self, tokens: &mut TokenStream) {
4073 print_expr_try(self, tokens, FixupContext::NONE);
4074 }
4075 }
4076
4077 #[cfg(feature = "full")]
4078 fn print_expr_try(e: &ExprTry, tokens: &mut TokenStream, fixup: FixupContext) {
4079 outer_attrs_to_tokens(&e.attrs, tokens);
4080 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.expr);
4081 print_subexpression(
4082 &e.expr,
4083 left_prec < Precedence::Unambiguous,
4084 tokens,
4085 left_fixup,
4086 );
4087 e.question_token.to_tokens(tokens);
4088 }
4089
4090 #[cfg(feature = "full")]
4091 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4092 impl ToTokens for ExprTryBlock {
4093 fn to_tokens(&self, tokens: &mut TokenStream) {
4094 outer_attrs_to_tokens(&self.attrs, tokens);
4095 self.try_token.to_tokens(tokens);
4096 self.block.to_tokens(tokens);
4097 }
4098 }
4099
4100 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4101 impl ToTokens for ExprTuple {
4102 fn to_tokens(&self, tokens: &mut TokenStream) {
4103 outer_attrs_to_tokens(&self.attrs, tokens);
4104 self.paren_token.surround(tokens, |tokens| {
4105 self.elems.to_tokens(tokens);
4106 if self.elems.len() == 1 && !self.elems.trailing_punct() {
4109 <Token![,]>::default().to_tokens(tokens);
4110 }
4111 });
4112 }
4113 }
4114
4115 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4116 impl ToTokens for ExprUnary {
4117 fn to_tokens(&self, tokens: &mut TokenStream) {
4118 print_expr_unary(self, tokens, FixupContext::NONE);
4119 }
4120 }
4121
4122 fn print_expr_unary(e: &ExprUnary, tokens: &mut TokenStream, fixup: FixupContext) {
4123 outer_attrs_to_tokens(&e.attrs, tokens);
4124 e.op.to_tokens(tokens);
4125 let (right_prec, right_fixup) = fixup.rightmost_subexpression(
4126 &e.expr,
4127 #[cfg(feature = "full")]
4128 Precedence::Prefix,
4129 );
4130 print_subexpression(
4131 &e.expr,
4132 right_prec < Precedence::Prefix,
4133 tokens,
4134 right_fixup,
4135 );
4136 }
4137
4138 #[cfg(feature = "full")]
4139 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4140 impl ToTokens for ExprUnsafe {
4141 fn to_tokens(&self, tokens: &mut TokenStream) {
4142 outer_attrs_to_tokens(&self.attrs, tokens);
4143 self.unsafe_token.to_tokens(tokens);
4144 self.block.brace_token.surround(tokens, |tokens| {
4145 inner_attrs_to_tokens(&self.attrs, tokens);
4146 tokens.append_all(&self.block.stmts);
4147 });
4148 }
4149 }
4150
4151 #[cfg(feature = "full")]
4152 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4153 impl ToTokens for ExprWhile {
4154 fn to_tokens(&self, tokens: &mut TokenStream) {
4155 outer_attrs_to_tokens(&self.attrs, tokens);
4156 self.label.to_tokens(tokens);
4157 self.while_token.to_tokens(tokens);
4158 print_expr(&self.cond, tokens, FixupContext::new_condition());
4159 self.body.brace_token.surround(tokens, |tokens| {
4160 inner_attrs_to_tokens(&self.attrs, tokens);
4161 tokens.append_all(&self.body.stmts);
4162 });
4163 }
4164 }
4165
4166 #[cfg(feature = "full")]
4167 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4168 impl ToTokens for ExprYield {
4169 fn to_tokens(&self, tokens: &mut TokenStream) {
4170 print_expr_yield(self, tokens, FixupContext::NONE);
4171 }
4172 }
4173
4174 #[cfg(feature = "full")]
4175 fn print_expr_yield(e: &ExprYield, tokens: &mut TokenStream, fixup: FixupContext) {
4176 outer_attrs_to_tokens(&e.attrs, tokens);
4177 e.yield_token.to_tokens(tokens);
4178 if let Some(expr) = &e.expr {
4179 print_expr(
4180 expr,
4181 tokens,
4182 fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
4183 );
4184 }
4185 }
4186
4187 #[cfg(feature = "full")]
4188 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4189 impl ToTokens for Arm {
4190 fn to_tokens(&self, tokens: &mut TokenStream) {
4191 tokens.append_all(&self.attrs);
4192 self.pat.to_tokens(tokens);
4193 self.fat_arrow_token.to_tokens(tokens);
4194 print_expr(&self.body, tokens, FixupContext::new_match_arm());
4195 self.comma.to_tokens(tokens);
4196 }
4197 }
4198
4199 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4200 impl ToTokens for FieldValue {
4201 fn to_tokens(&self, tokens: &mut TokenStream) {
4202 outer_attrs_to_tokens(&self.attrs, tokens);
4203 self.member.to_tokens(tokens);
4204 if let Some(colon_token) = &self.colon_token {
4205 colon_token.to_tokens(tokens);
4206 self.expr.to_tokens(tokens);
4207 }
4208 }
4209 }
4210
4211 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4212 impl ToTokens for Index {
4213 fn to_tokens(&self, tokens: &mut TokenStream) {
4214 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
4215 lit.set_span(self.span);
4216 tokens.append(lit);
4217 }
4218 }
4219
4220 #[cfg(feature = "full")]
4221 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4222 impl ToTokens for Label {
4223 fn to_tokens(&self, tokens: &mut TokenStream) {
4224 self.name.to_tokens(tokens);
4225 self.colon_token.to_tokens(tokens);
4226 }
4227 }
4228
4229 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4230 impl ToTokens for Member {
4231 fn to_tokens(&self, tokens: &mut TokenStream) {
4232 match self {
4233 Member::Named(ident) => ident.to_tokens(tokens),
4234 Member::Unnamed(index) => index.to_tokens(tokens),
4235 }
4236 }
4237 }
4238
4239 #[cfg(feature = "full")]
4240 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4241 impl ToTokens for RangeLimits {
4242 fn to_tokens(&self, tokens: &mut TokenStream) {
4243 match self {
4244 RangeLimits::HalfOpen(t) => t.to_tokens(tokens),
4245 RangeLimits::Closed(t) => t.to_tokens(tokens),
4246 }
4247 }
4248 }
4249}