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![as]) || input.peek(token::Paren) || input.peek(token::Bracket) || input.peek(token::Brace) || input.peek(Lit) || input.peek(Token![!]) && !input.peek(Token![!=]) || input.peek(Token![-]) && !input.peek(Token![-=]) && !input.peek(Token![->]) || input.peek(Token![*]) && !input.peek(Token![*=]) || input.peek(Token![|]) && !input.peek(Token![|=]) || input.peek(Token![&]) && !input.peek(Token![&=]) || input.peek(Token![..]) || input.peek(Token![<]) && !input.peek(Token![<=]) && !input.peek(Token![<<=]) || input.peek(Token![::]) || input.peek(Lifetime) || input.peek(Token![#]) }
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
1039#[cfg(any(feature = "parsing", feature = "printing"))]
1040impl Member {
1041 pub(crate) fn is_named(&self) -> bool {
1042 match self {
1043 Member::Named(_) => true,
1044 Member::Unnamed(_) => false,
1045 }
1046 }
1047}
1048
1049ast_struct! {
1050 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
1052 pub struct Index {
1053 pub index: u32,
1054 pub span: Span,
1055 }
1056}
1057
1058impl From<usize> for Index {
1059 fn from(index: usize) -> Index {
1060 assert!(index < u32::MAX as usize);
1061 Index {
1062 index: index as u32,
1063 span: Span::call_site(),
1064 }
1065 }
1066}
1067
1068impl Eq for Index {}
1069
1070impl PartialEq for Index {
1071 fn eq(&self, other: &Self) -> bool {
1072 self.index == other.index
1073 }
1074}
1075
1076impl Hash for Index {
1077 fn hash<H: Hasher>(&self, state: &mut H) {
1078 self.index.hash(state);
1079 }
1080}
1081
1082#[cfg(feature = "printing")]
1083impl IdentFragment for Index {
1084 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1085 Display::fmt(&self.index, formatter)
1086 }
1087
1088 fn span(&self) -> Option<Span> {
1089 Some(self.span)
1090 }
1091}
1092
1093ast_struct! {
1094 #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
1096 pub struct FieldValue {
1097 pub attrs: Vec<Attribute>,
1098 pub member: Member,
1099
1100 pub colon_token: Option<Token![:]>,
1103
1104 pub expr: Expr,
1105 }
1106}
1107
1108#[cfg(feature = "full")]
1109ast_struct! {
1110 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
1112 pub struct Label {
1113 pub name: Lifetime,
1114 pub colon_token: Token![:],
1115 }
1116}
1117
1118#[cfg(feature = "full")]
1119ast_struct! {
1120 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
1138 pub struct Arm {
1139 pub attrs: Vec<Attribute>,
1140 pub pat: Pat,
1141 pub guard: Option<(Token![if], Box<Expr>)>,
1142 pub fat_arrow_token: Token![=>],
1143 pub body: Box<Expr>,
1144 pub comma: Option<Token![,]>,
1145 }
1146}
1147
1148#[cfg(feature = "full")]
1149ast_enum! {
1150 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
1152 pub enum RangeLimits {
1153 HalfOpen(Token![..]),
1155 Closed(Token![..=]),
1157 }
1158}
1159
1160#[cfg(feature = "full")]
1161ast_enum! {
1162 #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
1165 pub enum PointerMutability {
1166 Const(Token![const]),
1167 Mut(Token![mut]),
1168 }
1169}
1170
1171#[cfg(feature = "parsing")]
1172pub(crate) mod parsing {
1173 #[cfg(feature = "full")]
1174 use crate::attr;
1175 use crate::attr::Attribute;
1176 #[cfg(feature = "full")]
1177 use crate::classify;
1178 use crate::error::{Error, Result};
1179 #[cfg(feature = "full")]
1180 use crate::expr::{
1181 Arm, ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure,
1182 ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch,
1183 ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprUnsafe,
1184 ExprWhile, ExprYield, Label, PointerMutability, RangeLimits,
1185 };
1186 use crate::expr::{
1187 Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro,
1188 ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprTuple, ExprUnary,
1189 FieldValue, Index, Member,
1190 };
1191 #[cfg(feature = "full")]
1192 use crate::generics::BoundLifetimes;
1193 use crate::ident::Ident;
1194 #[cfg(feature = "full")]
1195 use crate::lifetime::Lifetime;
1196 use crate::lit::{Lit, LitFloat, LitInt};
1197 use crate::mac::{self, Macro};
1198 use crate::op::BinOp;
1199 use crate::parse::discouraged::Speculative as _;
1200 #[cfg(feature = "full")]
1201 use crate::parse::ParseBuffer;
1202 use crate::parse::{Parse, ParseStream};
1203 #[cfg(feature = "full")]
1204 use crate::pat::{Pat, PatType};
1205 use crate::path::{self, AngleBracketedGenericArguments, Path, QSelf};
1206 use crate::precedence::Precedence;
1207 use crate::punctuated::Punctuated;
1208 #[cfg(feature = "full")]
1209 use crate::stmt::Block;
1210 use crate::token;
1211 use crate::ty;
1212 #[cfg(feature = "full")]
1213 use crate::ty::{ReturnType, Type};
1214 use crate::verbatim;
1215 #[cfg(feature = "full")]
1216 use proc_macro2::{Span, TokenStream};
1217 use std::mem;
1218
1219 #[cfg(feature = "full")]
1225 pub(super) struct AllowStruct(pub bool);
1226
1227 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1228 impl Parse for Expr {
1229 fn parse(input: ParseStream) -> Result<Self> {
1230 ambiguous_expr(
1231 input,
1232 #[cfg(feature = "full")]
1233 AllowStruct(true),
1234 )
1235 }
1236 }
1237
1238 #[cfg(feature = "full")]
1239 pub(super) fn parse_with_earlier_boundary_rule(input: ParseStream) -> Result<Expr> {
1240 let mut attrs = input.call(expr_attrs)?;
1241 let mut expr = if input.peek(token::Group) {
1242 let allow_struct = AllowStruct(true);
1243 let atom = expr_group(input, allow_struct)?;
1244 if continue_parsing_early(&atom) {
1245 trailer_helper(input, atom)?
1246 } else {
1247 atom
1248 }
1249 } else if input.peek(Token![if]) {
1250 Expr::If(input.parse()?)
1251 } else if input.peek(Token![while]) {
1252 Expr::While(input.parse()?)
1253 } else if input.peek(Token![for])
1254 && !(input.peek2(Token![<]) && (input.peek3(Lifetime) || input.peek3(Token![>])))
1255 {
1256 Expr::ForLoop(input.parse()?)
1257 } else if input.peek(Token![loop]) {
1258 Expr::Loop(input.parse()?)
1259 } else if input.peek(Token![match]) {
1260 Expr::Match(input.parse()?)
1261 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
1262 Expr::TryBlock(input.parse()?)
1263 } else if input.peek(Token![unsafe]) {
1264 Expr::Unsafe(input.parse()?)
1265 } else if input.peek(Token![const]) && input.peek2(token::Brace) {
1266 Expr::Const(input.parse()?)
1267 } else if input.peek(token::Brace) {
1268 Expr::Block(input.parse()?)
1269 } else if input.peek(Lifetime) {
1270 atom_labeled(input)?
1271 } else {
1272 let allow_struct = AllowStruct(true);
1273 unary_expr(input, allow_struct)?
1274 };
1275
1276 if continue_parsing_early(&expr) {
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 if input.peek(Token![.]) && !input.peek(Token![..]) || input.peek(Token![?]) {
1285 expr = trailer_helper(input, expr)?;
1286
1287 attrs.extend(expr.replace_attrs(Vec::new()));
1288 expr.replace_attrs(attrs);
1289
1290 let allow_struct = AllowStruct(true);
1291 return parse_expr(input, expr, allow_struct, Precedence::MIN);
1292 }
1293
1294 attrs.extend(expr.replace_attrs(Vec::new()));
1295 expr.replace_attrs(attrs);
1296 Ok(expr)
1297 }
1298
1299 #[cfg(feature = "full")]
1300 impl Copy for AllowStruct {}
1301
1302 #[cfg(feature = "full")]
1303 impl Clone for AllowStruct {
1304 fn clone(&self) -> Self {
1305 *self
1306 }
1307 }
1308
1309 #[cfg(feature = "full")]
1310 fn parse_expr(
1311 input: ParseStream,
1312 mut lhs: Expr,
1313 allow_struct: AllowStruct,
1314 base: Precedence,
1315 ) -> Result<Expr> {
1316 loop {
1317 let ahead = input.fork();
1318 if let Expr::Range(_) = lhs {
1319 break;
1321 } else if let Ok(op) = ahead.parse::<BinOp>() {
1322 let precedence = Precedence::of_binop(&op);
1323 if precedence < base {
1324 break;
1325 }
1326 if precedence == Precedence::Assign {
1327 if let Expr::Range(_) = lhs {
1328 break;
1329 }
1330 }
1331 if precedence == Precedence::Compare {
1332 if let Expr::Binary(lhs) = &lhs {
1333 if Precedence::of_binop(&lhs.op) == Precedence::Compare {
1334 return Err(input.error("comparison operators cannot be chained"));
1335 }
1336 }
1337 }
1338 input.advance_to(&ahead);
1339 let right = parse_binop_rhs(input, allow_struct, precedence)?;
1340 lhs = Expr::Binary(ExprBinary {
1341 attrs: Vec::new(),
1342 left: Box::new(lhs),
1343 op,
1344 right,
1345 });
1346 } else if Precedence::Assign >= base
1347 && input.peek(Token![=])
1348 && !input.peek(Token![=>])
1349 && match lhs {
1350 Expr::Range(_) => false,
1351 _ => true,
1352 }
1353 {
1354 let eq_token: Token![=] = input.parse()?;
1355 let right = parse_binop_rhs(input, allow_struct, Precedence::Assign)?;
1356 lhs = Expr::Assign(ExprAssign {
1357 attrs: Vec::new(),
1358 left: Box::new(lhs),
1359 eq_token,
1360 right,
1361 });
1362 } else if Precedence::Range >= base && input.peek(Token![..]) {
1363 let limits: RangeLimits = input.parse()?;
1364 let end = parse_range_end(input, &limits, allow_struct)?;
1365 lhs = Expr::Range(ExprRange {
1366 attrs: Vec::new(),
1367 start: Some(Box::new(lhs)),
1368 limits,
1369 end,
1370 });
1371 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1372 let as_token: Token![as] = input.parse()?;
1373 let allow_plus = false;
1374 let allow_group_generic = false;
1375 let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
1376 check_cast(input)?;
1377 lhs = Expr::Cast(ExprCast {
1378 attrs: Vec::new(),
1379 expr: Box::new(lhs),
1380 as_token,
1381 ty: Box::new(ty),
1382 });
1383 } else {
1384 break;
1385 }
1386 }
1387 Ok(lhs)
1388 }
1389
1390 #[cfg(not(feature = "full"))]
1391 fn parse_expr(input: ParseStream, mut lhs: Expr, base: Precedence) -> Result<Expr> {
1392 loop {
1393 let ahead = input.fork();
1394 if let Ok(op) = ahead.parse::<BinOp>() {
1395 let precedence = Precedence::of_binop(&op);
1396 if precedence < base {
1397 break;
1398 }
1399 if precedence == Precedence::Compare {
1400 if let Expr::Binary(lhs) = &lhs {
1401 if Precedence::of_binop(&lhs.op) == Precedence::Compare {
1402 return Err(input.error("comparison operators cannot be chained"));
1403 }
1404 }
1405 }
1406 input.advance_to(&ahead);
1407 let right = parse_binop_rhs(input, precedence)?;
1408 lhs = Expr::Binary(ExprBinary {
1409 attrs: Vec::new(),
1410 left: Box::new(lhs),
1411 op,
1412 right,
1413 });
1414 } else if Precedence::Cast >= base && input.peek(Token![as]) {
1415 let as_token: Token![as] = input.parse()?;
1416 let allow_plus = false;
1417 let allow_group_generic = false;
1418 let ty = ty::parsing::ambig_ty(input, allow_plus, allow_group_generic)?;
1419 check_cast(input)?;
1420 lhs = Expr::Cast(ExprCast {
1421 attrs: Vec::new(),
1422 expr: Box::new(lhs),
1423 as_token,
1424 ty: Box::new(ty),
1425 });
1426 } else {
1427 break;
1428 }
1429 }
1430 Ok(lhs)
1431 }
1432
1433 fn parse_binop_rhs(
1434 input: ParseStream,
1435 #[cfg(feature = "full")] allow_struct: AllowStruct,
1436 precedence: Precedence,
1437 ) -> Result<Box<Expr>> {
1438 let mut rhs = unary_expr(
1439 input,
1440 #[cfg(feature = "full")]
1441 allow_struct,
1442 )?;
1443 loop {
1444 let next = peek_precedence(input);
1445 if next > precedence || next == precedence && precedence == Precedence::Assign {
1446 let cursor = input.cursor();
1447 rhs = parse_expr(
1448 input,
1449 rhs,
1450 #[cfg(feature = "full")]
1451 allow_struct,
1452 next,
1453 )?;
1454 if cursor == input.cursor() {
1455 break;
1460 }
1461 } else {
1462 break;
1463 }
1464 }
1465 Ok(Box::new(rhs))
1466 }
1467
1468 fn peek_precedence(input: ParseStream) -> Precedence {
1469 if let Ok(op) = input.fork().parse() {
1470 Precedence::of_binop(&op)
1471 } else if input.peek(Token![=]) && !input.peek(Token![=>]) {
1472 Precedence::Assign
1473 } else if input.peek(Token![..]) {
1474 Precedence::Range
1475 } else if input.peek(Token![as]) {
1476 Precedence::Cast
1477 } else {
1478 Precedence::MIN
1479 }
1480 }
1481
1482 pub(super) fn ambiguous_expr(
1484 input: ParseStream,
1485 #[cfg(feature = "full")] allow_struct: AllowStruct,
1486 ) -> Result<Expr> {
1487 let lhs = unary_expr(
1488 input,
1489 #[cfg(feature = "full")]
1490 allow_struct,
1491 )?;
1492 parse_expr(
1493 input,
1494 lhs,
1495 #[cfg(feature = "full")]
1496 allow_struct,
1497 Precedence::MIN,
1498 )
1499 }
1500
1501 #[cfg(feature = "full")]
1502 fn expr_attrs(input: ParseStream) -> Result<Vec<Attribute>> {
1503 let mut attrs = Vec::new();
1504 while !input.peek(token::Group) && input.peek(Token![#]) {
1505 attrs.push(input.call(attr::parsing::single_parse_outer)?);
1506 }
1507 Ok(attrs)
1508 }
1509
1510 #[cfg(feature = "full")]
1515 fn unary_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1516 let begin = input.fork();
1517 let attrs = input.call(expr_attrs)?;
1518 if input.peek(token::Group) {
1519 return trailer_expr(begin, attrs, input, allow_struct);
1520 }
1521
1522 if input.peek(Token![&]) {
1523 let and_token: Token![&] = input.parse()?;
1524 let raw: Option<Token![raw]> = if input.peek(Token![raw])
1525 && (input.peek2(Token![mut]) || input.peek2(Token![const]))
1526 {
1527 Some(input.parse()?)
1528 } else {
1529 None
1530 };
1531 let mutability: Option<Token![mut]> = input.parse()?;
1532 let const_token: Option<Token![const]> = if raw.is_some() && mutability.is_none() {
1533 Some(input.parse()?)
1534 } else {
1535 None
1536 };
1537 let expr = Box::new(unary_expr(input, allow_struct)?);
1538 if let Some(raw) = raw {
1539 Ok(Expr::RawAddr(ExprRawAddr {
1540 attrs,
1541 and_token,
1542 raw,
1543 mutability: match mutability {
1544 Some(mut_token) => PointerMutability::Mut(mut_token),
1545 None => PointerMutability::Const(const_token.unwrap()),
1546 },
1547 expr,
1548 }))
1549 } else {
1550 Ok(Expr::Reference(ExprReference {
1551 attrs,
1552 and_token,
1553 mutability,
1554 expr,
1555 }))
1556 }
1557 } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
1558 expr_unary(input, attrs, allow_struct).map(Expr::Unary)
1559 } else {
1560 trailer_expr(begin, attrs, input, allow_struct)
1561 }
1562 }
1563
1564 #[cfg(not(feature = "full"))]
1565 fn unary_expr(input: ParseStream) -> Result<Expr> {
1566 if input.peek(Token![&]) {
1567 Ok(Expr::Reference(ExprReference {
1568 attrs: Vec::new(),
1569 and_token: input.parse()?,
1570 mutability: input.parse()?,
1571 expr: Box::new(unary_expr(input)?),
1572 }))
1573 } else if input.peek(Token![*]) || input.peek(Token![!]) || input.peek(Token![-]) {
1574 Ok(Expr::Unary(ExprUnary {
1575 attrs: Vec::new(),
1576 op: input.parse()?,
1577 expr: Box::new(unary_expr(input)?),
1578 }))
1579 } else {
1580 trailer_expr(input)
1581 }
1582 }
1583
1584 #[cfg(feature = "full")]
1591 fn trailer_expr(
1592 begin: ParseBuffer,
1593 mut attrs: Vec<Attribute>,
1594 input: ParseStream,
1595 allow_struct: AllowStruct,
1596 ) -> Result<Expr> {
1597 let atom = atom_expr(input, allow_struct)?;
1598 let mut e = trailer_helper(input, atom)?;
1599
1600 if let Expr::Verbatim(tokens) = &mut e {
1601 *tokens = verbatim::between(&begin, input);
1602 } else if !attrs.is_empty() {
1603 if let Expr::Range(range) = e {
1604 let spans: &[Span] = match &range.limits {
1605 RangeLimits::HalfOpen(limits) => &limits.spans,
1606 RangeLimits::Closed(limits) => &limits.spans,
1607 };
1608 return Err(crate::error::new2(
1609 spans[0],
1610 *spans.last().unwrap(),
1611 "attributes are not allowed on range expressions starting with `..`",
1612 ));
1613 }
1614 let inner_attrs = e.replace_attrs(Vec::new());
1615 attrs.extend(inner_attrs);
1616 e.replace_attrs(attrs);
1617 }
1618
1619 Ok(e)
1620 }
1621
1622 #[cfg(feature = "full")]
1623 fn trailer_helper(input: ParseStream, mut e: Expr) -> Result<Expr> {
1624 loop {
1625 if input.peek(token::Paren) {
1626 let content;
1627 e = Expr::Call(ExprCall {
1628 attrs: Vec::new(),
1629 func: Box::new(e),
1630 paren_token: parenthesized!(content in input),
1631 args: content.parse_terminated(Expr::parse, Token![,])?,
1632 });
1633 } else if input.peek(Token![.])
1634 && !input.peek(Token![..])
1635 && match e {
1636 Expr::Range(_) => false,
1637 _ => true,
1638 }
1639 {
1640 let mut dot_token: Token![.] = input.parse()?;
1641
1642 let float_token: Option<LitFloat> = input.parse()?;
1643 if let Some(float_token) = float_token {
1644 if multi_index(&mut e, &mut dot_token, float_token)? {
1645 continue;
1646 }
1647 }
1648
1649 let await_token: Option<Token![await]> = input.parse()?;
1650 if let Some(await_token) = await_token {
1651 e = Expr::Await(ExprAwait {
1652 attrs: Vec::new(),
1653 base: Box::new(e),
1654 dot_token,
1655 await_token,
1656 });
1657 continue;
1658 }
1659
1660 let member: Member = input.parse()?;
1661 let turbofish = if member.is_named() && input.peek(Token![::]) {
1662 Some(AngleBracketedGenericArguments::parse_turbofish(input)?)
1663 } else {
1664 None
1665 };
1666
1667 if turbofish.is_some() || input.peek(token::Paren) {
1668 if let Member::Named(method) = member {
1669 let content;
1670 e = Expr::MethodCall(ExprMethodCall {
1671 attrs: Vec::new(),
1672 receiver: Box::new(e),
1673 dot_token,
1674 method,
1675 turbofish,
1676 paren_token: parenthesized!(content in input),
1677 args: content.parse_terminated(Expr::parse, Token![,])?,
1678 });
1679 continue;
1680 }
1681 }
1682
1683 e = Expr::Field(ExprField {
1684 attrs: Vec::new(),
1685 base: Box::new(e),
1686 dot_token,
1687 member,
1688 });
1689 } else if input.peek(token::Bracket) {
1690 let content;
1691 e = Expr::Index(ExprIndex {
1692 attrs: Vec::new(),
1693 expr: Box::new(e),
1694 bracket_token: bracketed!(content in input),
1695 index: content.parse()?,
1696 });
1697 } else if input.peek(Token![?])
1698 && match e {
1699 Expr::Range(_) => false,
1700 _ => true,
1701 }
1702 {
1703 e = Expr::Try(ExprTry {
1704 attrs: Vec::new(),
1705 expr: Box::new(e),
1706 question_token: input.parse()?,
1707 });
1708 } else {
1709 break;
1710 }
1711 }
1712 Ok(e)
1713 }
1714
1715 #[cfg(not(feature = "full"))]
1716 fn trailer_expr(input: ParseStream) -> Result<Expr> {
1717 let mut e = atom_expr(input)?;
1718
1719 loop {
1720 if input.peek(token::Paren) {
1721 let content;
1722 e = Expr::Call(ExprCall {
1723 attrs: Vec::new(),
1724 func: Box::new(e),
1725 paren_token: parenthesized!(content in input),
1726 args: content.parse_terminated(Expr::parse, Token![,])?,
1727 });
1728 } else if input.peek(Token![.])
1729 && !input.peek(Token![..])
1730 && !input.peek2(Token![await])
1731 {
1732 let mut dot_token: Token![.] = input.parse()?;
1733
1734 let float_token: Option<LitFloat> = input.parse()?;
1735 if let Some(float_token) = float_token {
1736 if multi_index(&mut e, &mut dot_token, float_token)? {
1737 continue;
1738 }
1739 }
1740
1741 let member: Member = input.parse()?;
1742 let turbofish = if member.is_named() && input.peek(Token![::]) {
1743 let colon2_token: Token![::] = input.parse()?;
1744 let turbofish =
1745 AngleBracketedGenericArguments::do_parse(Some(colon2_token), input)?;
1746 Some(turbofish)
1747 } else {
1748 None
1749 };
1750
1751 if turbofish.is_some() || input.peek(token::Paren) {
1752 if let Member::Named(method) = member {
1753 let content;
1754 e = Expr::MethodCall(ExprMethodCall {
1755 attrs: Vec::new(),
1756 receiver: Box::new(e),
1757 dot_token,
1758 method,
1759 turbofish,
1760 paren_token: parenthesized!(content in input),
1761 args: content.parse_terminated(Expr::parse, Token![,])?,
1762 });
1763 continue;
1764 }
1765 }
1766
1767 e = Expr::Field(ExprField {
1768 attrs: Vec::new(),
1769 base: Box::new(e),
1770 dot_token,
1771 member,
1772 });
1773 } else if input.peek(token::Bracket) {
1774 let content;
1775 e = Expr::Index(ExprIndex {
1776 attrs: Vec::new(),
1777 expr: Box::new(e),
1778 bracket_token: bracketed!(content in input),
1779 index: content.parse()?,
1780 });
1781 } else {
1782 break;
1783 }
1784 }
1785
1786 Ok(e)
1787 }
1788
1789 #[cfg(feature = "full")]
1792 fn atom_expr(input: ParseStream, allow_struct: AllowStruct) -> Result<Expr> {
1793 if input.peek(token::Group) {
1794 expr_group(input, allow_struct)
1795 } else if input.peek(Lit) {
1796 input.parse().map(Expr::Lit)
1797 } else if input.peek(Token![async])
1798 && (input.peek2(token::Brace) || input.peek2(Token![move]) && input.peek3(token::Brace))
1799 {
1800 input.parse().map(Expr::Async)
1801 } else if input.peek(Token![try]) && input.peek2(token::Brace) {
1802 input.parse().map(Expr::TryBlock)
1803 } else if input.peek(Token![|])
1804 || input.peek(Token![move])
1805 || input.peek(Token![for])
1806 && input.peek2(Token![<])
1807 && (input.peek3(Lifetime) || input.peek3(Token![>]))
1808 || input.peek(Token![const]) && !input.peek2(token::Brace)
1809 || input.peek(Token![static])
1810 || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1811 {
1812 expr_closure(input, allow_struct).map(Expr::Closure)
1813 } else if token::parsing::peek_keyword(input.cursor(), "builtin") && input.peek2(Token![#])
1814 {
1815 expr_builtin(input)
1816 } else if input.peek(Ident)
1817 || input.peek(Token![::])
1818 || input.peek(Token![<])
1819 || input.peek(Token![self])
1820 || input.peek(Token![Self])
1821 || input.peek(Token![super])
1822 || input.peek(Token![crate])
1823 || input.peek(Token![try]) && (input.peek2(Token![!]) || input.peek2(Token![::]))
1824 {
1825 path_or_macro_or_struct(input, allow_struct)
1826 } else if input.peek(token::Paren) {
1827 paren_or_tuple(input)
1828 } else if input.peek(Token![break]) {
1829 expr_break(input, allow_struct).map(Expr::Break)
1830 } else if input.peek(Token![continue]) {
1831 input.parse().map(Expr::Continue)
1832 } else if input.peek(Token![return]) {
1833 input.parse().map(Expr::Return)
1834 } else if input.peek(Token![become]) {
1835 expr_become(input)
1836 } else if input.peek(token::Bracket) {
1837 array_or_repeat(input)
1838 } else if input.peek(Token![let]) {
1839 expr_let(input, allow_struct).map(Expr::Let)
1840 } else if input.peek(Token![if]) {
1841 input.parse().map(Expr::If)
1842 } else if input.peek(Token![while]) {
1843 input.parse().map(Expr::While)
1844 } else if input.peek(Token![for]) {
1845 input.parse().map(Expr::ForLoop)
1846 } else if input.peek(Token![loop]) {
1847 input.parse().map(Expr::Loop)
1848 } else if input.peek(Token![match]) {
1849 input.parse().map(Expr::Match)
1850 } else if input.peek(Token![yield]) {
1851 input.parse().map(Expr::Yield)
1852 } else if input.peek(Token![unsafe]) {
1853 input.parse().map(Expr::Unsafe)
1854 } else if input.peek(Token![const]) {
1855 input.parse().map(Expr::Const)
1856 } else if input.peek(token::Brace) {
1857 input.parse().map(Expr::Block)
1858 } else if input.peek(Token![..]) {
1859 expr_range(input, allow_struct).map(Expr::Range)
1860 } else if input.peek(Token![_]) {
1861 input.parse().map(Expr::Infer)
1862 } else if input.peek(Lifetime) {
1863 atom_labeled(input)
1864 } else {
1865 Err(input.error("expected an expression"))
1866 }
1867 }
1868
1869 #[cfg(feature = "full")]
1870 fn atom_labeled(input: ParseStream) -> Result<Expr> {
1871 let the_label: Label = input.parse()?;
1872 let mut expr = if input.peek(Token![while]) {
1873 Expr::While(input.parse()?)
1874 } else if input.peek(Token![for]) {
1875 Expr::ForLoop(input.parse()?)
1876 } else if input.peek(Token![loop]) {
1877 Expr::Loop(input.parse()?)
1878 } else if input.peek(token::Brace) {
1879 Expr::Block(input.parse()?)
1880 } else {
1881 return Err(input.error("expected loop or block expression"));
1882 };
1883 match &mut expr {
1884 Expr::While(ExprWhile { label, .. })
1885 | Expr::ForLoop(ExprForLoop { label, .. })
1886 | Expr::Loop(ExprLoop { label, .. })
1887 | Expr::Block(ExprBlock { label, .. }) => *label = Some(the_label),
1888 _ => unreachable!(),
1889 }
1890 Ok(expr)
1891 }
1892
1893 #[cfg(not(feature = "full"))]
1894 fn atom_expr(input: ParseStream) -> Result<Expr> {
1895 if input.peek(token::Group) {
1896 expr_group(input)
1897 } else if input.peek(Lit) {
1898 input.parse().map(Expr::Lit)
1899 } else if input.peek(token::Paren) {
1900 paren_or_tuple(input)
1901 } else if input.peek(Ident)
1902 || input.peek(Token![::])
1903 || input.peek(Token![<])
1904 || input.peek(Token![self])
1905 || input.peek(Token![Self])
1906 || input.peek(Token![super])
1907 || input.peek(Token![crate])
1908 {
1909 path_or_macro_or_struct(input)
1910 } else if input.is_empty() {
1911 Err(input.error("expected an expression"))
1912 } else {
1913 if input.peek(token::Brace) {
1914 let scan = input.fork();
1915 let content;
1916 braced!(content in scan);
1917 if content.parse::<Expr>().is_ok() && content.is_empty() {
1918 let expr_block = verbatim::between(input, &scan);
1919 input.advance_to(&scan);
1920 return Ok(Expr::Verbatim(expr_block));
1921 }
1922 }
1923 Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
1924 }
1925 }
1926
1927 #[cfg(feature = "full")]
1928 fn expr_builtin(input: ParseStream) -> Result<Expr> {
1929 let begin = input.fork();
1930
1931 token::parsing::keyword(input, "builtin")?;
1932 input.parse::<Token![#]>()?;
1933 input.parse::<Ident>()?;
1934
1935 let args;
1936 parenthesized!(args in input);
1937 args.parse::<TokenStream>()?;
1938
1939 Ok(Expr::Verbatim(verbatim::between(&begin, input)))
1940 }
1941
1942 fn path_or_macro_or_struct(
1943 input: ParseStream,
1944 #[cfg(feature = "full")] allow_struct: AllowStruct,
1945 ) -> Result<Expr> {
1946 let expr_style = true;
1947 let (qself, path) = path::parsing::qpath(input, expr_style)?;
1948 rest_of_path_or_macro_or_struct(
1949 qself,
1950 path,
1951 input,
1952 #[cfg(feature = "full")]
1953 allow_struct,
1954 )
1955 }
1956
1957 fn rest_of_path_or_macro_or_struct(
1958 qself: Option<QSelf>,
1959 path: Path,
1960 input: ParseStream,
1961 #[cfg(feature = "full")] allow_struct: AllowStruct,
1962 ) -> Result<Expr> {
1963 if qself.is_none()
1964 && input.peek(Token![!])
1965 && !input.peek(Token![!=])
1966 && path.is_mod_style()
1967 {
1968 let bang_token: Token![!] = input.parse()?;
1969 let (delimiter, tokens) = mac::parse_delimiter(input)?;
1970 return Ok(Expr::Macro(ExprMacro {
1971 attrs: Vec::new(),
1972 mac: Macro {
1973 path,
1974 bang_token,
1975 delimiter,
1976 tokens,
1977 },
1978 }));
1979 }
1980
1981 #[cfg(not(feature = "full"))]
1982 let allow_struct = (true,);
1983 if allow_struct.0 && input.peek(token::Brace) {
1984 return expr_struct_helper(input, qself, path).map(Expr::Struct);
1985 }
1986
1987 Ok(Expr::Path(ExprPath {
1988 attrs: Vec::new(),
1989 qself,
1990 path,
1991 }))
1992 }
1993
1994 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1995 impl Parse for ExprMacro {
1996 fn parse(input: ParseStream) -> Result<Self> {
1997 Ok(ExprMacro {
1998 attrs: Vec::new(),
1999 mac: input.parse()?,
2000 })
2001 }
2002 }
2003
2004 fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
2005 let content;
2006 let paren_token = parenthesized!(content in input);
2007 if content.is_empty() {
2008 return Ok(Expr::Tuple(ExprTuple {
2009 attrs: Vec::new(),
2010 paren_token,
2011 elems: Punctuated::new(),
2012 }));
2013 }
2014
2015 let first: Expr = content.parse()?;
2016 if content.is_empty() {
2017 return Ok(Expr::Paren(ExprParen {
2018 attrs: Vec::new(),
2019 paren_token,
2020 expr: Box::new(first),
2021 }));
2022 }
2023
2024 let mut elems = Punctuated::new();
2025 elems.push_value(first);
2026 while !content.is_empty() {
2027 let punct = content.parse()?;
2028 elems.push_punct(punct);
2029 if content.is_empty() {
2030 break;
2031 }
2032 let value = content.parse()?;
2033 elems.push_value(value);
2034 }
2035 Ok(Expr::Tuple(ExprTuple {
2036 attrs: Vec::new(),
2037 paren_token,
2038 elems,
2039 }))
2040 }
2041
2042 #[cfg(feature = "full")]
2043 fn array_or_repeat(input: ParseStream) -> Result<Expr> {
2044 let content;
2045 let bracket_token = bracketed!(content in input);
2046 if content.is_empty() {
2047 return Ok(Expr::Array(ExprArray {
2048 attrs: Vec::new(),
2049 bracket_token,
2050 elems: Punctuated::new(),
2051 }));
2052 }
2053
2054 let first: Expr = content.parse()?;
2055 if content.is_empty() || content.peek(Token![,]) {
2056 let mut elems = Punctuated::new();
2057 elems.push_value(first);
2058 while !content.is_empty() {
2059 let punct = content.parse()?;
2060 elems.push_punct(punct);
2061 if content.is_empty() {
2062 break;
2063 }
2064 let value = content.parse()?;
2065 elems.push_value(value);
2066 }
2067 Ok(Expr::Array(ExprArray {
2068 attrs: Vec::new(),
2069 bracket_token,
2070 elems,
2071 }))
2072 } else if content.peek(Token![;]) {
2073 let semi_token: Token![;] = content.parse()?;
2074 let len: Expr = content.parse()?;
2075 Ok(Expr::Repeat(ExprRepeat {
2076 attrs: Vec::new(),
2077 bracket_token,
2078 expr: Box::new(first),
2079 semi_token,
2080 len: Box::new(len),
2081 }))
2082 } else {
2083 Err(content.error("expected `,` or `;`"))
2084 }
2085 }
2086
2087 #[cfg(feature = "full")]
2088 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2089 impl Parse for ExprArray {
2090 fn parse(input: ParseStream) -> Result<Self> {
2091 let content;
2092 let bracket_token = bracketed!(content in input);
2093 let mut elems = Punctuated::new();
2094
2095 while !content.is_empty() {
2096 let first: Expr = content.parse()?;
2097 elems.push_value(first);
2098 if content.is_empty() {
2099 break;
2100 }
2101 let punct = content.parse()?;
2102 elems.push_punct(punct);
2103 }
2104
2105 Ok(ExprArray {
2106 attrs: Vec::new(),
2107 bracket_token,
2108 elems,
2109 })
2110 }
2111 }
2112
2113 #[cfg(feature = "full")]
2114 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2115 impl Parse for ExprRepeat {
2116 fn parse(input: ParseStream) -> Result<Self> {
2117 let content;
2118 Ok(ExprRepeat {
2119 bracket_token: bracketed!(content in input),
2120 attrs: Vec::new(),
2121 expr: content.parse()?,
2122 semi_token: content.parse()?,
2123 len: content.parse()?,
2124 })
2125 }
2126 }
2127
2128 #[cfg(feature = "full")]
2129 fn continue_parsing_early(mut expr: &Expr) -> bool {
2130 while let Expr::Group(group) = expr {
2131 expr = &group.expr;
2132 }
2133 match expr {
2134 Expr::If(_)
2135 | Expr::While(_)
2136 | Expr::ForLoop(_)
2137 | Expr::Loop(_)
2138 | Expr::Match(_)
2139 | Expr::TryBlock(_)
2140 | Expr::Unsafe(_)
2141 | Expr::Const(_)
2142 | Expr::Block(_) => false,
2143 _ => true,
2144 }
2145 }
2146
2147 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2148 impl Parse for ExprLit {
2149 fn parse(input: ParseStream) -> Result<Self> {
2150 Ok(ExprLit {
2151 attrs: Vec::new(),
2152 lit: input.parse()?,
2153 })
2154 }
2155 }
2156
2157 fn expr_group(
2158 input: ParseStream,
2159 #[cfg(feature = "full")] allow_struct: AllowStruct,
2160 ) -> Result<Expr> {
2161 let group = crate::group::parse_group(input)?;
2162 let mut inner: Expr = group.content.parse()?;
2163
2164 match inner {
2165 Expr::Path(mut expr) if expr.attrs.is_empty() => {
2166 let grouped_len = expr.path.segments.len();
2167 Path::parse_rest(input, &mut expr.path, true)?;
2168 match rest_of_path_or_macro_or_struct(
2169 expr.qself,
2170 expr.path,
2171 input,
2172 #[cfg(feature = "full")]
2173 allow_struct,
2174 )? {
2175 Expr::Path(expr) if expr.path.segments.len() == grouped_len => {
2176 inner = Expr::Path(expr);
2177 }
2178 extended => return Ok(extended),
2179 }
2180 }
2181 _ => {}
2182 }
2183
2184 Ok(Expr::Group(ExprGroup {
2185 attrs: Vec::new(),
2186 group_token: group.token,
2187 expr: Box::new(inner),
2188 }))
2189 }
2190
2191 #[cfg(feature = "full")]
2192 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2193 impl Parse for ExprParen {
2194 fn parse(input: ParseStream) -> Result<Self> {
2195 let content;
2196 Ok(ExprParen {
2197 attrs: Vec::new(),
2198 paren_token: parenthesized!(content in input),
2199 expr: content.parse()?,
2200 })
2201 }
2202 }
2203
2204 #[cfg(feature = "full")]
2205 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2206 impl Parse for ExprLet {
2207 fn parse(input: ParseStream) -> Result<Self> {
2208 let allow_struct = AllowStruct(true);
2209 expr_let(input, allow_struct)
2210 }
2211 }
2212
2213 #[cfg(feature = "full")]
2214 fn expr_let(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprLet> {
2215 Ok(ExprLet {
2216 attrs: Vec::new(),
2217 let_token: input.parse()?,
2218 pat: Box::new(Pat::parse_multi_with_leading_vert(input)?),
2219 eq_token: input.parse()?,
2220 expr: Box::new({
2221 let lhs = unary_expr(input, allow_struct)?;
2222 parse_expr(input, lhs, allow_struct, Precedence::Compare)?
2223 }),
2224 })
2225 }
2226
2227 #[cfg(feature = "full")]
2228 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2229 impl Parse for ExprIf {
2230 fn parse(input: ParseStream) -> Result<Self> {
2231 let attrs = input.call(Attribute::parse_outer)?;
2232
2233 let mut clauses = Vec::new();
2234 let mut expr;
2235 loop {
2236 let if_token: Token![if] = input.parse()?;
2237 let cond = input.call(Expr::parse_without_eager_brace)?;
2238 let then_branch: Block = input.parse()?;
2239
2240 expr = ExprIf {
2241 attrs: Vec::new(),
2242 if_token,
2243 cond: Box::new(cond),
2244 then_branch,
2245 else_branch: None,
2246 };
2247
2248 if !input.peek(Token![else]) {
2249 break;
2250 }
2251
2252 let else_token: Token![else] = input.parse()?;
2253 let lookahead = input.lookahead1();
2254 if lookahead.peek(Token![if]) {
2255 expr.else_branch = Some((else_token, Box::new(Expr::PLACEHOLDER)));
2256 clauses.push(expr);
2257 } else if lookahead.peek(token::Brace) {
2258 expr.else_branch = Some((
2259 else_token,
2260 Box::new(Expr::Block(ExprBlock {
2261 attrs: Vec::new(),
2262 label: None,
2263 block: input.parse()?,
2264 })),
2265 ));
2266 break;
2267 } else {
2268 return Err(lookahead.error());
2269 }
2270 }
2271
2272 while let Some(mut prev) = clauses.pop() {
2273 *prev.else_branch.as_mut().unwrap().1 = Expr::If(expr);
2274 expr = prev;
2275 }
2276 expr.attrs = attrs;
2277 Ok(expr)
2278 }
2279 }
2280
2281 #[cfg(feature = "full")]
2282 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2283 impl Parse for ExprInfer {
2284 fn parse(input: ParseStream) -> Result<Self> {
2285 Ok(ExprInfer {
2286 attrs: input.call(Attribute::parse_outer)?,
2287 underscore_token: input.parse()?,
2288 })
2289 }
2290 }
2291
2292 #[cfg(feature = "full")]
2293 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2294 impl Parse for ExprForLoop {
2295 fn parse(input: ParseStream) -> Result<Self> {
2296 let mut attrs = input.call(Attribute::parse_outer)?;
2297 let label: Option<Label> = input.parse()?;
2298 let for_token: Token![for] = input.parse()?;
2299
2300 let pat = Pat::parse_multi_with_leading_vert(input)?;
2301
2302 let in_token: Token![in] = input.parse()?;
2303 let expr: Expr = input.call(Expr::parse_without_eager_brace)?;
2304
2305 let content;
2306 let brace_token = braced!(content in input);
2307 attr::parsing::parse_inner(&content, &mut attrs)?;
2308 let stmts = content.call(Block::parse_within)?;
2309
2310 Ok(ExprForLoop {
2311 attrs,
2312 label,
2313 for_token,
2314 pat: Box::new(pat),
2315 in_token,
2316 expr: Box::new(expr),
2317 body: Block { brace_token, stmts },
2318 })
2319 }
2320 }
2321
2322 #[cfg(feature = "full")]
2323 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2324 impl Parse for ExprLoop {
2325 fn parse(input: ParseStream) -> Result<Self> {
2326 let mut attrs = input.call(Attribute::parse_outer)?;
2327 let label: Option<Label> = input.parse()?;
2328 let loop_token: Token![loop] = input.parse()?;
2329
2330 let content;
2331 let brace_token = braced!(content in input);
2332 attr::parsing::parse_inner(&content, &mut attrs)?;
2333 let stmts = content.call(Block::parse_within)?;
2334
2335 Ok(ExprLoop {
2336 attrs,
2337 label,
2338 loop_token,
2339 body: Block { brace_token, stmts },
2340 })
2341 }
2342 }
2343
2344 #[cfg(feature = "full")]
2345 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2346 impl Parse for ExprMatch {
2347 fn parse(input: ParseStream) -> Result<Self> {
2348 let mut attrs = input.call(Attribute::parse_outer)?;
2349 let match_token: Token![match] = input.parse()?;
2350 let expr = Expr::parse_without_eager_brace(input)?;
2351
2352 let content;
2353 let brace_token = braced!(content in input);
2354 attr::parsing::parse_inner(&content, &mut attrs)?;
2355
2356 let arms = Arm::parse_multiple(&content)?;
2357
2358 Ok(ExprMatch {
2359 attrs,
2360 match_token,
2361 expr: Box::new(expr),
2362 brace_token,
2363 arms,
2364 })
2365 }
2366 }
2367
2368 macro_rules! impl_by_parsing_expr {
2369 (
2370 $(
2371 $expr_type:ty, $variant:ident, $msg:expr,
2372 )*
2373 ) => {
2374 $(
2375 #[cfg(all(feature = "full", feature = "printing"))]
2376 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2377 impl Parse for $expr_type {
2378 fn parse(input: ParseStream) -> Result<Self> {
2379 let mut expr: Expr = input.parse()?;
2380 loop {
2381 match expr {
2382 Expr::$variant(inner) => return Ok(inner),
2383 Expr::Group(next) => expr = *next.expr,
2384 _ => return Err(Error::new_spanned(expr, $msg)),
2385 }
2386 }
2387 }
2388 }
2389 )*
2390 };
2391 }
2392
2393 impl_by_parsing_expr! {
2394 ExprAssign, Assign, "expected assignment expression",
2395 ExprAwait, Await, "expected await expression",
2396 ExprBinary, Binary, "expected binary operation",
2397 ExprCall, Call, "expected function call expression",
2398 ExprCast, Cast, "expected cast expression",
2399 ExprField, Field, "expected struct field access",
2400 ExprIndex, Index, "expected indexing expression",
2401 ExprMethodCall, MethodCall, "expected method call expression",
2402 ExprRange, Range, "expected range expression",
2403 ExprTry, Try, "expected try expression",
2404 ExprTuple, Tuple, "expected tuple expression",
2405 }
2406
2407 #[cfg(feature = "full")]
2408 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2409 impl Parse for ExprUnary {
2410 fn parse(input: ParseStream) -> Result<Self> {
2411 let attrs = Vec::new();
2412 let allow_struct = AllowStruct(true);
2413 expr_unary(input, attrs, allow_struct)
2414 }
2415 }
2416
2417 #[cfg(feature = "full")]
2418 fn expr_unary(
2419 input: ParseStream,
2420 attrs: Vec<Attribute>,
2421 allow_struct: AllowStruct,
2422 ) -> Result<ExprUnary> {
2423 Ok(ExprUnary {
2424 attrs,
2425 op: input.parse()?,
2426 expr: Box::new(unary_expr(input, allow_struct)?),
2427 })
2428 }
2429
2430 #[cfg(feature = "full")]
2431 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2432 impl Parse for ExprClosure {
2433 fn parse(input: ParseStream) -> Result<Self> {
2434 let allow_struct = AllowStruct(true);
2435 expr_closure(input, allow_struct)
2436 }
2437 }
2438
2439 #[cfg(feature = "full")]
2440 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2441 impl Parse for ExprRawAddr {
2442 fn parse(input: ParseStream) -> Result<Self> {
2443 let allow_struct = AllowStruct(true);
2444 Ok(ExprRawAddr {
2445 attrs: Vec::new(),
2446 and_token: input.parse()?,
2447 raw: input.parse()?,
2448 mutability: input.parse()?,
2449 expr: Box::new(unary_expr(input, allow_struct)?),
2450 })
2451 }
2452 }
2453
2454 #[cfg(feature = "full")]
2455 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2456 impl Parse for ExprReference {
2457 fn parse(input: ParseStream) -> Result<Self> {
2458 let allow_struct = AllowStruct(true);
2459 Ok(ExprReference {
2460 attrs: Vec::new(),
2461 and_token: input.parse()?,
2462 mutability: input.parse()?,
2463 expr: Box::new(unary_expr(input, allow_struct)?),
2464 })
2465 }
2466 }
2467
2468 #[cfg(feature = "full")]
2469 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2470 impl Parse for ExprBreak {
2471 fn parse(input: ParseStream) -> Result<Self> {
2472 let allow_struct = AllowStruct(true);
2473 expr_break(input, allow_struct)
2474 }
2475 }
2476
2477 #[cfg(feature = "full")]
2478 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2479 impl Parse for ExprReturn {
2480 fn parse(input: ParseStream) -> Result<Self> {
2481 Ok(ExprReturn {
2482 attrs: Vec::new(),
2483 return_token: input.parse()?,
2484 expr: {
2485 if Expr::peek(input) {
2486 Some(input.parse()?)
2487 } else {
2488 None
2489 }
2490 },
2491 })
2492 }
2493 }
2494
2495 #[cfg(feature = "full")]
2496 fn expr_become(input: ParseStream) -> Result<Expr> {
2497 let begin = input.fork();
2498 input.parse::<Token![become]>()?;
2499 input.parse::<Expr>()?;
2500 Ok(Expr::Verbatim(verbatim::between(&begin, input)))
2501 }
2502
2503 #[cfg(feature = "full")]
2504 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2505 impl Parse for ExprTryBlock {
2506 fn parse(input: ParseStream) -> Result<Self> {
2507 Ok(ExprTryBlock {
2508 attrs: Vec::new(),
2509 try_token: input.parse()?,
2510 block: input.parse()?,
2511 })
2512 }
2513 }
2514
2515 #[cfg(feature = "full")]
2516 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2517 impl Parse for ExprYield {
2518 fn parse(input: ParseStream) -> Result<Self> {
2519 Ok(ExprYield {
2520 attrs: Vec::new(),
2521 yield_token: input.parse()?,
2522 expr: {
2523 if Expr::peek(input) {
2524 Some(input.parse()?)
2525 } else {
2526 None
2527 }
2528 },
2529 })
2530 }
2531 }
2532
2533 #[cfg(feature = "full")]
2534 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
2535 let lifetimes: Option<BoundLifetimes> = input.parse()?;
2536 let constness: Option<Token![const]> = input.parse()?;
2537 let movability: Option<Token![static]> = input.parse()?;
2538 let asyncness: Option<Token![async]> = input.parse()?;
2539 let capture: Option<Token![move]> = input.parse()?;
2540 let or1_token: Token![|] = input.parse()?;
2541
2542 let mut inputs = Punctuated::new();
2543 loop {
2544 if input.peek(Token![|]) {
2545 break;
2546 }
2547 let value = closure_arg(input)?;
2548 inputs.push_value(value);
2549 if input.peek(Token![|]) {
2550 break;
2551 }
2552 let punct: Token![,] = input.parse()?;
2553 inputs.push_punct(punct);
2554 }
2555
2556 let or2_token: Token![|] = input.parse()?;
2557
2558 let (output, body) = if input.peek(Token![->]) {
2559 let arrow_token: Token![->] = input.parse()?;
2560 let ty: Type = input.parse()?;
2561 let body: Block = input.parse()?;
2562 let output = ReturnType::Type(arrow_token, Box::new(ty));
2563 let block = Expr::Block(ExprBlock {
2564 attrs: Vec::new(),
2565 label: None,
2566 block: body,
2567 });
2568 (output, block)
2569 } else {
2570 let body = ambiguous_expr(input, allow_struct)?;
2571 (ReturnType::Default, body)
2572 };
2573
2574 Ok(ExprClosure {
2575 attrs: Vec::new(),
2576 lifetimes,
2577 constness,
2578 movability,
2579 asyncness,
2580 capture,
2581 or1_token,
2582 inputs,
2583 or2_token,
2584 output,
2585 body: Box::new(body),
2586 })
2587 }
2588
2589 #[cfg(feature = "full")]
2590 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2591 impl Parse for ExprAsync {
2592 fn parse(input: ParseStream) -> Result<Self> {
2593 Ok(ExprAsync {
2594 attrs: Vec::new(),
2595 async_token: input.parse()?,
2596 capture: input.parse()?,
2597 block: input.parse()?,
2598 })
2599 }
2600 }
2601
2602 #[cfg(feature = "full")]
2603 fn closure_arg(input: ParseStream) -> Result<Pat> {
2604 let attrs = input.call(Attribute::parse_outer)?;
2605 let mut pat = Pat::parse_single(input)?;
2606
2607 if input.peek(Token![:]) {
2608 Ok(Pat::Type(PatType {
2609 attrs,
2610 pat: Box::new(pat),
2611 colon_token: input.parse()?,
2612 ty: input.parse()?,
2613 }))
2614 } else {
2615 match &mut pat {
2616 Pat::Const(pat) => pat.attrs = attrs,
2617 Pat::Ident(pat) => pat.attrs = attrs,
2618 Pat::Lit(pat) => pat.attrs = attrs,
2619 Pat::Macro(pat) => pat.attrs = attrs,
2620 Pat::Or(pat) => pat.attrs = attrs,
2621 Pat::Paren(pat) => pat.attrs = attrs,
2622 Pat::Path(pat) => pat.attrs = attrs,
2623 Pat::Range(pat) => pat.attrs = attrs,
2624 Pat::Reference(pat) => pat.attrs = attrs,
2625 Pat::Rest(pat) => pat.attrs = attrs,
2626 Pat::Slice(pat) => pat.attrs = attrs,
2627 Pat::Struct(pat) => pat.attrs = attrs,
2628 Pat::Tuple(pat) => pat.attrs = attrs,
2629 Pat::TupleStruct(pat) => pat.attrs = attrs,
2630 Pat::Type(_) => unreachable!(),
2631 Pat::Verbatim(_) => {}
2632 Pat::Wild(pat) => pat.attrs = attrs,
2633 }
2634 Ok(pat)
2635 }
2636 }
2637
2638 #[cfg(feature = "full")]
2639 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2640 impl Parse for ExprWhile {
2641 fn parse(input: ParseStream) -> Result<Self> {
2642 let mut attrs = input.call(Attribute::parse_outer)?;
2643 let label: Option<Label> = input.parse()?;
2644 let while_token: Token![while] = input.parse()?;
2645 let cond = Expr::parse_without_eager_brace(input)?;
2646
2647 let content;
2648 let brace_token = braced!(content in input);
2649 attr::parsing::parse_inner(&content, &mut attrs)?;
2650 let stmts = content.call(Block::parse_within)?;
2651
2652 Ok(ExprWhile {
2653 attrs,
2654 label,
2655 while_token,
2656 cond: Box::new(cond),
2657 body: Block { brace_token, stmts },
2658 })
2659 }
2660 }
2661
2662 #[cfg(feature = "full")]
2663 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2664 impl Parse for ExprConst {
2665 fn parse(input: ParseStream) -> Result<Self> {
2666 let const_token: Token![const] = input.parse()?;
2667
2668 let content;
2669 let brace_token = braced!(content in input);
2670 let inner_attrs = content.call(Attribute::parse_inner)?;
2671 let stmts = content.call(Block::parse_within)?;
2672
2673 Ok(ExprConst {
2674 attrs: inner_attrs,
2675 const_token,
2676 block: Block { brace_token, stmts },
2677 })
2678 }
2679 }
2680
2681 #[cfg(feature = "full")]
2682 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2683 impl Parse for Label {
2684 fn parse(input: ParseStream) -> Result<Self> {
2685 Ok(Label {
2686 name: input.parse()?,
2687 colon_token: input.parse()?,
2688 })
2689 }
2690 }
2691
2692 #[cfg(feature = "full")]
2693 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2694 impl Parse for Option<Label> {
2695 fn parse(input: ParseStream) -> Result<Self> {
2696 if input.peek(Lifetime) {
2697 input.parse().map(Some)
2698 } else {
2699 Ok(None)
2700 }
2701 }
2702 }
2703
2704 #[cfg(feature = "full")]
2705 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2706 impl Parse for ExprContinue {
2707 fn parse(input: ParseStream) -> Result<Self> {
2708 Ok(ExprContinue {
2709 attrs: Vec::new(),
2710 continue_token: input.parse()?,
2711 label: input.parse()?,
2712 })
2713 }
2714 }
2715
2716 #[cfg(feature = "full")]
2717 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2718 let break_token: Token![break] = input.parse()?;
2719
2720 let ahead = input.fork();
2721 let label: Option<Lifetime> = ahead.parse()?;
2722 if label.is_some() && ahead.peek(Token![:]) {
2723 let _: Expr = input.parse()?;
2726 let start_span = label.unwrap().apostrophe;
2727 let end_span = input.cursor().prev_span();
2728 return Err(crate::error::new2(
2729 start_span,
2730 end_span,
2731 "parentheses required",
2732 ));
2733 }
2734
2735 input.advance_to(&ahead);
2736 let expr = if Expr::peek(input) && (allow_struct.0 || !input.peek(token::Brace)) {
2737 Some(input.parse()?)
2738 } else {
2739 None
2740 };
2741
2742 Ok(ExprBreak {
2743 attrs: Vec::new(),
2744 break_token,
2745 label,
2746 expr,
2747 })
2748 }
2749
2750 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2751 impl Parse for FieldValue {
2752 fn parse(input: ParseStream) -> Result<Self> {
2753 let attrs = input.call(Attribute::parse_outer)?;
2754 let member: Member = input.parse()?;
2755 let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
2756 let colon_token: Token![:] = input.parse()?;
2757 let value: Expr = input.parse()?;
2758 (Some(colon_token), value)
2759 } else if let Member::Named(ident) = &member {
2760 let value = Expr::Path(ExprPath {
2761 attrs: Vec::new(),
2762 qself: None,
2763 path: Path::from(ident.clone()),
2764 });
2765 (None, value)
2766 } else {
2767 unreachable!()
2768 };
2769
2770 Ok(FieldValue {
2771 attrs,
2772 member,
2773 colon_token,
2774 expr: value,
2775 })
2776 }
2777 }
2778
2779 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2780 impl Parse for ExprStruct {
2781 fn parse(input: ParseStream) -> Result<Self> {
2782 let expr_style = true;
2783 let (qself, path) = path::parsing::qpath(input, expr_style)?;
2784 expr_struct_helper(input, qself, path)
2785 }
2786 }
2787
2788 fn expr_struct_helper(
2789 input: ParseStream,
2790 qself: Option<QSelf>,
2791 path: Path,
2792 ) -> Result<ExprStruct> {
2793 let content;
2794 let brace_token = braced!(content in input);
2795
2796 let mut fields = Punctuated::new();
2797 while !content.is_empty() {
2798 if content.peek(Token![..]) {
2799 return Ok(ExprStruct {
2800 attrs: Vec::new(),
2801 qself,
2802 path,
2803 brace_token,
2804 fields,
2805 dot2_token: Some(content.parse()?),
2806 rest: if content.is_empty() {
2807 None
2808 } else {
2809 Some(Box::new(content.parse()?))
2810 },
2811 });
2812 }
2813
2814 fields.push(content.parse()?);
2815 if content.is_empty() {
2816 break;
2817 }
2818 let punct: Token![,] = content.parse()?;
2819 fields.push_punct(punct);
2820 }
2821
2822 Ok(ExprStruct {
2823 attrs: Vec::new(),
2824 qself,
2825 path,
2826 brace_token,
2827 fields,
2828 dot2_token: None,
2829 rest: None,
2830 })
2831 }
2832
2833 #[cfg(feature = "full")]
2834 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2835 impl Parse for ExprUnsafe {
2836 fn parse(input: ParseStream) -> Result<Self> {
2837 let unsafe_token: Token![unsafe] = input.parse()?;
2838
2839 let content;
2840 let brace_token = braced!(content in input);
2841 let inner_attrs = content.call(Attribute::parse_inner)?;
2842 let stmts = content.call(Block::parse_within)?;
2843
2844 Ok(ExprUnsafe {
2845 attrs: inner_attrs,
2846 unsafe_token,
2847 block: Block { brace_token, stmts },
2848 })
2849 }
2850 }
2851
2852 #[cfg(feature = "full")]
2853 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2854 impl Parse for ExprBlock {
2855 fn parse(input: ParseStream) -> Result<Self> {
2856 let mut attrs = input.call(Attribute::parse_outer)?;
2857 let label: Option<Label> = input.parse()?;
2858
2859 let content;
2860 let brace_token = braced!(content in input);
2861 attr::parsing::parse_inner(&content, &mut attrs)?;
2862 let stmts = content.call(Block::parse_within)?;
2863
2864 Ok(ExprBlock {
2865 attrs,
2866 label,
2867 block: Block { brace_token, stmts },
2868 })
2869 }
2870 }
2871
2872 #[cfg(feature = "full")]
2873 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2874 let limits: RangeLimits = input.parse()?;
2875 let end = parse_range_end(input, &limits, allow_struct)?;
2876 Ok(ExprRange {
2877 attrs: Vec::new(),
2878 start: None,
2879 limits,
2880 end,
2881 })
2882 }
2883
2884 #[cfg(feature = "full")]
2885 fn parse_range_end(
2886 input: ParseStream,
2887 limits: &RangeLimits,
2888 allow_struct: AllowStruct,
2889 ) -> Result<Option<Box<Expr>>> {
2890 if matches!(limits, RangeLimits::HalfOpen(_))
2891 && (input.is_empty()
2892 || input.peek(Token![,])
2893 || input.peek(Token![;])
2894 || input.peek(Token![.]) && !input.peek(Token![..])
2895 || input.peek(Token![?])
2896 || input.peek(Token![=>])
2897 || !allow_struct.0 && input.peek(token::Brace)
2898 || input.peek(Token![=])
2899 || input.peek(Token![+])
2900 || input.peek(Token![/])
2901 || input.peek(Token![%])
2902 || input.peek(Token![^])
2903 || input.peek(Token![>])
2904 || input.peek(Token![<=])
2905 || input.peek(Token![!=])
2906 || input.peek(Token![-=])
2907 || input.peek(Token![*=])
2908 || input.peek(Token![&=])
2909 || input.peek(Token![|=])
2910 || input.peek(Token![<<=])
2911 || input.peek(Token![as]))
2912 {
2913 Ok(None)
2914 } else {
2915 let end = parse_binop_rhs(input, allow_struct, Precedence::Range)?;
2916 Ok(Some(end))
2917 }
2918 }
2919
2920 #[cfg(feature = "full")]
2921 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2922 impl Parse for RangeLimits {
2923 fn parse(input: ParseStream) -> Result<Self> {
2924 let lookahead = input.lookahead1();
2925 let dot_dot = lookahead.peek(Token![..]);
2926 let dot_dot_eq = dot_dot && lookahead.peek(Token![..=]);
2927 let dot_dot_dot = dot_dot && input.peek(Token![...]);
2928 if dot_dot_eq {
2929 input.parse().map(RangeLimits::Closed)
2930 } else if dot_dot && !dot_dot_dot {
2931 input.parse().map(RangeLimits::HalfOpen)
2932 } else {
2933 Err(lookahead.error())
2934 }
2935 }
2936 }
2937
2938 #[cfg(feature = "full")]
2939 impl RangeLimits {
2940 pub(crate) fn parse_obsolete(input: ParseStream) -> Result<Self> {
2941 let lookahead = input.lookahead1();
2942 let dot_dot = lookahead.peek(Token![..]);
2943 let dot_dot_eq = dot_dot && lookahead.peek(Token![..=]);
2944 let dot_dot_dot = dot_dot && input.peek(Token![...]);
2945 if dot_dot_eq {
2946 input.parse().map(RangeLimits::Closed)
2947 } else if dot_dot_dot {
2948 let dot3: Token![...] = input.parse()?;
2949 Ok(RangeLimits::Closed(Token))
2950 } else if dot_dot {
2951 input.parse().map(RangeLimits::HalfOpen)
2952 } else {
2953 Err(lookahead.error())
2954 }
2955 }
2956 }
2957
2958 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2959 impl Parse for ExprPath {
2960 fn parse(input: ParseStream) -> Result<Self> {
2961 #[cfg(not(feature = "full"))]
2962 let attrs = Vec::new();
2963 #[cfg(feature = "full")]
2964 let attrs = input.call(Attribute::parse_outer)?;
2965
2966 let expr_style = true;
2967 let (qself, path) = path::parsing::qpath(input, expr_style)?;
2968
2969 Ok(ExprPath { attrs, qself, path })
2970 }
2971 }
2972
2973 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2974 impl Parse for Member {
2975 fn parse(input: ParseStream) -> Result<Self> {
2976 if input.peek(Ident) {
2977 input.parse().map(Member::Named)
2978 } else if input.peek(LitInt) {
2979 input.parse().map(Member::Unnamed)
2980 } else {
2981 Err(input.error("expected identifier or integer"))
2982 }
2983 }
2984 }
2985
2986 #[cfg(feature = "full")]
2987 impl Arm {
2988 pub(crate) fn parse_multiple(input: ParseStream) -> Result<Vec<Self>> {
2989 let mut arms = Vec::new();
2990 while !input.is_empty() {
2991 arms.push(input.call(Arm::parse)?);
2992 }
2993 Ok(arms)
2994 }
2995 }
2996
2997 #[cfg(feature = "full")]
2998 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2999 impl Parse for Arm {
3000 fn parse(input: ParseStream) -> Result<Arm> {
3001 let requires_comma;
3002 Ok(Arm {
3003 attrs: input.call(Attribute::parse_outer)?,
3004 pat: Pat::parse_multi_with_leading_vert(input)?,
3005 guard: {
3006 if input.peek(Token![if]) {
3007 let if_token: Token![if] = input.parse()?;
3008 let guard: Expr = input.parse()?;
3009 Some((if_token, Box::new(guard)))
3010 } else {
3011 None
3012 }
3013 },
3014 fat_arrow_token: input.parse()?,
3015 body: {
3016 let body = Expr::parse_with_earlier_boundary_rule(input)?;
3017 requires_comma = classify::requires_comma_to_be_match_arm(&body);
3018 Box::new(body)
3019 },
3020 comma: {
3021 if requires_comma && !input.is_empty() {
3022 Some(input.parse()?)
3023 } else {
3024 input.parse()?
3025 }
3026 },
3027 })
3028 }
3029 }
3030
3031 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3032 impl Parse for Index {
3033 fn parse(input: ParseStream) -> Result<Self> {
3034 let lit: LitInt = input.parse()?;
3035 if lit.suffix().is_empty() {
3036 Ok(Index {
3037 index: lit
3038 .base10_digits()
3039 .parse()
3040 .map_err(|err| Error::new(lit.span(), err))?,
3041 span: lit.span(),
3042 })
3043 } else {
3044 Err(Error::new(lit.span(), "expected unsuffixed integer"))
3045 }
3046 }
3047 }
3048
3049 fn multi_index(e: &mut Expr, dot_token: &mut Token![.], float: LitFloat) -> Result<bool> {
3050 let float_token = float.token();
3051 let float_span = float_token.span();
3052 let mut float_repr = float_token.to_string();
3053 let trailing_dot = float_repr.ends_with('.');
3054 if trailing_dot {
3055 float_repr.truncate(float_repr.len() - 1);
3056 }
3057
3058 let mut offset = 0;
3059 for part in float_repr.split('.') {
3060 let mut index: Index =
3061 crate::parse_str(part).map_err(|err| Error::new(float_span, err))?;
3062 let part_end = offset + part.len();
3063 index.span = float_token.subspan(offset..part_end).unwrap_or(float_span);
3064
3065 let base = mem::replace(e, Expr::PLACEHOLDER);
3066 *e = Expr::Field(ExprField {
3067 attrs: Vec::new(),
3068 base: Box::new(base),
3069 dot_token: Token,
3070 member: Member::Unnamed(index),
3071 });
3072
3073 let dot_span = float_token
3074 .subspan(part_end..part_end + 1)
3075 .unwrap_or(float_span);
3076 *dot_token = Token;
3077 offset = part_end + 1;
3078 }
3079
3080 Ok(!trailing_dot)
3081 }
3082
3083 #[cfg(feature = "full")]
3084 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3085 impl Parse for PointerMutability {
3086 fn parse(input: ParseStream) -> Result<Self> {
3087 let lookahead = input.lookahead1();
3088 if lookahead.peek(Token![const]) {
3089 Ok(PointerMutability::Const(input.parse()?))
3090 } else if lookahead.peek(Token![mut]) {
3091 Ok(PointerMutability::Mut(input.parse()?))
3092 } else {
3093 Err(lookahead.error())
3094 }
3095 }
3096 }
3097
3098 fn check_cast(input: ParseStream) -> Result<()> {
3099 let kind = if input.peek(Token![.]) && !input.peek(Token![..]) {
3100 if input.peek2(Token![await]) {
3101 "`.await`"
3102 } else if input.peek2(Ident) && (input.peek3(token::Paren) || input.peek3(Token![::])) {
3103 "a method call"
3104 } else {
3105 "a field access"
3106 }
3107 } else if input.peek(Token![?]) {
3108 "`?`"
3109 } else if input.peek(token::Bracket) {
3110 "indexing"
3111 } else if input.peek(token::Paren) {
3112 "a function call"
3113 } else {
3114 return Ok(());
3115 };
3116 let msg = format!("casts cannot be followed by {}", kind);
3117 Err(input.error(msg))
3118 }
3119}
3120
3121#[cfg(feature = "printing")]
3122pub(crate) mod printing {
3123 use crate::attr::Attribute;
3124 #[cfg(feature = "full")]
3125 use crate::attr::FilterAttrs;
3126 #[cfg(feature = "full")]
3127 use crate::classify;
3128 #[cfg(feature = "full")]
3129 use crate::expr::{
3130 Arm, ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure,
3131 ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch,
3132 ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprUnsafe,
3133 ExprWhile, ExprYield, Label, PointerMutability, RangeLimits,
3134 };
3135 use crate::expr::{
3136 Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro,
3137 ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprTuple, ExprUnary,
3138 FieldValue, Index, Member,
3139 };
3140 use crate::fixup::FixupContext;
3141 use crate::op::BinOp;
3142 use crate::path;
3143 use crate::path::printing::PathStyle;
3144 use crate::precedence::Precedence;
3145 use crate::token;
3146 #[cfg(feature = "full")]
3147 use crate::ty::ReturnType;
3148 use proc_macro2::{Literal, Span, TokenStream};
3149 use quote::{ToTokens, TokenStreamExt};
3150
3151 #[cfg(feature = "full")]
3152 pub(crate) fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3153 tokens.append_all(attrs.outer());
3154 }
3155
3156 #[cfg(feature = "full")]
3157 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3158 tokens.append_all(attrs.inner());
3159 }
3160
3161 #[cfg(not(feature = "full"))]
3162 pub(crate) fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3163
3164 pub(crate) fn print_subexpression(
3165 expr: &Expr,
3166 needs_group: bool,
3167 tokens: &mut TokenStream,
3168 mut fixup: FixupContext,
3169 ) {
3170 if needs_group {
3171 fixup = FixupContext::NONE;
3183 }
3184
3185 let do_print_expr = |tokens: &mut TokenStream| print_expr(expr, tokens, fixup);
3186
3187 if needs_group {
3188 token::Paren::default().surround(tokens, do_print_expr);
3189 } else {
3190 do_print_expr(tokens);
3191 }
3192 }
3193
3194 pub(crate) fn print_expr(expr: &Expr, tokens: &mut TokenStream, mut fixup: FixupContext) {
3195 #[cfg(feature = "full")]
3196 let needs_group = fixup.parenthesize(expr);
3197 #[cfg(not(feature = "full"))]
3198 let needs_group = false;
3199
3200 if needs_group {
3201 fixup = FixupContext::NONE;
3202 }
3203
3204 let do_print_expr = |tokens: &mut TokenStream| match expr {
3205 #[cfg(feature = "full")]
3206 Expr::Array(e) => e.to_tokens(tokens),
3207 #[cfg(feature = "full")]
3208 Expr::Assign(e) => print_expr_assign(e, tokens, fixup),
3209 #[cfg(feature = "full")]
3210 Expr::Async(e) => e.to_tokens(tokens),
3211 #[cfg(feature = "full")]
3212 Expr::Await(e) => print_expr_await(e, tokens, fixup),
3213 Expr::Binary(e) => print_expr_binary(e, tokens, fixup),
3214 #[cfg(feature = "full")]
3215 Expr::Block(e) => e.to_tokens(tokens),
3216 #[cfg(feature = "full")]
3217 Expr::Break(e) => print_expr_break(e, tokens, fixup),
3218 Expr::Call(e) => print_expr_call(e, tokens, fixup),
3219 Expr::Cast(e) => print_expr_cast(e, tokens, fixup),
3220 #[cfg(feature = "full")]
3221 Expr::Closure(e) => print_expr_closure(e, tokens, fixup),
3222 #[cfg(feature = "full")]
3223 Expr::Const(e) => e.to_tokens(tokens),
3224 #[cfg(feature = "full")]
3225 Expr::Continue(e) => e.to_tokens(tokens),
3226 Expr::Field(e) => print_expr_field(e, tokens, fixup),
3227 #[cfg(feature = "full")]
3228 Expr::ForLoop(e) => e.to_tokens(tokens),
3229 Expr::Group(e) => e.to_tokens(tokens),
3230 #[cfg(feature = "full")]
3231 Expr::If(e) => e.to_tokens(tokens),
3232 Expr::Index(e) => print_expr_index(e, tokens, fixup),
3233 #[cfg(feature = "full")]
3234 Expr::Infer(e) => e.to_tokens(tokens),
3235 #[cfg(feature = "full")]
3236 Expr::Let(e) => print_expr_let(e, tokens, fixup),
3237 Expr::Lit(e) => e.to_tokens(tokens),
3238 #[cfg(feature = "full")]
3239 Expr::Loop(e) => e.to_tokens(tokens),
3240 Expr::Macro(e) => e.to_tokens(tokens),
3241 #[cfg(feature = "full")]
3242 Expr::Match(e) => e.to_tokens(tokens),
3243 Expr::MethodCall(e) => print_expr_method_call(e, tokens, fixup),
3244 Expr::Paren(e) => e.to_tokens(tokens),
3245 Expr::Path(e) => e.to_tokens(tokens),
3246 #[cfg(feature = "full")]
3247 Expr::Range(e) => print_expr_range(e, tokens, fixup),
3248 #[cfg(feature = "full")]
3249 Expr::RawAddr(e) => print_expr_raw_addr(e, tokens, fixup),
3250 Expr::Reference(e) => print_expr_reference(e, tokens, fixup),
3251 #[cfg(feature = "full")]
3252 Expr::Repeat(e) => e.to_tokens(tokens),
3253 #[cfg(feature = "full")]
3254 Expr::Return(e) => print_expr_return(e, tokens, fixup),
3255 Expr::Struct(e) => e.to_tokens(tokens),
3256 #[cfg(feature = "full")]
3257 Expr::Try(e) => print_expr_try(e, tokens, fixup),
3258 #[cfg(feature = "full")]
3259 Expr::TryBlock(e) => e.to_tokens(tokens),
3260 Expr::Tuple(e) => e.to_tokens(tokens),
3261 Expr::Unary(e) => print_expr_unary(e, tokens, fixup),
3262 #[cfg(feature = "full")]
3263 Expr::Unsafe(e) => e.to_tokens(tokens),
3264 Expr::Verbatim(e) => e.to_tokens(tokens),
3265 #[cfg(feature = "full")]
3266 Expr::While(e) => e.to_tokens(tokens),
3267 #[cfg(feature = "full")]
3268 Expr::Yield(e) => print_expr_yield(e, tokens, fixup),
3269
3270 #[cfg(not(feature = "full"))]
3271 _ => unreachable!(),
3272 };
3273
3274 if needs_group {
3275 token::Paren::default().surround(tokens, do_print_expr);
3276 } else {
3277 do_print_expr(tokens);
3278 }
3279 }
3280
3281 #[cfg(feature = "full")]
3282 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3283 impl ToTokens for ExprArray {
3284 fn to_tokens(&self, tokens: &mut TokenStream) {
3285 outer_attrs_to_tokens(&self.attrs, tokens);
3286 self.bracket_token.surround(tokens, |tokens| {
3287 self.elems.to_tokens(tokens);
3288 });
3289 }
3290 }
3291
3292 #[cfg(feature = "full")]
3293 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3294 impl ToTokens for ExprAssign {
3295 fn to_tokens(&self, tokens: &mut TokenStream) {
3296 print_expr_assign(self, tokens, FixupContext::NONE);
3297 }
3298 }
3299
3300 #[cfg(feature = "full")]
3301 fn print_expr_assign(e: &ExprAssign, tokens: &mut TokenStream, mut fixup: FixupContext) {
3302 outer_attrs_to_tokens(&e.attrs, tokens);
3303
3304 let needs_group = !e.attrs.is_empty();
3305 if needs_group {
3306 fixup = FixupContext::NONE;
3307 }
3308
3309 let do_print_expr = |tokens: &mut TokenStream| {
3310 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3311 &e.left,
3312 false,
3313 false,
3314 Precedence::Assign,
3315 );
3316 print_subexpression(&e.left, left_prec <= Precedence::Range, tokens, left_fixup);
3317 e.eq_token.to_tokens(tokens);
3318 print_expr(
3319 &e.right,
3320 tokens,
3321 fixup.rightmost_subexpression_fixup(false, false, Precedence::Assign),
3322 );
3323 };
3324
3325 if needs_group {
3326 token::Paren::default().surround(tokens, do_print_expr);
3327 } else {
3328 do_print_expr(tokens);
3329 }
3330 }
3331
3332 #[cfg(feature = "full")]
3333 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3334 impl ToTokens for ExprAsync {
3335 fn to_tokens(&self, tokens: &mut TokenStream) {
3336 outer_attrs_to_tokens(&self.attrs, tokens);
3337 self.async_token.to_tokens(tokens);
3338 self.capture.to_tokens(tokens);
3339 self.block.to_tokens(tokens);
3340 }
3341 }
3342
3343 #[cfg(feature = "full")]
3344 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3345 impl ToTokens for ExprAwait {
3346 fn to_tokens(&self, tokens: &mut TokenStream) {
3347 print_expr_await(self, tokens, FixupContext::NONE);
3348 }
3349 }
3350
3351 #[cfg(feature = "full")]
3352 fn print_expr_await(e: &ExprAwait, tokens: &mut TokenStream, fixup: FixupContext) {
3353 outer_attrs_to_tokens(&e.attrs, tokens);
3354 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.base);
3355 print_subexpression(
3356 &e.base,
3357 left_prec < Precedence::Unambiguous,
3358 tokens,
3359 left_fixup,
3360 );
3361 e.dot_token.to_tokens(tokens);
3362 e.await_token.to_tokens(tokens);
3363 }
3364
3365 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3366 impl ToTokens for ExprBinary {
3367 fn to_tokens(&self, tokens: &mut TokenStream) {
3368 print_expr_binary(self, tokens, FixupContext::NONE);
3369 }
3370 }
3371
3372 fn print_expr_binary(e: &ExprBinary, tokens: &mut TokenStream, mut fixup: FixupContext) {
3373 outer_attrs_to_tokens(&e.attrs, tokens);
3374
3375 let needs_group = !e.attrs.is_empty();
3376 if needs_group {
3377 fixup = FixupContext::NONE;
3378 }
3379
3380 let do_print_expr = |tokens: &mut TokenStream| {
3381 let binop_prec = Precedence::of_binop(&e.op);
3382 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3383 &e.left,
3384 #[cfg(feature = "full")]
3385 match &e.op {
3386 BinOp::Sub(_)
3387 | BinOp::Mul(_)
3388 | BinOp::And(_)
3389 | BinOp::Or(_)
3390 | BinOp::BitAnd(_)
3391 | BinOp::BitOr(_)
3392 | BinOp::Shl(_)
3393 | BinOp::Lt(_) => true,
3394 _ => false,
3395 },
3396 match &e.op {
3397 BinOp::Shl(_) | BinOp::Lt(_) => true,
3398 _ => false,
3399 },
3400 #[cfg(feature = "full")]
3401 binop_prec,
3402 );
3403 let left_needs_group = match binop_prec {
3404 Precedence::Assign => left_prec <= Precedence::Range,
3405 Precedence::Compare => left_prec <= binop_prec,
3406 _ => left_prec < binop_prec,
3407 };
3408
3409 let right_fixup = fixup.rightmost_subexpression_fixup(
3410 #[cfg(feature = "full")]
3411 false,
3412 #[cfg(feature = "full")]
3413 false,
3414 #[cfg(feature = "full")]
3415 binop_prec,
3416 );
3417 let right_needs_group = binop_prec != Precedence::Assign
3418 && right_fixup.rightmost_subexpression_precedence(&e.right) <= binop_prec;
3419
3420 print_subexpression(&e.left, left_needs_group, tokens, left_fixup);
3421 e.op.to_tokens(tokens);
3422 print_subexpression(&e.right, right_needs_group, tokens, right_fixup);
3423 };
3424
3425 if needs_group {
3426 token::Paren::default().surround(tokens, do_print_expr);
3427 } else {
3428 do_print_expr(tokens);
3429 }
3430 }
3431
3432 #[cfg(feature = "full")]
3433 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3434 impl ToTokens for ExprBlock {
3435 fn to_tokens(&self, tokens: &mut TokenStream) {
3436 outer_attrs_to_tokens(&self.attrs, tokens);
3437 self.label.to_tokens(tokens);
3438 self.block.brace_token.surround(tokens, |tokens| {
3439 inner_attrs_to_tokens(&self.attrs, tokens);
3440 tokens.append_all(&self.block.stmts);
3441 });
3442 }
3443 }
3444
3445 #[cfg(feature = "full")]
3446 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3447 impl ToTokens for ExprBreak {
3448 fn to_tokens(&self, tokens: &mut TokenStream) {
3449 print_expr_break(self, tokens, FixupContext::NONE);
3450 }
3451 }
3452
3453 #[cfg(feature = "full")]
3454 fn print_expr_break(e: &ExprBreak, tokens: &mut TokenStream, fixup: FixupContext) {
3455 outer_attrs_to_tokens(&e.attrs, tokens);
3456 e.break_token.to_tokens(tokens);
3457 e.label.to_tokens(tokens);
3458 if let Some(value) = &e.expr {
3459 print_subexpression(
3460 value,
3461 e.label.is_none() && classify::expr_leading_label(value),
3464 tokens,
3465 fixup.rightmost_subexpression_fixup(true, true, Precedence::Jump),
3466 );
3467 }
3468 }
3469
3470 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3471 impl ToTokens for ExprCall {
3472 fn to_tokens(&self, tokens: &mut TokenStream) {
3473 print_expr_call(self, tokens, FixupContext::NONE);
3474 }
3475 }
3476
3477 fn print_expr_call(e: &ExprCall, tokens: &mut TokenStream, fixup: FixupContext) {
3478 outer_attrs_to_tokens(&e.attrs, tokens);
3479
3480 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3481 &e.func,
3482 #[cfg(feature = "full")]
3483 true,
3484 false,
3485 #[cfg(feature = "full")]
3486 Precedence::Unambiguous,
3487 );
3488 let needs_group = if let Expr::Field(func) = &*e.func {
3489 func.member.is_named()
3490 } else {
3491 left_prec < Precedence::Unambiguous
3492 };
3493 print_subexpression(&e.func, needs_group, tokens, left_fixup);
3494
3495 e.paren_token.surround(tokens, |tokens| {
3496 e.args.to_tokens(tokens);
3497 });
3498 }
3499
3500 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3501 impl ToTokens for ExprCast {
3502 fn to_tokens(&self, tokens: &mut TokenStream) {
3503 print_expr_cast(self, tokens, FixupContext::NONE);
3504 }
3505 }
3506
3507 fn print_expr_cast(e: &ExprCast, tokens: &mut TokenStream, mut fixup: FixupContext) {
3508 outer_attrs_to_tokens(&e.attrs, tokens);
3509
3510 let needs_group = !e.attrs.is_empty();
3511 if needs_group {
3512 fixup = FixupContext::NONE;
3513 }
3514
3515 let do_print_expr = |tokens: &mut TokenStream| {
3516 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3517 &e.expr,
3518 #[cfg(feature = "full")]
3519 false,
3520 false,
3521 #[cfg(feature = "full")]
3522 Precedence::Cast,
3523 );
3524 print_subexpression(&e.expr, left_prec < Precedence::Cast, tokens, left_fixup);
3525 e.as_token.to_tokens(tokens);
3526 e.ty.to_tokens(tokens);
3527 };
3528
3529 if needs_group {
3530 token::Paren::default().surround(tokens, do_print_expr);
3531 } else {
3532 do_print_expr(tokens);
3533 }
3534 }
3535
3536 #[cfg(feature = "full")]
3537 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3538 impl ToTokens for ExprClosure {
3539 fn to_tokens(&self, tokens: &mut TokenStream) {
3540 print_expr_closure(self, tokens, FixupContext::NONE);
3541 }
3542 }
3543
3544 #[cfg(feature = "full")]
3545 fn print_expr_closure(e: &ExprClosure, tokens: &mut TokenStream, fixup: FixupContext) {
3546 outer_attrs_to_tokens(&e.attrs, tokens);
3547 e.lifetimes.to_tokens(tokens);
3548 e.constness.to_tokens(tokens);
3549 e.movability.to_tokens(tokens);
3550 e.asyncness.to_tokens(tokens);
3551 e.capture.to_tokens(tokens);
3552 e.or1_token.to_tokens(tokens);
3553 e.inputs.to_tokens(tokens);
3554 e.or2_token.to_tokens(tokens);
3555 e.output.to_tokens(tokens);
3556 if matches!(e.output, ReturnType::Default)
3557 || matches!(&*e.body, Expr::Block(body) if body.attrs.is_empty() && body.label.is_none())
3558 {
3559 print_expr(
3560 &e.body,
3561 tokens,
3562 fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump),
3563 );
3564 } else {
3565 token::Brace::default().surround(tokens, |tokens| {
3566 print_expr(&e.body, tokens, FixupContext::new_stmt());
3567 });
3568 }
3569 }
3570
3571 #[cfg(feature = "full")]
3572 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3573 impl ToTokens for ExprConst {
3574 fn to_tokens(&self, tokens: &mut TokenStream) {
3575 outer_attrs_to_tokens(&self.attrs, tokens);
3576 self.const_token.to_tokens(tokens);
3577 self.block.brace_token.surround(tokens, |tokens| {
3578 inner_attrs_to_tokens(&self.attrs, tokens);
3579 tokens.append_all(&self.block.stmts);
3580 });
3581 }
3582 }
3583
3584 #[cfg(feature = "full")]
3585 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3586 impl ToTokens for ExprContinue {
3587 fn to_tokens(&self, tokens: &mut TokenStream) {
3588 outer_attrs_to_tokens(&self.attrs, tokens);
3589 self.continue_token.to_tokens(tokens);
3590 self.label.to_tokens(tokens);
3591 }
3592 }
3593
3594 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3595 impl ToTokens for ExprField {
3596 fn to_tokens(&self, tokens: &mut TokenStream) {
3597 print_expr_field(self, tokens, FixupContext::NONE);
3598 }
3599 }
3600
3601 fn print_expr_field(e: &ExprField, tokens: &mut TokenStream, fixup: FixupContext) {
3602 outer_attrs_to_tokens(&e.attrs, tokens);
3603 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.base);
3604 print_subexpression(
3605 &e.base,
3606 left_prec < Precedence::Unambiguous,
3607 tokens,
3608 left_fixup,
3609 );
3610 e.dot_token.to_tokens(tokens);
3611 e.member.to_tokens(tokens);
3612 }
3613
3614 #[cfg(feature = "full")]
3615 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3616 impl ToTokens for ExprForLoop {
3617 fn to_tokens(&self, tokens: &mut TokenStream) {
3618 outer_attrs_to_tokens(&self.attrs, tokens);
3619 self.label.to_tokens(tokens);
3620 self.for_token.to_tokens(tokens);
3621 self.pat.to_tokens(tokens);
3622 self.in_token.to_tokens(tokens);
3623 print_expr(&self.expr, tokens, FixupContext::new_condition());
3624 self.body.brace_token.surround(tokens, |tokens| {
3625 inner_attrs_to_tokens(&self.attrs, tokens);
3626 tokens.append_all(&self.body.stmts);
3627 });
3628 }
3629 }
3630
3631 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3632 impl ToTokens for ExprGroup {
3633 fn to_tokens(&self, tokens: &mut TokenStream) {
3634 outer_attrs_to_tokens(&self.attrs, tokens);
3635 self.group_token.surround(tokens, |tokens| {
3636 self.expr.to_tokens(tokens);
3637 });
3638 }
3639 }
3640
3641 #[cfg(feature = "full")]
3642 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3643 impl ToTokens for ExprIf {
3644 fn to_tokens(&self, tokens: &mut TokenStream) {
3645 outer_attrs_to_tokens(&self.attrs, tokens);
3646
3647 let mut expr = self;
3648 loop {
3649 expr.if_token.to_tokens(tokens);
3650 print_expr(&expr.cond, tokens, FixupContext::new_condition());
3651 expr.then_branch.to_tokens(tokens);
3652
3653 let (else_token, else_) = match &expr.else_branch {
3654 Some(else_branch) => else_branch,
3655 None => break,
3656 };
3657
3658 else_token.to_tokens(tokens);
3659 match &**else_ {
3660 Expr::If(next) => {
3661 expr = next;
3662 }
3663 Expr::Block(last) => {
3664 last.to_tokens(tokens);
3665 break;
3666 }
3667 other => {
3670 token::Brace::default().surround(tokens, |tokens| {
3671 print_expr(other, tokens, FixupContext::new_stmt());
3672 });
3673 break;
3674 }
3675 }
3676 }
3677 }
3678 }
3679
3680 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3681 impl ToTokens for ExprIndex {
3682 fn to_tokens(&self, tokens: &mut TokenStream) {
3683 print_expr_index(self, tokens, FixupContext::NONE);
3684 }
3685 }
3686
3687 fn print_expr_index(e: &ExprIndex, tokens: &mut TokenStream, fixup: FixupContext) {
3688 outer_attrs_to_tokens(&e.attrs, tokens);
3689 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3690 &e.expr,
3691 #[cfg(feature = "full")]
3692 true,
3693 false,
3694 #[cfg(feature = "full")]
3695 Precedence::Unambiguous,
3696 );
3697 print_subexpression(
3698 &e.expr,
3699 left_prec < Precedence::Unambiguous,
3700 tokens,
3701 left_fixup,
3702 );
3703 e.bracket_token.surround(tokens, |tokens| {
3704 e.index.to_tokens(tokens);
3705 });
3706 }
3707
3708 #[cfg(feature = "full")]
3709 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3710 impl ToTokens for ExprInfer {
3711 fn to_tokens(&self, tokens: &mut TokenStream) {
3712 outer_attrs_to_tokens(&self.attrs, tokens);
3713 self.underscore_token.to_tokens(tokens);
3714 }
3715 }
3716
3717 #[cfg(feature = "full")]
3718 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3719 impl ToTokens for ExprLet {
3720 fn to_tokens(&self, tokens: &mut TokenStream) {
3721 print_expr_let(self, tokens, FixupContext::NONE);
3722 }
3723 }
3724
3725 #[cfg(feature = "full")]
3726 fn print_expr_let(e: &ExprLet, tokens: &mut TokenStream, fixup: FixupContext) {
3727 outer_attrs_to_tokens(&e.attrs, tokens);
3728 e.let_token.to_tokens(tokens);
3729 e.pat.to_tokens(tokens);
3730 e.eq_token.to_tokens(tokens);
3731 let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Let);
3732 print_subexpression(&e.expr, right_prec < Precedence::Let, tokens, right_fixup);
3733 }
3734
3735 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3736 impl ToTokens for ExprLit {
3737 fn to_tokens(&self, tokens: &mut TokenStream) {
3738 outer_attrs_to_tokens(&self.attrs, tokens);
3739 self.lit.to_tokens(tokens);
3740 }
3741 }
3742
3743 #[cfg(feature = "full")]
3744 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3745 impl ToTokens for ExprLoop {
3746 fn to_tokens(&self, tokens: &mut TokenStream) {
3747 outer_attrs_to_tokens(&self.attrs, tokens);
3748 self.label.to_tokens(tokens);
3749 self.loop_token.to_tokens(tokens);
3750 self.body.brace_token.surround(tokens, |tokens| {
3751 inner_attrs_to_tokens(&self.attrs, tokens);
3752 tokens.append_all(&self.body.stmts);
3753 });
3754 }
3755 }
3756
3757 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3758 impl ToTokens for ExprMacro {
3759 fn to_tokens(&self, tokens: &mut TokenStream) {
3760 outer_attrs_to_tokens(&self.attrs, tokens);
3761 self.mac.to_tokens(tokens);
3762 }
3763 }
3764
3765 #[cfg(feature = "full")]
3766 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3767 impl ToTokens for ExprMatch {
3768 fn to_tokens(&self, tokens: &mut TokenStream) {
3769 outer_attrs_to_tokens(&self.attrs, tokens);
3770 self.match_token.to_tokens(tokens);
3771 print_expr(&self.expr, tokens, FixupContext::new_condition());
3772 self.brace_token.surround(tokens, |tokens| {
3773 inner_attrs_to_tokens(&self.attrs, tokens);
3774 for (i, arm) in self.arms.iter().enumerate() {
3775 arm.to_tokens(tokens);
3776 let is_last = i == self.arms.len() - 1;
3779 if !is_last
3780 && classify::requires_comma_to_be_match_arm(&arm.body)
3781 && arm.comma.is_none()
3782 {
3783 <Token![,]>::default().to_tokens(tokens);
3784 }
3785 }
3786 });
3787 }
3788 }
3789
3790 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3791 impl ToTokens for ExprMethodCall {
3792 fn to_tokens(&self, tokens: &mut TokenStream) {
3793 print_expr_method_call(self, tokens, FixupContext::NONE);
3794 }
3795 }
3796
3797 fn print_expr_method_call(e: &ExprMethodCall, tokens: &mut TokenStream, fixup: FixupContext) {
3798 outer_attrs_to_tokens(&e.attrs, tokens);
3799 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.receiver);
3800 print_subexpression(
3801 &e.receiver,
3802 left_prec < Precedence::Unambiguous,
3803 tokens,
3804 left_fixup,
3805 );
3806 e.dot_token.to_tokens(tokens);
3807 e.method.to_tokens(tokens);
3808 if let Some(turbofish) = &e.turbofish {
3809 path::printing::print_angle_bracketed_generic_arguments(
3810 tokens,
3811 turbofish,
3812 PathStyle::Expr,
3813 );
3814 }
3815 e.paren_token.surround(tokens, |tokens| {
3816 e.args.to_tokens(tokens);
3817 });
3818 }
3819
3820 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3821 impl ToTokens for ExprParen {
3822 fn to_tokens(&self, tokens: &mut TokenStream) {
3823 outer_attrs_to_tokens(&self.attrs, tokens);
3824 self.paren_token.surround(tokens, |tokens| {
3825 self.expr.to_tokens(tokens);
3826 });
3827 }
3828 }
3829
3830 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3831 impl ToTokens for ExprPath {
3832 fn to_tokens(&self, tokens: &mut TokenStream) {
3833 outer_attrs_to_tokens(&self.attrs, tokens);
3834 path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
3835 }
3836 }
3837
3838 #[cfg(feature = "full")]
3839 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3840 impl ToTokens for ExprRange {
3841 fn to_tokens(&self, tokens: &mut TokenStream) {
3842 print_expr_range(self, tokens, FixupContext::NONE);
3843 }
3844 }
3845
3846 #[cfg(feature = "full")]
3847 fn print_expr_range(e: &ExprRange, tokens: &mut TokenStream, mut fixup: FixupContext) {
3848 outer_attrs_to_tokens(&e.attrs, tokens);
3849
3850 let needs_group = !e.attrs.is_empty();
3851 if needs_group {
3852 fixup = FixupContext::NONE;
3853 }
3854
3855 let do_print_expr = |tokens: &mut TokenStream| {
3856 if let Some(start) = &e.start {
3857 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3858 start,
3859 true,
3860 false,
3861 Precedence::Range,
3862 );
3863 print_subexpression(start, left_prec <= Precedence::Range, tokens, left_fixup);
3864 }
3865 e.limits.to_tokens(tokens);
3866 if let Some(end) = &e.end {
3867 let right_fixup =
3868 fixup.rightmost_subexpression_fixup(false, true, Precedence::Range);
3869 let right_prec = right_fixup.rightmost_subexpression_precedence(end);
3870 print_subexpression(end, right_prec <= Precedence::Range, tokens, right_fixup);
3871 }
3872 };
3873
3874 if needs_group {
3875 token::Paren::default().surround(tokens, do_print_expr);
3876 } else {
3877 do_print_expr(tokens);
3878 }
3879 }
3880
3881 #[cfg(feature = "full")]
3882 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3883 impl ToTokens for ExprRawAddr {
3884 fn to_tokens(&self, tokens: &mut TokenStream) {
3885 print_expr_raw_addr(self, tokens, FixupContext::NONE);
3886 }
3887 }
3888
3889 #[cfg(feature = "full")]
3890 fn print_expr_raw_addr(e: &ExprRawAddr, tokens: &mut TokenStream, fixup: FixupContext) {
3891 outer_attrs_to_tokens(&e.attrs, tokens);
3892 e.and_token.to_tokens(tokens);
3893 e.raw.to_tokens(tokens);
3894 e.mutability.to_tokens(tokens);
3895 let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Prefix);
3896 print_subexpression(
3897 &e.expr,
3898 right_prec < Precedence::Prefix,
3899 tokens,
3900 right_fixup,
3901 );
3902 }
3903
3904 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3905 impl ToTokens for ExprReference {
3906 fn to_tokens(&self, tokens: &mut TokenStream) {
3907 print_expr_reference(self, tokens, FixupContext::NONE);
3908 }
3909 }
3910
3911 fn print_expr_reference(e: &ExprReference, tokens: &mut TokenStream, fixup: FixupContext) {
3912 outer_attrs_to_tokens(&e.attrs, tokens);
3913 e.and_token.to_tokens(tokens);
3914 e.mutability.to_tokens(tokens);
3915 let (right_prec, right_fixup) = fixup.rightmost_subexpression(
3916 &e.expr,
3917 #[cfg(feature = "full")]
3918 Precedence::Prefix,
3919 );
3920 print_subexpression(
3921 &e.expr,
3922 right_prec < Precedence::Prefix,
3923 tokens,
3924 right_fixup,
3925 );
3926 }
3927
3928 #[cfg(feature = "full")]
3929 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3930 impl ToTokens for ExprRepeat {
3931 fn to_tokens(&self, tokens: &mut TokenStream) {
3932 outer_attrs_to_tokens(&self.attrs, tokens);
3933 self.bracket_token.surround(tokens, |tokens| {
3934 self.expr.to_tokens(tokens);
3935 self.semi_token.to_tokens(tokens);
3936 self.len.to_tokens(tokens);
3937 });
3938 }
3939 }
3940
3941 #[cfg(feature = "full")]
3942 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3943 impl ToTokens for ExprReturn {
3944 fn to_tokens(&self, tokens: &mut TokenStream) {
3945 print_expr_return(self, tokens, FixupContext::NONE);
3946 }
3947 }
3948
3949 #[cfg(feature = "full")]
3950 fn print_expr_return(e: &ExprReturn, tokens: &mut TokenStream, fixup: FixupContext) {
3951 outer_attrs_to_tokens(&e.attrs, tokens);
3952 e.return_token.to_tokens(tokens);
3953 if let Some(expr) = &e.expr {
3954 print_expr(
3955 expr,
3956 tokens,
3957 fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
3958 );
3959 }
3960 }
3961
3962 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3963 impl ToTokens for ExprStruct {
3964 fn to_tokens(&self, tokens: &mut TokenStream) {
3965 outer_attrs_to_tokens(&self.attrs, tokens);
3966 path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
3967 self.brace_token.surround(tokens, |tokens| {
3968 self.fields.to_tokens(tokens);
3969 if let Some(dot2_token) = &self.dot2_token {
3970 dot2_token.to_tokens(tokens);
3971 } else if self.rest.is_some() {
3972 Token).to_tokens(tokens);
3973 }
3974 self.rest.to_tokens(tokens);
3975 });
3976 }
3977 }
3978
3979 #[cfg(feature = "full")]
3980 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3981 impl ToTokens for ExprTry {
3982 fn to_tokens(&self, tokens: &mut TokenStream) {
3983 print_expr_try(self, tokens, FixupContext::NONE);
3984 }
3985 }
3986
3987 #[cfg(feature = "full")]
3988 fn print_expr_try(e: &ExprTry, tokens: &mut TokenStream, fixup: FixupContext) {
3989 outer_attrs_to_tokens(&e.attrs, tokens);
3990 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.expr);
3991 print_subexpression(
3992 &e.expr,
3993 left_prec < Precedence::Unambiguous,
3994 tokens,
3995 left_fixup,
3996 );
3997 e.question_token.to_tokens(tokens);
3998 }
3999
4000 #[cfg(feature = "full")]
4001 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4002 impl ToTokens for ExprTryBlock {
4003 fn to_tokens(&self, tokens: &mut TokenStream) {
4004 outer_attrs_to_tokens(&self.attrs, tokens);
4005 self.try_token.to_tokens(tokens);
4006 self.block.to_tokens(tokens);
4007 }
4008 }
4009
4010 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4011 impl ToTokens for ExprTuple {
4012 fn to_tokens(&self, tokens: &mut TokenStream) {
4013 outer_attrs_to_tokens(&self.attrs, tokens);
4014 self.paren_token.surround(tokens, |tokens| {
4015 self.elems.to_tokens(tokens);
4016 if self.elems.len() == 1 && !self.elems.trailing_punct() {
4019 <Token![,]>::default().to_tokens(tokens);
4020 }
4021 });
4022 }
4023 }
4024
4025 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4026 impl ToTokens for ExprUnary {
4027 fn to_tokens(&self, tokens: &mut TokenStream) {
4028 print_expr_unary(self, tokens, FixupContext::NONE);
4029 }
4030 }
4031
4032 fn print_expr_unary(e: &ExprUnary, tokens: &mut TokenStream, fixup: FixupContext) {
4033 outer_attrs_to_tokens(&e.attrs, tokens);
4034 e.op.to_tokens(tokens);
4035 let (right_prec, right_fixup) = fixup.rightmost_subexpression(
4036 &e.expr,
4037 #[cfg(feature = "full")]
4038 Precedence::Prefix,
4039 );
4040 print_subexpression(
4041 &e.expr,
4042 right_prec < Precedence::Prefix,
4043 tokens,
4044 right_fixup,
4045 );
4046 }
4047
4048 #[cfg(feature = "full")]
4049 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4050 impl ToTokens for ExprUnsafe {
4051 fn to_tokens(&self, tokens: &mut TokenStream) {
4052 outer_attrs_to_tokens(&self.attrs, tokens);
4053 self.unsafe_token.to_tokens(tokens);
4054 self.block.brace_token.surround(tokens, |tokens| {
4055 inner_attrs_to_tokens(&self.attrs, tokens);
4056 tokens.append_all(&self.block.stmts);
4057 });
4058 }
4059 }
4060
4061 #[cfg(feature = "full")]
4062 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4063 impl ToTokens for ExprWhile {
4064 fn to_tokens(&self, tokens: &mut TokenStream) {
4065 outer_attrs_to_tokens(&self.attrs, tokens);
4066 self.label.to_tokens(tokens);
4067 self.while_token.to_tokens(tokens);
4068 print_expr(&self.cond, tokens, FixupContext::new_condition());
4069 self.body.brace_token.surround(tokens, |tokens| {
4070 inner_attrs_to_tokens(&self.attrs, tokens);
4071 tokens.append_all(&self.body.stmts);
4072 });
4073 }
4074 }
4075
4076 #[cfg(feature = "full")]
4077 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4078 impl ToTokens for ExprYield {
4079 fn to_tokens(&self, tokens: &mut TokenStream) {
4080 print_expr_yield(self, tokens, FixupContext::NONE);
4081 }
4082 }
4083
4084 #[cfg(feature = "full")]
4085 fn print_expr_yield(e: &ExprYield, tokens: &mut TokenStream, fixup: FixupContext) {
4086 outer_attrs_to_tokens(&e.attrs, tokens);
4087 e.yield_token.to_tokens(tokens);
4088 if let Some(expr) = &e.expr {
4089 print_expr(
4090 expr,
4091 tokens,
4092 fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
4093 );
4094 }
4095 }
4096
4097 #[cfg(feature = "full")]
4098 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4099 impl ToTokens for Arm {
4100 fn to_tokens(&self, tokens: &mut TokenStream) {
4101 tokens.append_all(&self.attrs);
4102 self.pat.to_tokens(tokens);
4103 if let Some((if_token, guard)) = &self.guard {
4104 if_token.to_tokens(tokens);
4105 guard.to_tokens(tokens);
4106 }
4107 self.fat_arrow_token.to_tokens(tokens);
4108 print_expr(&self.body, tokens, FixupContext::new_match_arm());
4109 self.comma.to_tokens(tokens);
4110 }
4111 }
4112
4113 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4114 impl ToTokens for FieldValue {
4115 fn to_tokens(&self, tokens: &mut TokenStream) {
4116 outer_attrs_to_tokens(&self.attrs, tokens);
4117 self.member.to_tokens(tokens);
4118 if let Some(colon_token) = &self.colon_token {
4119 colon_token.to_tokens(tokens);
4120 self.expr.to_tokens(tokens);
4121 }
4122 }
4123 }
4124
4125 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4126 impl ToTokens for Index {
4127 fn to_tokens(&self, tokens: &mut TokenStream) {
4128 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
4129 lit.set_span(self.span);
4130 tokens.append(lit);
4131 }
4132 }
4133
4134 #[cfg(feature = "full")]
4135 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4136 impl ToTokens for Label {
4137 fn to_tokens(&self, tokens: &mut TokenStream) {
4138 self.name.to_tokens(tokens);
4139 self.colon_token.to_tokens(tokens);
4140 }
4141 }
4142
4143 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4144 impl ToTokens for Member {
4145 fn to_tokens(&self, tokens: &mut TokenStream) {
4146 match self {
4147 Member::Named(ident) => ident.to_tokens(tokens),
4148 Member::Unnamed(index) => index.to_tokens(tokens),
4149 }
4150 }
4151 }
4152
4153 #[cfg(feature = "full")]
4154 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4155 impl ToTokens for RangeLimits {
4156 fn to_tokens(&self, tokens: &mut TokenStream) {
4157 match self {
4158 RangeLimits::HalfOpen(t) => t.to_tokens(tokens),
4159 RangeLimits::Closed(t) => t.to_tokens(tokens),
4160 }
4161 }
4162 }
4163
4164 #[cfg(feature = "full")]
4165 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4166 impl ToTokens for PointerMutability {
4167 fn to_tokens(&self, tokens: &mut TokenStream) {
4168 match self {
4169 PointerMutability::Const(const_token) => const_token.to_tokens(tokens),
4170 PointerMutability::Mut(mut_token) => mut_token.to_tokens(tokens),
4171 }
4172 }
4173 }
4174}