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