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::{self, 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 && !generics::parsing::choose_generics_over_qpath_after_keyword(input)
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 && generics::parsing::choose_generics_over_qpath_after_keyword(input)
1807 || input.peek(Token![const]) && !input.peek2(token::Brace)
1808 || input.peek(Token![static])
1809 || input.peek(Token![async]) && (input.peek2(Token![|]) || input.peek2(Token![move]))
1810 {
1811 expr_closure(input, allow_struct).map(Expr::Closure)
1812 } else if token::parsing::peek_keyword(input.cursor(), "builtin") && input.peek2(Token![#])
1813 {
1814 expr_builtin(input)
1815 } else if input.peek(Ident)
1816 || input.peek(Token![::])
1817 || input.peek(Token![<])
1818 || input.peek(Token![self])
1819 || input.peek(Token![Self])
1820 || input.peek(Token![super])
1821 || input.peek(Token![crate])
1822 || input.peek(Token![try]) && (input.peek2(Token![!]) || input.peek2(Token![::]))
1823 {
1824 path_or_macro_or_struct(input, allow_struct)
1825 } else if input.peek(token::Paren) {
1826 paren_or_tuple(input)
1827 } else if input.peek(Token![break]) {
1828 expr_break(input, allow_struct).map(Expr::Break)
1829 } else if input.peek(Token![continue]) {
1830 input.parse().map(Expr::Continue)
1831 } else if input.peek(Token![return]) {
1832 input.parse().map(Expr::Return)
1833 } else if input.peek(Token![become]) {
1834 expr_become(input)
1835 } else if input.peek(token::Bracket) {
1836 array_or_repeat(input)
1837 } else if input.peek(Token![let]) {
1838 expr_let(input, allow_struct).map(Expr::Let)
1839 } else if input.peek(Token![if]) {
1840 input.parse().map(Expr::If)
1841 } else if input.peek(Token![while]) {
1842 input.parse().map(Expr::While)
1843 } else if input.peek(Token![for]) {
1844 input.parse().map(Expr::ForLoop)
1845 } else if input.peek(Token![loop]) {
1846 input.parse().map(Expr::Loop)
1847 } else if input.peek(Token![match]) {
1848 input.parse().map(Expr::Match)
1849 } else if input.peek(Token![yield]) {
1850 input.parse().map(Expr::Yield)
1851 } else if input.peek(Token![unsafe]) {
1852 input.parse().map(Expr::Unsafe)
1853 } else if input.peek(Token![const]) {
1854 input.parse().map(Expr::Const)
1855 } else if input.peek(token::Brace) {
1856 input.parse().map(Expr::Block)
1857 } else if input.peek(Token![..]) {
1858 expr_range(input, allow_struct).map(Expr::Range)
1859 } else if input.peek(Token![_]) {
1860 input.parse().map(Expr::Infer)
1861 } else if input.peek(Lifetime) {
1862 atom_labeled(input)
1863 } else {
1864 Err(input.error("expected an expression"))
1865 }
1866 }
1867
1868 #[cfg(feature = "full")]
1869 fn atom_labeled(input: ParseStream) -> Result<Expr> {
1870 let the_label: Label = input.parse()?;
1871 let mut expr = if input.peek(Token![while]) {
1872 Expr::While(input.parse()?)
1873 } else if input.peek(Token![for]) {
1874 Expr::ForLoop(input.parse()?)
1875 } else if input.peek(Token![loop]) {
1876 Expr::Loop(input.parse()?)
1877 } else if input.peek(token::Brace) {
1878 Expr::Block(input.parse()?)
1879 } else {
1880 return Err(input.error("expected loop or block expression"));
1881 };
1882 match &mut expr {
1883 Expr::While(ExprWhile { label, .. })
1884 | Expr::ForLoop(ExprForLoop { label, .. })
1885 | Expr::Loop(ExprLoop { label, .. })
1886 | Expr::Block(ExprBlock { label, .. }) => *label = Some(the_label),
1887 _ => unreachable!(),
1888 }
1889 Ok(expr)
1890 }
1891
1892 #[cfg(not(feature = "full"))]
1893 fn atom_expr(input: ParseStream) -> Result<Expr> {
1894 if input.peek(token::Group) {
1895 expr_group(input)
1896 } else if input.peek(Lit) {
1897 input.parse().map(Expr::Lit)
1898 } else if input.peek(token::Paren) {
1899 paren_or_tuple(input)
1900 } else if input.peek(Ident)
1901 || input.peek(Token![::])
1902 || input.peek(Token![<])
1903 || input.peek(Token![self])
1904 || input.peek(Token![Self])
1905 || input.peek(Token![super])
1906 || input.peek(Token![crate])
1907 {
1908 path_or_macro_or_struct(input)
1909 } else if input.is_empty() {
1910 Err(input.error("expected an expression"))
1911 } else {
1912 if input.peek(token::Brace) {
1913 let scan = input.fork();
1914 let content;
1915 braced!(content in scan);
1916 if content.parse::<Expr>().is_ok() && content.is_empty() {
1917 let expr_block = verbatim::between(input, &scan);
1918 input.advance_to(&scan);
1919 return Ok(Expr::Verbatim(expr_block));
1920 }
1921 }
1922 Err(input.error("unsupported expression; enable syn's features=[\"full\"]"))
1923 }
1924 }
1925
1926 #[cfg(feature = "full")]
1927 fn expr_builtin(input: ParseStream) -> Result<Expr> {
1928 let begin = input.fork();
1929
1930 token::parsing::keyword(input, "builtin")?;
1931 input.parse::<Token![#]>()?;
1932 input.parse::<Ident>()?;
1933
1934 let args;
1935 parenthesized!(args in input);
1936 args.parse::<TokenStream>()?;
1937
1938 Ok(Expr::Verbatim(verbatim::between(&begin, input)))
1939 }
1940
1941 fn path_or_macro_or_struct(
1942 input: ParseStream,
1943 #[cfg(feature = "full")] allow_struct: AllowStruct,
1944 ) -> Result<Expr> {
1945 let expr_style = true;
1946 let (qself, path) = path::parsing::qpath(input, expr_style)?;
1947 rest_of_path_or_macro_or_struct(
1948 qself,
1949 path,
1950 input,
1951 #[cfg(feature = "full")]
1952 allow_struct,
1953 )
1954 }
1955
1956 fn rest_of_path_or_macro_or_struct(
1957 qself: Option<QSelf>,
1958 path: Path,
1959 input: ParseStream,
1960 #[cfg(feature = "full")] allow_struct: AllowStruct,
1961 ) -> Result<Expr> {
1962 if qself.is_none()
1963 && input.peek(Token![!])
1964 && !input.peek(Token![!=])
1965 && path.is_mod_style()
1966 {
1967 let bang_token: Token![!] = input.parse()?;
1968 let (delimiter, tokens) = mac::parse_delimiter(input)?;
1969 return Ok(Expr::Macro(ExprMacro {
1970 attrs: Vec::new(),
1971 mac: Macro {
1972 path,
1973 bang_token,
1974 delimiter,
1975 tokens,
1976 },
1977 }));
1978 }
1979
1980 #[cfg(not(feature = "full"))]
1981 let allow_struct = (true,);
1982 if allow_struct.0 && input.peek(token::Brace) {
1983 return expr_struct_helper(input, qself, path).map(Expr::Struct);
1984 }
1985
1986 Ok(Expr::Path(ExprPath {
1987 attrs: Vec::new(),
1988 qself,
1989 path,
1990 }))
1991 }
1992
1993 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1994 impl Parse for ExprMacro {
1995 fn parse(input: ParseStream) -> Result<Self> {
1996 Ok(ExprMacro {
1997 attrs: Vec::new(),
1998 mac: input.parse()?,
1999 })
2000 }
2001 }
2002
2003 fn paren_or_tuple(input: ParseStream) -> Result<Expr> {
2004 let content;
2005 let paren_token = parenthesized!(content in input);
2006 if content.is_empty() {
2007 return Ok(Expr::Tuple(ExprTuple {
2008 attrs: Vec::new(),
2009 paren_token,
2010 elems: Punctuated::new(),
2011 }));
2012 }
2013
2014 let first: Expr = content.parse()?;
2015 if content.is_empty() {
2016 return Ok(Expr::Paren(ExprParen {
2017 attrs: Vec::new(),
2018 paren_token,
2019 expr: Box::new(first),
2020 }));
2021 }
2022
2023 let mut elems = Punctuated::new();
2024 elems.push_value(first);
2025 while !content.is_empty() {
2026 let punct = content.parse()?;
2027 elems.push_punct(punct);
2028 if content.is_empty() {
2029 break;
2030 }
2031 let value = content.parse()?;
2032 elems.push_value(value);
2033 }
2034 Ok(Expr::Tuple(ExprTuple {
2035 attrs: Vec::new(),
2036 paren_token,
2037 elems,
2038 }))
2039 }
2040
2041 #[cfg(feature = "full")]
2042 fn array_or_repeat(input: ParseStream) -> Result<Expr> {
2043 let content;
2044 let bracket_token = bracketed!(content in input);
2045 if content.is_empty() {
2046 return Ok(Expr::Array(ExprArray {
2047 attrs: Vec::new(),
2048 bracket_token,
2049 elems: Punctuated::new(),
2050 }));
2051 }
2052
2053 let first: Expr = content.parse()?;
2054 if content.is_empty() || content.peek(Token![,]) {
2055 let mut elems = Punctuated::new();
2056 elems.push_value(first);
2057 while !content.is_empty() {
2058 let punct = content.parse()?;
2059 elems.push_punct(punct);
2060 if content.is_empty() {
2061 break;
2062 }
2063 let value = content.parse()?;
2064 elems.push_value(value);
2065 }
2066 Ok(Expr::Array(ExprArray {
2067 attrs: Vec::new(),
2068 bracket_token,
2069 elems,
2070 }))
2071 } else if content.peek(Token![;]) {
2072 let semi_token: Token![;] = content.parse()?;
2073 let len: Expr = content.parse()?;
2074 Ok(Expr::Repeat(ExprRepeat {
2075 attrs: Vec::new(),
2076 bracket_token,
2077 expr: Box::new(first),
2078 semi_token,
2079 len: Box::new(len),
2080 }))
2081 } else {
2082 Err(content.error("expected `,` or `;`"))
2083 }
2084 }
2085
2086 #[cfg(feature = "full")]
2087 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2088 impl Parse for ExprArray {
2089 fn parse(input: ParseStream) -> Result<Self> {
2090 let content;
2091 let bracket_token = bracketed!(content in input);
2092 let mut elems = Punctuated::new();
2093
2094 while !content.is_empty() {
2095 let first: Expr = content.parse()?;
2096 elems.push_value(first);
2097 if content.is_empty() {
2098 break;
2099 }
2100 let punct = content.parse()?;
2101 elems.push_punct(punct);
2102 }
2103
2104 Ok(ExprArray {
2105 attrs: Vec::new(),
2106 bracket_token,
2107 elems,
2108 })
2109 }
2110 }
2111
2112 #[cfg(feature = "full")]
2113 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2114 impl Parse for ExprRepeat {
2115 fn parse(input: ParseStream) -> Result<Self> {
2116 let content;
2117 Ok(ExprRepeat {
2118 bracket_token: bracketed!(content in input),
2119 attrs: Vec::new(),
2120 expr: content.parse()?,
2121 semi_token: content.parse()?,
2122 len: content.parse()?,
2123 })
2124 }
2125 }
2126
2127 #[cfg(feature = "full")]
2128 fn continue_parsing_early(mut expr: &Expr) -> bool {
2129 while let Expr::Group(group) = expr {
2130 expr = &group.expr;
2131 }
2132 match expr {
2133 Expr::If(_)
2134 | Expr::While(_)
2135 | Expr::ForLoop(_)
2136 | Expr::Loop(_)
2137 | Expr::Match(_)
2138 | Expr::TryBlock(_)
2139 | Expr::Unsafe(_)
2140 | Expr::Const(_)
2141 | Expr::Block(_) => false,
2142 _ => true,
2143 }
2144 }
2145
2146 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2147 impl Parse for ExprLit {
2148 fn parse(input: ParseStream) -> Result<Self> {
2149 Ok(ExprLit {
2150 attrs: Vec::new(),
2151 lit: input.parse()?,
2152 })
2153 }
2154 }
2155
2156 fn expr_group(
2157 input: ParseStream,
2158 #[cfg(feature = "full")] allow_struct: AllowStruct,
2159 ) -> Result<Expr> {
2160 let group = crate::group::parse_group(input)?;
2161 let mut inner: Expr = group.content.parse()?;
2162
2163 match inner {
2164 Expr::Path(mut expr) if expr.attrs.is_empty() => {
2165 let grouped_len = expr.path.segments.len();
2166 Path::parse_rest(input, &mut expr.path, true)?;
2167 match rest_of_path_or_macro_or_struct(
2168 expr.qself,
2169 expr.path,
2170 input,
2171 #[cfg(feature = "full")]
2172 allow_struct,
2173 )? {
2174 Expr::Path(expr) if expr.path.segments.len() == grouped_len => {
2175 inner = Expr::Path(expr);
2176 }
2177 extended => return Ok(extended),
2178 }
2179 }
2180 _ => {}
2181 }
2182
2183 Ok(Expr::Group(ExprGroup {
2184 attrs: Vec::new(),
2185 group_token: group.token,
2186 expr: Box::new(inner),
2187 }))
2188 }
2189
2190 #[cfg(feature = "full")]
2191 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2192 impl Parse for ExprParen {
2193 fn parse(input: ParseStream) -> Result<Self> {
2194 let content;
2195 Ok(ExprParen {
2196 attrs: Vec::new(),
2197 paren_token: parenthesized!(content in input),
2198 expr: content.parse()?,
2199 })
2200 }
2201 }
2202
2203 #[cfg(feature = "full")]
2204 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2205 impl Parse for ExprLet {
2206 fn parse(input: ParseStream) -> Result<Self> {
2207 let allow_struct = AllowStruct(true);
2208 expr_let(input, allow_struct)
2209 }
2210 }
2211
2212 #[cfg(feature = "full")]
2213 fn expr_let(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprLet> {
2214 Ok(ExprLet {
2215 attrs: Vec::new(),
2216 let_token: input.parse()?,
2217 pat: Box::new(Pat::parse_multi_with_leading_vert(input)?),
2218 eq_token: input.parse()?,
2219 expr: Box::new({
2220 let lhs = unary_expr(input, allow_struct)?;
2221 parse_expr(input, lhs, allow_struct, Precedence::Compare)?
2222 }),
2223 })
2224 }
2225
2226 #[cfg(feature = "full")]
2227 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2228 impl Parse for ExprIf {
2229 fn parse(input: ParseStream) -> Result<Self> {
2230 let attrs = input.call(Attribute::parse_outer)?;
2231
2232 let mut clauses = Vec::new();
2233 let mut expr;
2234 loop {
2235 let if_token: Token![if] = input.parse()?;
2236 let cond = input.call(Expr::parse_without_eager_brace)?;
2237 let then_branch: Block = input.parse()?;
2238
2239 expr = ExprIf {
2240 attrs: Vec::new(),
2241 if_token,
2242 cond: Box::new(cond),
2243 then_branch,
2244 else_branch: None,
2245 };
2246
2247 if !input.peek(Token![else]) {
2248 break;
2249 }
2250
2251 let else_token: Token![else] = input.parse()?;
2252 let lookahead = input.lookahead1();
2253 if lookahead.peek(Token![if]) {
2254 expr.else_branch = Some((else_token, Box::new(Expr::PLACEHOLDER)));
2255 clauses.push(expr);
2256 } else if lookahead.peek(token::Brace) {
2257 expr.else_branch = Some((
2258 else_token,
2259 Box::new(Expr::Block(ExprBlock {
2260 attrs: Vec::new(),
2261 label: None,
2262 block: input.parse()?,
2263 })),
2264 ));
2265 break;
2266 } else {
2267 return Err(lookahead.error());
2268 }
2269 }
2270
2271 while let Some(mut prev) = clauses.pop() {
2272 *prev.else_branch.as_mut().unwrap().1 = Expr::If(expr);
2273 expr = prev;
2274 }
2275 expr.attrs = attrs;
2276 Ok(expr)
2277 }
2278 }
2279
2280 #[cfg(feature = "full")]
2281 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2282 impl Parse for ExprInfer {
2283 fn parse(input: ParseStream) -> Result<Self> {
2284 Ok(ExprInfer {
2285 attrs: input.call(Attribute::parse_outer)?,
2286 underscore_token: input.parse()?,
2287 })
2288 }
2289 }
2290
2291 #[cfg(feature = "full")]
2292 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2293 impl Parse for ExprForLoop {
2294 fn parse(input: ParseStream) -> Result<Self> {
2295 let mut attrs = input.call(Attribute::parse_outer)?;
2296 let label: Option<Label> = input.parse()?;
2297 let for_token: Token![for] = input.parse()?;
2298
2299 let pat = Pat::parse_multi_with_leading_vert(input)?;
2300
2301 let in_token: Token![in] = input.parse()?;
2302 let expr: Expr = input.call(Expr::parse_without_eager_brace)?;
2303
2304 let content;
2305 let brace_token = braced!(content in input);
2306 attr::parsing::parse_inner(&content, &mut attrs)?;
2307 let stmts = content.call(Block::parse_within)?;
2308
2309 Ok(ExprForLoop {
2310 attrs,
2311 label,
2312 for_token,
2313 pat: Box::new(pat),
2314 in_token,
2315 expr: Box::new(expr),
2316 body: Block { brace_token, stmts },
2317 })
2318 }
2319 }
2320
2321 #[cfg(feature = "full")]
2322 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2323 impl Parse for ExprLoop {
2324 fn parse(input: ParseStream) -> Result<Self> {
2325 let mut attrs = input.call(Attribute::parse_outer)?;
2326 let label: Option<Label> = input.parse()?;
2327 let loop_token: Token![loop] = input.parse()?;
2328
2329 let content;
2330 let brace_token = braced!(content in input);
2331 attr::parsing::parse_inner(&content, &mut attrs)?;
2332 let stmts = content.call(Block::parse_within)?;
2333
2334 Ok(ExprLoop {
2335 attrs,
2336 label,
2337 loop_token,
2338 body: Block { brace_token, stmts },
2339 })
2340 }
2341 }
2342
2343 #[cfg(feature = "full")]
2344 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2345 impl Parse for ExprMatch {
2346 fn parse(input: ParseStream) -> Result<Self> {
2347 let mut attrs = input.call(Attribute::parse_outer)?;
2348 let match_token: Token![match] = input.parse()?;
2349 let expr = Expr::parse_without_eager_brace(input)?;
2350
2351 let content;
2352 let brace_token = braced!(content in input);
2353 attr::parsing::parse_inner(&content, &mut attrs)?;
2354
2355 let arms = Arm::parse_multiple(&content)?;
2356
2357 Ok(ExprMatch {
2358 attrs,
2359 match_token,
2360 expr: Box::new(expr),
2361 brace_token,
2362 arms,
2363 })
2364 }
2365 }
2366
2367 macro_rules! impl_by_parsing_expr {
2368 (
2369 $(
2370 $expr_type:ty, $variant:ident, $msg:expr,
2371 )*
2372 ) => {
2373 $(
2374 #[cfg(all(feature = "full", feature = "printing"))]
2375 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2376 impl Parse for $expr_type {
2377 fn parse(input: ParseStream) -> Result<Self> {
2378 let mut expr: Expr = input.parse()?;
2379 loop {
2380 match expr {
2381 Expr::$variant(inner) => return Ok(inner),
2382 Expr::Group(next) => expr = *next.expr,
2383 _ => return Err(Error::new_spanned(expr, $msg)),
2384 }
2385 }
2386 }
2387 }
2388 )*
2389 };
2390 }
2391
2392 impl_by_parsing_expr! {
2393 ExprAssign, Assign, "expected assignment expression",
2394 ExprAwait, Await, "expected await expression",
2395 ExprBinary, Binary, "expected binary operation",
2396 ExprCall, Call, "expected function call expression",
2397 ExprCast, Cast, "expected cast expression",
2398 ExprField, Field, "expected struct field access",
2399 ExprIndex, Index, "expected indexing expression",
2400 ExprMethodCall, MethodCall, "expected method call expression",
2401 ExprRange, Range, "expected range expression",
2402 ExprTry, Try, "expected try expression",
2403 ExprTuple, Tuple, "expected tuple expression",
2404 }
2405
2406 #[cfg(feature = "full")]
2407 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2408 impl Parse for ExprUnary {
2409 fn parse(input: ParseStream) -> Result<Self> {
2410 let attrs = Vec::new();
2411 let allow_struct = AllowStruct(true);
2412 expr_unary(input, attrs, allow_struct)
2413 }
2414 }
2415
2416 #[cfg(feature = "full")]
2417 fn expr_unary(
2418 input: ParseStream,
2419 attrs: Vec<Attribute>,
2420 allow_struct: AllowStruct,
2421 ) -> Result<ExprUnary> {
2422 Ok(ExprUnary {
2423 attrs,
2424 op: input.parse()?,
2425 expr: Box::new(unary_expr(input, allow_struct)?),
2426 })
2427 }
2428
2429 #[cfg(feature = "full")]
2430 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2431 impl Parse for ExprClosure {
2432 fn parse(input: ParseStream) -> Result<Self> {
2433 let allow_struct = AllowStruct(true);
2434 expr_closure(input, allow_struct)
2435 }
2436 }
2437
2438 #[cfg(feature = "full")]
2439 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2440 impl Parse for ExprRawAddr {
2441 fn parse(input: ParseStream) -> Result<Self> {
2442 let allow_struct = AllowStruct(true);
2443 Ok(ExprRawAddr {
2444 attrs: Vec::new(),
2445 and_token: input.parse()?,
2446 raw: input.parse()?,
2447 mutability: input.parse()?,
2448 expr: Box::new(unary_expr(input, allow_struct)?),
2449 })
2450 }
2451 }
2452
2453 #[cfg(feature = "full")]
2454 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2455 impl Parse for ExprReference {
2456 fn parse(input: ParseStream) -> Result<Self> {
2457 let allow_struct = AllowStruct(true);
2458 Ok(ExprReference {
2459 attrs: Vec::new(),
2460 and_token: input.parse()?,
2461 mutability: input.parse()?,
2462 expr: Box::new(unary_expr(input, allow_struct)?),
2463 })
2464 }
2465 }
2466
2467 #[cfg(feature = "full")]
2468 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2469 impl Parse for ExprBreak {
2470 fn parse(input: ParseStream) -> Result<Self> {
2471 let allow_struct = AllowStruct(true);
2472 expr_break(input, allow_struct)
2473 }
2474 }
2475
2476 #[cfg(feature = "full")]
2477 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2478 impl Parse for ExprReturn {
2479 fn parse(input: ParseStream) -> Result<Self> {
2480 Ok(ExprReturn {
2481 attrs: Vec::new(),
2482 return_token: input.parse()?,
2483 expr: {
2484 if Expr::peek(input) {
2485 Some(input.parse()?)
2486 } else {
2487 None
2488 }
2489 },
2490 })
2491 }
2492 }
2493
2494 #[cfg(feature = "full")]
2495 fn expr_become(input: ParseStream) -> Result<Expr> {
2496 let begin = input.fork();
2497 input.parse::<Token![become]>()?;
2498 input.parse::<Expr>()?;
2499 Ok(Expr::Verbatim(verbatim::between(&begin, input)))
2500 }
2501
2502 #[cfg(feature = "full")]
2503 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2504 impl Parse for ExprTryBlock {
2505 fn parse(input: ParseStream) -> Result<Self> {
2506 Ok(ExprTryBlock {
2507 attrs: Vec::new(),
2508 try_token: input.parse()?,
2509 block: input.parse()?,
2510 })
2511 }
2512 }
2513
2514 #[cfg(feature = "full")]
2515 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2516 impl Parse for ExprYield {
2517 fn parse(input: ParseStream) -> Result<Self> {
2518 Ok(ExprYield {
2519 attrs: Vec::new(),
2520 yield_token: input.parse()?,
2521 expr: {
2522 if Expr::peek(input) {
2523 Some(input.parse()?)
2524 } else {
2525 None
2526 }
2527 },
2528 })
2529 }
2530 }
2531
2532 #[cfg(feature = "full")]
2533 fn expr_closure(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprClosure> {
2534 let lifetimes: Option<BoundLifetimes> = input.parse()?;
2535 let constness: Option<Token![const]> = input.parse()?;
2536 let movability: Option<Token![static]> = input.parse()?;
2537 let asyncness: Option<Token![async]> = input.parse()?;
2538 let capture: Option<Token![move]> = input.parse()?;
2539 let or1_token: Token![|] = input.parse()?;
2540
2541 let mut inputs = Punctuated::new();
2542 loop {
2543 if input.peek(Token![|]) {
2544 break;
2545 }
2546 let value = closure_arg(input)?;
2547 inputs.push_value(value);
2548 if input.peek(Token![|]) {
2549 break;
2550 }
2551 let punct: Token![,] = input.parse()?;
2552 inputs.push_punct(punct);
2553 }
2554
2555 let or2_token: Token![|] = input.parse()?;
2556
2557 let (output, body) = if input.peek(Token![->]) {
2558 let arrow_token: Token![->] = input.parse()?;
2559 let ty: Type = input.parse()?;
2560 let body: Block = input.parse()?;
2561 let output = ReturnType::Type(arrow_token, Box::new(ty));
2562 let block = Expr::Block(ExprBlock {
2563 attrs: Vec::new(),
2564 label: None,
2565 block: body,
2566 });
2567 (output, block)
2568 } else {
2569 let body = ambiguous_expr(input, allow_struct)?;
2570 (ReturnType::Default, body)
2571 };
2572
2573 Ok(ExprClosure {
2574 attrs: Vec::new(),
2575 lifetimes,
2576 constness,
2577 movability,
2578 asyncness,
2579 capture,
2580 or1_token,
2581 inputs,
2582 or2_token,
2583 output,
2584 body: Box::new(body),
2585 })
2586 }
2587
2588 #[cfg(feature = "full")]
2589 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2590 impl Parse for ExprAsync {
2591 fn parse(input: ParseStream) -> Result<Self> {
2592 Ok(ExprAsync {
2593 attrs: Vec::new(),
2594 async_token: input.parse()?,
2595 capture: input.parse()?,
2596 block: input.parse()?,
2597 })
2598 }
2599 }
2600
2601 #[cfg(feature = "full")]
2602 fn closure_arg(input: ParseStream) -> Result<Pat> {
2603 let attrs = input.call(Attribute::parse_outer)?;
2604 let mut pat = Pat::parse_single(input)?;
2605
2606 if input.peek(Token![:]) {
2607 Ok(Pat::Type(PatType {
2608 attrs,
2609 pat: Box::new(pat),
2610 colon_token: input.parse()?,
2611 ty: input.parse()?,
2612 }))
2613 } else {
2614 match &mut pat {
2615 Pat::Const(pat) => pat.attrs = attrs,
2616 Pat::Ident(pat) => pat.attrs = attrs,
2617 Pat::Lit(pat) => pat.attrs = attrs,
2618 Pat::Macro(pat) => pat.attrs = attrs,
2619 Pat::Or(pat) => pat.attrs = attrs,
2620 Pat::Paren(pat) => pat.attrs = attrs,
2621 Pat::Path(pat) => pat.attrs = attrs,
2622 Pat::Range(pat) => pat.attrs = attrs,
2623 Pat::Reference(pat) => pat.attrs = attrs,
2624 Pat::Rest(pat) => pat.attrs = attrs,
2625 Pat::Slice(pat) => pat.attrs = attrs,
2626 Pat::Struct(pat) => pat.attrs = attrs,
2627 Pat::Tuple(pat) => pat.attrs = attrs,
2628 Pat::TupleStruct(pat) => pat.attrs = attrs,
2629 Pat::Type(_) => unreachable!(),
2630 Pat::Verbatim(_) => {}
2631 Pat::Wild(pat) => pat.attrs = attrs,
2632 }
2633 Ok(pat)
2634 }
2635 }
2636
2637 #[cfg(feature = "full")]
2638 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2639 impl Parse for ExprWhile {
2640 fn parse(input: ParseStream) -> Result<Self> {
2641 let mut attrs = input.call(Attribute::parse_outer)?;
2642 let label: Option<Label> = input.parse()?;
2643 let while_token: Token![while] = input.parse()?;
2644 let cond = Expr::parse_without_eager_brace(input)?;
2645
2646 let content;
2647 let brace_token = braced!(content in input);
2648 attr::parsing::parse_inner(&content, &mut attrs)?;
2649 let stmts = content.call(Block::parse_within)?;
2650
2651 Ok(ExprWhile {
2652 attrs,
2653 label,
2654 while_token,
2655 cond: Box::new(cond),
2656 body: Block { brace_token, stmts },
2657 })
2658 }
2659 }
2660
2661 #[cfg(feature = "full")]
2662 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2663 impl Parse for ExprConst {
2664 fn parse(input: ParseStream) -> Result<Self> {
2665 let const_token: Token![const] = input.parse()?;
2666
2667 let content;
2668 let brace_token = braced!(content in input);
2669 let inner_attrs = content.call(Attribute::parse_inner)?;
2670 let stmts = content.call(Block::parse_within)?;
2671
2672 Ok(ExprConst {
2673 attrs: inner_attrs,
2674 const_token,
2675 block: Block { brace_token, stmts },
2676 })
2677 }
2678 }
2679
2680 #[cfg(feature = "full")]
2681 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2682 impl Parse for Label {
2683 fn parse(input: ParseStream) -> Result<Self> {
2684 Ok(Label {
2685 name: input.parse()?,
2686 colon_token: input.parse()?,
2687 })
2688 }
2689 }
2690
2691 #[cfg(feature = "full")]
2692 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2693 impl Parse for Option<Label> {
2694 fn parse(input: ParseStream) -> Result<Self> {
2695 if input.peek(Lifetime) {
2696 input.parse().map(Some)
2697 } else {
2698 Ok(None)
2699 }
2700 }
2701 }
2702
2703 #[cfg(feature = "full")]
2704 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2705 impl Parse for ExprContinue {
2706 fn parse(input: ParseStream) -> Result<Self> {
2707 Ok(ExprContinue {
2708 attrs: Vec::new(),
2709 continue_token: input.parse()?,
2710 label: input.parse()?,
2711 })
2712 }
2713 }
2714
2715 #[cfg(feature = "full")]
2716 fn expr_break(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprBreak> {
2717 let break_token: Token![break] = input.parse()?;
2718
2719 let ahead = input.fork();
2720 let label: Option<Lifetime> = ahead.parse()?;
2721 if label.is_some() && ahead.peek(Token![:]) {
2722 let _: Expr = input.parse()?;
2725 let start_span = label.unwrap().apostrophe;
2726 let end_span = input.cursor().prev_span();
2727 return Err(crate::error::new2(
2728 start_span,
2729 end_span,
2730 "parentheses required",
2731 ));
2732 }
2733
2734 input.advance_to(&ahead);
2735 let expr = if Expr::peek(input) && (allow_struct.0 || !input.peek(token::Brace)) {
2736 Some(input.parse()?)
2737 } else {
2738 None
2739 };
2740
2741 Ok(ExprBreak {
2742 attrs: Vec::new(),
2743 break_token,
2744 label,
2745 expr,
2746 })
2747 }
2748
2749 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2750 impl Parse for FieldValue {
2751 fn parse(input: ParseStream) -> Result<Self> {
2752 let attrs = input.call(Attribute::parse_outer)?;
2753 let member: Member = input.parse()?;
2754 let (colon_token, value) = if input.peek(Token![:]) || !member.is_named() {
2755 let colon_token: Token![:] = input.parse()?;
2756 let value: Expr = input.parse()?;
2757 (Some(colon_token), value)
2758 } else if let Member::Named(ident) = &member {
2759 let value = Expr::Path(ExprPath {
2760 attrs: Vec::new(),
2761 qself: None,
2762 path: Path::from(ident.clone()),
2763 });
2764 (None, value)
2765 } else {
2766 unreachable!()
2767 };
2768
2769 Ok(FieldValue {
2770 attrs,
2771 member,
2772 colon_token,
2773 expr: value,
2774 })
2775 }
2776 }
2777
2778 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2779 impl Parse for ExprStruct {
2780 fn parse(input: ParseStream) -> Result<Self> {
2781 let expr_style = true;
2782 let (qself, path) = path::parsing::qpath(input, expr_style)?;
2783 expr_struct_helper(input, qself, path)
2784 }
2785 }
2786
2787 fn expr_struct_helper(
2788 input: ParseStream,
2789 qself: Option<QSelf>,
2790 path: Path,
2791 ) -> Result<ExprStruct> {
2792 let content;
2793 let brace_token = braced!(content in input);
2794
2795 let mut fields = Punctuated::new();
2796 while !content.is_empty() {
2797 if content.peek(Token![..]) {
2798 return Ok(ExprStruct {
2799 attrs: Vec::new(),
2800 qself,
2801 path,
2802 brace_token,
2803 fields,
2804 dot2_token: Some(content.parse()?),
2805 rest: if content.is_empty() {
2806 None
2807 } else {
2808 Some(Box::new(content.parse()?))
2809 },
2810 });
2811 }
2812
2813 fields.push(content.parse()?);
2814 if content.is_empty() {
2815 break;
2816 }
2817 let punct: Token![,] = content.parse()?;
2818 fields.push_punct(punct);
2819 }
2820
2821 Ok(ExprStruct {
2822 attrs: Vec::new(),
2823 qself,
2824 path,
2825 brace_token,
2826 fields,
2827 dot2_token: None,
2828 rest: None,
2829 })
2830 }
2831
2832 #[cfg(feature = "full")]
2833 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2834 impl Parse for ExprUnsafe {
2835 fn parse(input: ParseStream) -> Result<Self> {
2836 let unsafe_token: Token![unsafe] = input.parse()?;
2837
2838 let content;
2839 let brace_token = braced!(content in input);
2840 let inner_attrs = content.call(Attribute::parse_inner)?;
2841 let stmts = content.call(Block::parse_within)?;
2842
2843 Ok(ExprUnsafe {
2844 attrs: inner_attrs,
2845 unsafe_token,
2846 block: Block { brace_token, stmts },
2847 })
2848 }
2849 }
2850
2851 #[cfg(feature = "full")]
2852 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2853 impl Parse for ExprBlock {
2854 fn parse(input: ParseStream) -> Result<Self> {
2855 let mut attrs = input.call(Attribute::parse_outer)?;
2856 let label: Option<Label> = input.parse()?;
2857
2858 let content;
2859 let brace_token = braced!(content in input);
2860 attr::parsing::parse_inner(&content, &mut attrs)?;
2861 let stmts = content.call(Block::parse_within)?;
2862
2863 Ok(ExprBlock {
2864 attrs,
2865 label,
2866 block: Block { brace_token, stmts },
2867 })
2868 }
2869 }
2870
2871 #[cfg(feature = "full")]
2872 fn expr_range(input: ParseStream, allow_struct: AllowStruct) -> Result<ExprRange> {
2873 let limits: RangeLimits = input.parse()?;
2874 let end = parse_range_end(input, &limits, allow_struct)?;
2875 Ok(ExprRange {
2876 attrs: Vec::new(),
2877 start: None,
2878 limits,
2879 end,
2880 })
2881 }
2882
2883 #[cfg(feature = "full")]
2884 fn parse_range_end(
2885 input: ParseStream,
2886 limits: &RangeLimits,
2887 allow_struct: AllowStruct,
2888 ) -> Result<Option<Box<Expr>>> {
2889 if matches!(limits, RangeLimits::HalfOpen(_))
2890 && (input.is_empty()
2891 || input.peek(Token![,])
2892 || input.peek(Token![;])
2893 || input.peek(Token![.]) && !input.peek(Token![..])
2894 || input.peek(Token![?])
2895 || input.peek(Token![=>])
2896 || !allow_struct.0 && input.peek(token::Brace)
2897 || input.peek(Token![=])
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![as]))
2911 {
2912 Ok(None)
2913 } else {
2914 let end = parse_binop_rhs(input, allow_struct, Precedence::Range)?;
2915 Ok(Some(end))
2916 }
2917 }
2918
2919 #[cfg(feature = "full")]
2920 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2921 impl Parse for RangeLimits {
2922 fn parse(input: ParseStream) -> Result<Self> {
2923 let lookahead = input.lookahead1();
2924 let dot_dot = lookahead.peek(Token![..]);
2925 let dot_dot_eq = dot_dot && lookahead.peek(Token![..=]);
2926 let dot_dot_dot = dot_dot && input.peek(Token![...]);
2927 if dot_dot_eq {
2928 input.parse().map(RangeLimits::Closed)
2929 } else if dot_dot && !dot_dot_dot {
2930 input.parse().map(RangeLimits::HalfOpen)
2931 } else {
2932 Err(lookahead.error())
2933 }
2934 }
2935 }
2936
2937 #[cfg(feature = "full")]
2938 impl RangeLimits {
2939 pub(crate) fn parse_obsolete(input: ParseStream) -> Result<Self> {
2940 let lookahead = input.lookahead1();
2941 let dot_dot = lookahead.peek(Token![..]);
2942 let dot_dot_eq = dot_dot && lookahead.peek(Token![..=]);
2943 let dot_dot_dot = dot_dot && input.peek(Token![...]);
2944 if dot_dot_eq {
2945 input.parse().map(RangeLimits::Closed)
2946 } else if dot_dot_dot {
2947 let dot3: Token![...] = input.parse()?;
2948 Ok(RangeLimits::Closed(Token))
2949 } else if dot_dot {
2950 input.parse().map(RangeLimits::HalfOpen)
2951 } else {
2952 Err(lookahead.error())
2953 }
2954 }
2955 }
2956
2957 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2958 impl Parse for ExprPath {
2959 fn parse(input: ParseStream) -> Result<Self> {
2960 #[cfg(not(feature = "full"))]
2961 let attrs = Vec::new();
2962 #[cfg(feature = "full")]
2963 let attrs = input.call(Attribute::parse_outer)?;
2964
2965 let expr_style = true;
2966 let (qself, path) = path::parsing::qpath(input, expr_style)?;
2967
2968 Ok(ExprPath { attrs, qself, path })
2969 }
2970 }
2971
2972 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2973 impl Parse for Member {
2974 fn parse(input: ParseStream) -> Result<Self> {
2975 if input.peek(Ident) {
2976 input.parse().map(Member::Named)
2977 } else if input.peek(LitInt) {
2978 input.parse().map(Member::Unnamed)
2979 } else {
2980 Err(input.error("expected identifier or integer"))
2981 }
2982 }
2983 }
2984
2985 #[cfg(feature = "full")]
2986 impl Arm {
2987 pub(crate) fn parse_multiple(input: ParseStream) -> Result<Vec<Self>> {
2988 let mut arms = Vec::new();
2989 while !input.is_empty() {
2990 arms.push(input.call(Arm::parse)?);
2991 }
2992 Ok(arms)
2993 }
2994 }
2995
2996 #[cfg(feature = "full")]
2997 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
2998 impl Parse for Arm {
2999 fn parse(input: ParseStream) -> Result<Arm> {
3000 let requires_comma;
3001 Ok(Arm {
3002 attrs: input.call(Attribute::parse_outer)?,
3003 pat: Pat::parse_multi_with_leading_vert(input)?,
3004 guard: {
3005 if input.peek(Token![if]) {
3006 let if_token: Token![if] = input.parse()?;
3007 let guard: Expr = input.parse()?;
3008 Some((if_token, Box::new(guard)))
3009 } else {
3010 None
3011 }
3012 },
3013 fat_arrow_token: input.parse()?,
3014 body: {
3015 let body = Expr::parse_with_earlier_boundary_rule(input)?;
3016 requires_comma = classify::requires_comma_to_be_match_arm(&body);
3017 Box::new(body)
3018 },
3019 comma: {
3020 if requires_comma && !input.is_empty() {
3021 Some(input.parse()?)
3022 } else {
3023 input.parse()?
3024 }
3025 },
3026 })
3027 }
3028 }
3029
3030 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3031 impl Parse for Index {
3032 fn parse(input: ParseStream) -> Result<Self> {
3033 let lit: LitInt = input.parse()?;
3034 if lit.suffix().is_empty() {
3035 Ok(Index {
3036 index: lit
3037 .base10_digits()
3038 .parse()
3039 .map_err(|err| Error::new(lit.span(), err))?,
3040 span: lit.span(),
3041 })
3042 } else {
3043 Err(Error::new(lit.span(), "expected unsuffixed integer"))
3044 }
3045 }
3046 }
3047
3048 fn multi_index(e: &mut Expr, dot_token: &mut Token![.], float: LitFloat) -> Result<bool> {
3049 let float_token = float.token();
3050 let float_span = float_token.span();
3051 let mut float_repr = float_token.to_string();
3052 let trailing_dot = float_repr.ends_with('.');
3053 if trailing_dot {
3054 float_repr.truncate(float_repr.len() - 1);
3055 }
3056
3057 let mut offset = 0;
3058 for part in float_repr.split('.') {
3059 let mut index: Index =
3060 crate::parse_str(part).map_err(|err| Error::new(float_span, err))?;
3061 let part_end = offset + part.len();
3062 index.span = float_token.subspan(offset..part_end).unwrap_or(float_span);
3063
3064 let base = mem::replace(e, Expr::PLACEHOLDER);
3065 *e = Expr::Field(ExprField {
3066 attrs: Vec::new(),
3067 base: Box::new(base),
3068 dot_token: Token,
3069 member: Member::Unnamed(index),
3070 });
3071
3072 let dot_span = float_token
3073 .subspan(part_end..part_end + 1)
3074 .unwrap_or(float_span);
3075 *dot_token = Token;
3076 offset = part_end + 1;
3077 }
3078
3079 Ok(!trailing_dot)
3080 }
3081
3082 #[cfg(feature = "full")]
3083 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
3084 impl Parse for PointerMutability {
3085 fn parse(input: ParseStream) -> Result<Self> {
3086 let lookahead = input.lookahead1();
3087 if lookahead.peek(Token![const]) {
3088 Ok(PointerMutability::Const(input.parse()?))
3089 } else if lookahead.peek(Token![mut]) {
3090 Ok(PointerMutability::Mut(input.parse()?))
3091 } else {
3092 Err(lookahead.error())
3093 }
3094 }
3095 }
3096
3097 fn check_cast(input: ParseStream) -> Result<()> {
3098 let kind = if input.peek(Token![.]) && !input.peek(Token![..]) {
3099 if input.peek2(Token![await]) {
3100 "`.await`"
3101 } else if input.peek2(Ident) && (input.peek3(token::Paren) || input.peek3(Token![::])) {
3102 "a method call"
3103 } else {
3104 "a field access"
3105 }
3106 } else if input.peek(Token![?]) {
3107 "`?`"
3108 } else if input.peek(token::Bracket) {
3109 "indexing"
3110 } else if input.peek(token::Paren) {
3111 "a function call"
3112 } else {
3113 return Ok(());
3114 };
3115 let msg = format!("casts cannot be followed by {}", kind);
3116 Err(input.error(msg))
3117 }
3118}
3119
3120#[cfg(feature = "printing")]
3121pub(crate) mod printing {
3122 use crate::attr::Attribute;
3123 #[cfg(feature = "full")]
3124 use crate::attr::FilterAttrs;
3125 #[cfg(feature = "full")]
3126 use crate::classify;
3127 #[cfg(feature = "full")]
3128 use crate::expr::{
3129 Arm, ExprArray, ExprAssign, ExprAsync, ExprAwait, ExprBlock, ExprBreak, ExprClosure,
3130 ExprConst, ExprContinue, ExprForLoop, ExprIf, ExprInfer, ExprLet, ExprLoop, ExprMatch,
3131 ExprRange, ExprRawAddr, ExprRepeat, ExprReturn, ExprTry, ExprTryBlock, ExprUnsafe,
3132 ExprWhile, ExprYield, Label, PointerMutability, RangeLimits,
3133 };
3134 use crate::expr::{
3135 Expr, ExprBinary, ExprCall, ExprCast, ExprField, ExprGroup, ExprIndex, ExprLit, ExprMacro,
3136 ExprMethodCall, ExprParen, ExprPath, ExprReference, ExprStruct, ExprTuple, ExprUnary,
3137 FieldValue, Index, Member,
3138 };
3139 use crate::fixup::FixupContext;
3140 use crate::op::BinOp;
3141 use crate::path;
3142 use crate::path::printing::PathStyle;
3143 use crate::precedence::Precedence;
3144 use crate::token;
3145 #[cfg(feature = "full")]
3146 use crate::ty::ReturnType;
3147 use proc_macro2::{Literal, Span, TokenStream};
3148 use quote::{ToTokens, TokenStreamExt};
3149
3150 #[cfg(feature = "full")]
3151 pub(crate) fn outer_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3152 tokens.append_all(attrs.outer());
3153 }
3154
3155 #[cfg(feature = "full")]
3156 fn inner_attrs_to_tokens(attrs: &[Attribute], tokens: &mut TokenStream) {
3157 tokens.append_all(attrs.inner());
3158 }
3159
3160 #[cfg(not(feature = "full"))]
3161 pub(crate) fn outer_attrs_to_tokens(_attrs: &[Attribute], _tokens: &mut TokenStream) {}
3162
3163 pub(crate) fn print_subexpression(
3164 expr: &Expr,
3165 needs_group: bool,
3166 tokens: &mut TokenStream,
3167 mut fixup: FixupContext,
3168 ) {
3169 if needs_group {
3170 fixup = FixupContext::NONE;
3182 }
3183
3184 let do_print_expr = |tokens: &mut TokenStream| print_expr(expr, tokens, fixup);
3185
3186 if needs_group {
3187 token::Paren::default().surround(tokens, do_print_expr);
3188 } else {
3189 do_print_expr(tokens);
3190 }
3191 }
3192
3193 pub(crate) fn print_expr(expr: &Expr, tokens: &mut TokenStream, mut fixup: FixupContext) {
3194 #[cfg(feature = "full")]
3195 let needs_group = fixup.parenthesize(expr);
3196 #[cfg(not(feature = "full"))]
3197 let needs_group = false;
3198
3199 if needs_group {
3200 fixup = FixupContext::NONE;
3201 }
3202
3203 let do_print_expr = |tokens: &mut TokenStream| match expr {
3204 #[cfg(feature = "full")]
3205 Expr::Array(e) => e.to_tokens(tokens),
3206 #[cfg(feature = "full")]
3207 Expr::Assign(e) => print_expr_assign(e, tokens, fixup),
3208 #[cfg(feature = "full")]
3209 Expr::Async(e) => e.to_tokens(tokens),
3210 #[cfg(feature = "full")]
3211 Expr::Await(e) => print_expr_await(e, tokens, fixup),
3212 Expr::Binary(e) => print_expr_binary(e, tokens, fixup),
3213 #[cfg(feature = "full")]
3214 Expr::Block(e) => e.to_tokens(tokens),
3215 #[cfg(feature = "full")]
3216 Expr::Break(e) => print_expr_break(e, tokens, fixup),
3217 Expr::Call(e) => print_expr_call(e, tokens, fixup),
3218 Expr::Cast(e) => print_expr_cast(e, tokens, fixup),
3219 #[cfg(feature = "full")]
3220 Expr::Closure(e) => print_expr_closure(e, tokens, fixup),
3221 #[cfg(feature = "full")]
3222 Expr::Const(e) => e.to_tokens(tokens),
3223 #[cfg(feature = "full")]
3224 Expr::Continue(e) => e.to_tokens(tokens),
3225 Expr::Field(e) => print_expr_field(e, tokens, fixup),
3226 #[cfg(feature = "full")]
3227 Expr::ForLoop(e) => e.to_tokens(tokens),
3228 Expr::Group(e) => e.to_tokens(tokens),
3229 #[cfg(feature = "full")]
3230 Expr::If(e) => e.to_tokens(tokens),
3231 Expr::Index(e) => print_expr_index(e, tokens, fixup),
3232 #[cfg(feature = "full")]
3233 Expr::Infer(e) => e.to_tokens(tokens),
3234 #[cfg(feature = "full")]
3235 Expr::Let(e) => print_expr_let(e, tokens, fixup),
3236 Expr::Lit(e) => e.to_tokens(tokens),
3237 #[cfg(feature = "full")]
3238 Expr::Loop(e) => e.to_tokens(tokens),
3239 Expr::Macro(e) => e.to_tokens(tokens),
3240 #[cfg(feature = "full")]
3241 Expr::Match(e) => e.to_tokens(tokens),
3242 Expr::MethodCall(e) => print_expr_method_call(e, tokens, fixup),
3243 Expr::Paren(e) => e.to_tokens(tokens),
3244 Expr::Path(e) => e.to_tokens(tokens),
3245 #[cfg(feature = "full")]
3246 Expr::Range(e) => print_expr_range(e, tokens, fixup),
3247 #[cfg(feature = "full")]
3248 Expr::RawAddr(e) => print_expr_raw_addr(e, tokens, fixup),
3249 Expr::Reference(e) => print_expr_reference(e, tokens, fixup),
3250 #[cfg(feature = "full")]
3251 Expr::Repeat(e) => e.to_tokens(tokens),
3252 #[cfg(feature = "full")]
3253 Expr::Return(e) => print_expr_return(e, tokens, fixup),
3254 Expr::Struct(e) => e.to_tokens(tokens),
3255 #[cfg(feature = "full")]
3256 Expr::Try(e) => print_expr_try(e, tokens, fixup),
3257 #[cfg(feature = "full")]
3258 Expr::TryBlock(e) => e.to_tokens(tokens),
3259 Expr::Tuple(e) => e.to_tokens(tokens),
3260 Expr::Unary(e) => print_expr_unary(e, tokens, fixup),
3261 #[cfg(feature = "full")]
3262 Expr::Unsafe(e) => e.to_tokens(tokens),
3263 Expr::Verbatim(e) => e.to_tokens(tokens),
3264 #[cfg(feature = "full")]
3265 Expr::While(e) => e.to_tokens(tokens),
3266 #[cfg(feature = "full")]
3267 Expr::Yield(e) => print_expr_yield(e, tokens, fixup),
3268
3269 #[cfg(not(feature = "full"))]
3270 _ => unreachable!(),
3271 };
3272
3273 if needs_group {
3274 token::Paren::default().surround(tokens, do_print_expr);
3275 } else {
3276 do_print_expr(tokens);
3277 }
3278 }
3279
3280 #[cfg(feature = "full")]
3281 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3282 impl ToTokens for ExprArray {
3283 fn to_tokens(&self, tokens: &mut TokenStream) {
3284 outer_attrs_to_tokens(&self.attrs, tokens);
3285 self.bracket_token.surround(tokens, |tokens| {
3286 self.elems.to_tokens(tokens);
3287 });
3288 }
3289 }
3290
3291 #[cfg(feature = "full")]
3292 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3293 impl ToTokens for ExprAssign {
3294 fn to_tokens(&self, tokens: &mut TokenStream) {
3295 print_expr_assign(self, tokens, FixupContext::NONE);
3296 }
3297 }
3298
3299 #[cfg(feature = "full")]
3300 fn print_expr_assign(e: &ExprAssign, tokens: &mut TokenStream, mut fixup: FixupContext) {
3301 outer_attrs_to_tokens(&e.attrs, tokens);
3302
3303 let needs_group = !e.attrs.is_empty();
3304 if needs_group {
3305 fixup = FixupContext::NONE;
3306 }
3307
3308 let do_print_expr = |tokens: &mut TokenStream| {
3309 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3310 &e.left,
3311 false,
3312 false,
3313 Precedence::Assign,
3314 );
3315 print_subexpression(&e.left, left_prec <= Precedence::Range, tokens, left_fixup);
3316 e.eq_token.to_tokens(tokens);
3317 print_expr(
3318 &e.right,
3319 tokens,
3320 fixup.rightmost_subexpression_fixup(false, false, Precedence::Assign),
3321 );
3322 };
3323
3324 if needs_group {
3325 token::Paren::default().surround(tokens, do_print_expr);
3326 } else {
3327 do_print_expr(tokens);
3328 }
3329 }
3330
3331 #[cfg(feature = "full")]
3332 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3333 impl ToTokens for ExprAsync {
3334 fn to_tokens(&self, tokens: &mut TokenStream) {
3335 outer_attrs_to_tokens(&self.attrs, tokens);
3336 self.async_token.to_tokens(tokens);
3337 self.capture.to_tokens(tokens);
3338 self.block.to_tokens(tokens);
3339 }
3340 }
3341
3342 #[cfg(feature = "full")]
3343 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3344 impl ToTokens for ExprAwait {
3345 fn to_tokens(&self, tokens: &mut TokenStream) {
3346 print_expr_await(self, tokens, FixupContext::NONE);
3347 }
3348 }
3349
3350 #[cfg(feature = "full")]
3351 fn print_expr_await(e: &ExprAwait, tokens: &mut TokenStream, fixup: FixupContext) {
3352 outer_attrs_to_tokens(&e.attrs, tokens);
3353 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.base);
3354 print_subexpression(
3355 &e.base,
3356 left_prec < Precedence::Unambiguous,
3357 tokens,
3358 left_fixup,
3359 );
3360 e.dot_token.to_tokens(tokens);
3361 e.await_token.to_tokens(tokens);
3362 }
3363
3364 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3365 impl ToTokens for ExprBinary {
3366 fn to_tokens(&self, tokens: &mut TokenStream) {
3367 print_expr_binary(self, tokens, FixupContext::NONE);
3368 }
3369 }
3370
3371 fn print_expr_binary(e: &ExprBinary, tokens: &mut TokenStream, mut fixup: FixupContext) {
3372 outer_attrs_to_tokens(&e.attrs, tokens);
3373
3374 let needs_group = !e.attrs.is_empty();
3375 if needs_group {
3376 fixup = FixupContext::NONE;
3377 }
3378
3379 let do_print_expr = |tokens: &mut TokenStream| {
3380 let binop_prec = Precedence::of_binop(&e.op);
3381 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3382 &e.left,
3383 #[cfg(feature = "full")]
3384 match &e.op {
3385 BinOp::Sub(_)
3386 | BinOp::Mul(_)
3387 | BinOp::And(_)
3388 | BinOp::Or(_)
3389 | BinOp::BitAnd(_)
3390 | BinOp::BitOr(_)
3391 | BinOp::Shl(_)
3392 | BinOp::Lt(_) => true,
3393 _ => false,
3394 },
3395 match &e.op {
3396 BinOp::Shl(_) | BinOp::Lt(_) => true,
3397 _ => false,
3398 },
3399 #[cfg(feature = "full")]
3400 binop_prec,
3401 );
3402 let left_needs_group = match binop_prec {
3403 Precedence::Assign => left_prec <= Precedence::Range,
3404 Precedence::Compare => left_prec <= binop_prec,
3405 _ => left_prec < binop_prec,
3406 };
3407
3408 let right_fixup = fixup.rightmost_subexpression_fixup(
3409 #[cfg(feature = "full")]
3410 false,
3411 #[cfg(feature = "full")]
3412 false,
3413 #[cfg(feature = "full")]
3414 binop_prec,
3415 );
3416 let right_needs_group = binop_prec != Precedence::Assign
3417 && right_fixup.rightmost_subexpression_precedence(&e.right) <= binop_prec;
3418
3419 print_subexpression(&e.left, left_needs_group, tokens, left_fixup);
3420 e.op.to_tokens(tokens);
3421 print_subexpression(&e.right, right_needs_group, tokens, right_fixup);
3422 };
3423
3424 if needs_group {
3425 token::Paren::default().surround(tokens, do_print_expr);
3426 } else {
3427 do_print_expr(tokens);
3428 }
3429 }
3430
3431 #[cfg(feature = "full")]
3432 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3433 impl ToTokens for ExprBlock {
3434 fn to_tokens(&self, tokens: &mut TokenStream) {
3435 outer_attrs_to_tokens(&self.attrs, tokens);
3436 self.label.to_tokens(tokens);
3437 self.block.brace_token.surround(tokens, |tokens| {
3438 inner_attrs_to_tokens(&self.attrs, tokens);
3439 tokens.append_all(&self.block.stmts);
3440 });
3441 }
3442 }
3443
3444 #[cfg(feature = "full")]
3445 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3446 impl ToTokens for ExprBreak {
3447 fn to_tokens(&self, tokens: &mut TokenStream) {
3448 print_expr_break(self, tokens, FixupContext::NONE);
3449 }
3450 }
3451
3452 #[cfg(feature = "full")]
3453 fn print_expr_break(e: &ExprBreak, tokens: &mut TokenStream, fixup: FixupContext) {
3454 outer_attrs_to_tokens(&e.attrs, tokens);
3455 e.break_token.to_tokens(tokens);
3456 e.label.to_tokens(tokens);
3457 if let Some(value) = &e.expr {
3458 print_subexpression(
3459 value,
3460 e.label.is_none() && classify::expr_leading_label(value),
3463 tokens,
3464 fixup.rightmost_subexpression_fixup(true, true, Precedence::Jump),
3465 );
3466 }
3467 }
3468
3469 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3470 impl ToTokens for ExprCall {
3471 fn to_tokens(&self, tokens: &mut TokenStream) {
3472 print_expr_call(self, tokens, FixupContext::NONE);
3473 }
3474 }
3475
3476 fn print_expr_call(e: &ExprCall, tokens: &mut TokenStream, fixup: FixupContext) {
3477 outer_attrs_to_tokens(&e.attrs, tokens);
3478
3479 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3480 &e.func,
3481 #[cfg(feature = "full")]
3482 true,
3483 false,
3484 #[cfg(feature = "full")]
3485 Precedence::Unambiguous,
3486 );
3487 let needs_group = if let Expr::Field(func) = &*e.func {
3488 func.member.is_named()
3489 } else {
3490 left_prec < Precedence::Unambiguous
3491 };
3492 print_subexpression(&e.func, needs_group, tokens, left_fixup);
3493
3494 e.paren_token.surround(tokens, |tokens| {
3495 e.args.to_tokens(tokens);
3496 });
3497 }
3498
3499 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3500 impl ToTokens for ExprCast {
3501 fn to_tokens(&self, tokens: &mut TokenStream) {
3502 print_expr_cast(self, tokens, FixupContext::NONE);
3503 }
3504 }
3505
3506 fn print_expr_cast(e: &ExprCast, tokens: &mut TokenStream, mut fixup: FixupContext) {
3507 outer_attrs_to_tokens(&e.attrs, tokens);
3508
3509 let needs_group = !e.attrs.is_empty();
3510 if needs_group {
3511 fixup = FixupContext::NONE;
3512 }
3513
3514 let do_print_expr = |tokens: &mut TokenStream| {
3515 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3516 &e.expr,
3517 #[cfg(feature = "full")]
3518 false,
3519 false,
3520 #[cfg(feature = "full")]
3521 Precedence::Cast,
3522 );
3523 print_subexpression(&e.expr, left_prec < Precedence::Cast, tokens, left_fixup);
3524 e.as_token.to_tokens(tokens);
3525 e.ty.to_tokens(tokens);
3526 };
3527
3528 if needs_group {
3529 token::Paren::default().surround(tokens, do_print_expr);
3530 } else {
3531 do_print_expr(tokens);
3532 }
3533 }
3534
3535 #[cfg(feature = "full")]
3536 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3537 impl ToTokens for ExprClosure {
3538 fn to_tokens(&self, tokens: &mut TokenStream) {
3539 print_expr_closure(self, tokens, FixupContext::NONE);
3540 }
3541 }
3542
3543 #[cfg(feature = "full")]
3544 fn print_expr_closure(e: &ExprClosure, tokens: &mut TokenStream, fixup: FixupContext) {
3545 outer_attrs_to_tokens(&e.attrs, tokens);
3546 e.lifetimes.to_tokens(tokens);
3547 e.constness.to_tokens(tokens);
3548 e.movability.to_tokens(tokens);
3549 e.asyncness.to_tokens(tokens);
3550 e.capture.to_tokens(tokens);
3551 e.or1_token.to_tokens(tokens);
3552 e.inputs.to_tokens(tokens);
3553 e.or2_token.to_tokens(tokens);
3554 e.output.to_tokens(tokens);
3555 if matches!(e.output, ReturnType::Default)
3556 || matches!(&*e.body, Expr::Block(body) if body.attrs.is_empty() && body.label.is_none())
3557 {
3558 print_expr(
3559 &e.body,
3560 tokens,
3561 fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump),
3562 );
3563 } else {
3564 token::Brace::default().surround(tokens, |tokens| {
3565 print_expr(&e.body, tokens, FixupContext::new_stmt());
3566 });
3567 }
3568 }
3569
3570 #[cfg(feature = "full")]
3571 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3572 impl ToTokens for ExprConst {
3573 fn to_tokens(&self, tokens: &mut TokenStream) {
3574 outer_attrs_to_tokens(&self.attrs, tokens);
3575 self.const_token.to_tokens(tokens);
3576 self.block.brace_token.surround(tokens, |tokens| {
3577 inner_attrs_to_tokens(&self.attrs, tokens);
3578 tokens.append_all(&self.block.stmts);
3579 });
3580 }
3581 }
3582
3583 #[cfg(feature = "full")]
3584 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3585 impl ToTokens for ExprContinue {
3586 fn to_tokens(&self, tokens: &mut TokenStream) {
3587 outer_attrs_to_tokens(&self.attrs, tokens);
3588 self.continue_token.to_tokens(tokens);
3589 self.label.to_tokens(tokens);
3590 }
3591 }
3592
3593 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3594 impl ToTokens for ExprField {
3595 fn to_tokens(&self, tokens: &mut TokenStream) {
3596 print_expr_field(self, tokens, FixupContext::NONE);
3597 }
3598 }
3599
3600 fn print_expr_field(e: &ExprField, tokens: &mut TokenStream, fixup: FixupContext) {
3601 outer_attrs_to_tokens(&e.attrs, tokens);
3602 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.base);
3603 print_subexpression(
3604 &e.base,
3605 left_prec < Precedence::Unambiguous,
3606 tokens,
3607 left_fixup,
3608 );
3609 e.dot_token.to_tokens(tokens);
3610 e.member.to_tokens(tokens);
3611 }
3612
3613 #[cfg(feature = "full")]
3614 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3615 impl ToTokens for ExprForLoop {
3616 fn to_tokens(&self, tokens: &mut TokenStream) {
3617 outer_attrs_to_tokens(&self.attrs, tokens);
3618 self.label.to_tokens(tokens);
3619 self.for_token.to_tokens(tokens);
3620 self.pat.to_tokens(tokens);
3621 self.in_token.to_tokens(tokens);
3622 print_expr(&self.expr, tokens, FixupContext::new_condition());
3623 self.body.brace_token.surround(tokens, |tokens| {
3624 inner_attrs_to_tokens(&self.attrs, tokens);
3625 tokens.append_all(&self.body.stmts);
3626 });
3627 }
3628 }
3629
3630 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3631 impl ToTokens for ExprGroup {
3632 fn to_tokens(&self, tokens: &mut TokenStream) {
3633 outer_attrs_to_tokens(&self.attrs, tokens);
3634 self.group_token.surround(tokens, |tokens| {
3635 self.expr.to_tokens(tokens);
3636 });
3637 }
3638 }
3639
3640 #[cfg(feature = "full")]
3641 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3642 impl ToTokens for ExprIf {
3643 fn to_tokens(&self, tokens: &mut TokenStream) {
3644 outer_attrs_to_tokens(&self.attrs, tokens);
3645
3646 let mut expr = self;
3647 loop {
3648 expr.if_token.to_tokens(tokens);
3649 print_expr(&expr.cond, tokens, FixupContext::new_condition());
3650 expr.then_branch.to_tokens(tokens);
3651
3652 let (else_token, else_) = match &expr.else_branch {
3653 Some(else_branch) => else_branch,
3654 None => break,
3655 };
3656
3657 else_token.to_tokens(tokens);
3658 match &**else_ {
3659 Expr::If(next) => {
3660 expr = next;
3661 }
3662 Expr::Block(last) => {
3663 last.to_tokens(tokens);
3664 break;
3665 }
3666 other => {
3669 token::Brace::default().surround(tokens, |tokens| {
3670 print_expr(other, tokens, FixupContext::new_stmt());
3671 });
3672 break;
3673 }
3674 }
3675 }
3676 }
3677 }
3678
3679 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3680 impl ToTokens for ExprIndex {
3681 fn to_tokens(&self, tokens: &mut TokenStream) {
3682 print_expr_index(self, tokens, FixupContext::NONE);
3683 }
3684 }
3685
3686 fn print_expr_index(e: &ExprIndex, tokens: &mut TokenStream, fixup: FixupContext) {
3687 outer_attrs_to_tokens(&e.attrs, tokens);
3688 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3689 &e.expr,
3690 #[cfg(feature = "full")]
3691 true,
3692 false,
3693 #[cfg(feature = "full")]
3694 Precedence::Unambiguous,
3695 );
3696 print_subexpression(
3697 &e.expr,
3698 left_prec < Precedence::Unambiguous,
3699 tokens,
3700 left_fixup,
3701 );
3702 e.bracket_token.surround(tokens, |tokens| {
3703 e.index.to_tokens(tokens);
3704 });
3705 }
3706
3707 #[cfg(feature = "full")]
3708 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3709 impl ToTokens for ExprInfer {
3710 fn to_tokens(&self, tokens: &mut TokenStream) {
3711 outer_attrs_to_tokens(&self.attrs, tokens);
3712 self.underscore_token.to_tokens(tokens);
3713 }
3714 }
3715
3716 #[cfg(feature = "full")]
3717 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3718 impl ToTokens for ExprLet {
3719 fn to_tokens(&self, tokens: &mut TokenStream) {
3720 print_expr_let(self, tokens, FixupContext::NONE);
3721 }
3722 }
3723
3724 #[cfg(feature = "full")]
3725 fn print_expr_let(e: &ExprLet, tokens: &mut TokenStream, fixup: FixupContext) {
3726 outer_attrs_to_tokens(&e.attrs, tokens);
3727 e.let_token.to_tokens(tokens);
3728 e.pat.to_tokens(tokens);
3729 e.eq_token.to_tokens(tokens);
3730 let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Let);
3731 print_subexpression(&e.expr, right_prec < Precedence::Let, tokens, right_fixup);
3732 }
3733
3734 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3735 impl ToTokens for ExprLit {
3736 fn to_tokens(&self, tokens: &mut TokenStream) {
3737 outer_attrs_to_tokens(&self.attrs, tokens);
3738 self.lit.to_tokens(tokens);
3739 }
3740 }
3741
3742 #[cfg(feature = "full")]
3743 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3744 impl ToTokens for ExprLoop {
3745 fn to_tokens(&self, tokens: &mut TokenStream) {
3746 outer_attrs_to_tokens(&self.attrs, tokens);
3747 self.label.to_tokens(tokens);
3748 self.loop_token.to_tokens(tokens);
3749 self.body.brace_token.surround(tokens, |tokens| {
3750 inner_attrs_to_tokens(&self.attrs, tokens);
3751 tokens.append_all(&self.body.stmts);
3752 });
3753 }
3754 }
3755
3756 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3757 impl ToTokens for ExprMacro {
3758 fn to_tokens(&self, tokens: &mut TokenStream) {
3759 outer_attrs_to_tokens(&self.attrs, tokens);
3760 self.mac.to_tokens(tokens);
3761 }
3762 }
3763
3764 #[cfg(feature = "full")]
3765 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3766 impl ToTokens for ExprMatch {
3767 fn to_tokens(&self, tokens: &mut TokenStream) {
3768 outer_attrs_to_tokens(&self.attrs, tokens);
3769 self.match_token.to_tokens(tokens);
3770 print_expr(&self.expr, tokens, FixupContext::new_condition());
3771 self.brace_token.surround(tokens, |tokens| {
3772 inner_attrs_to_tokens(&self.attrs, tokens);
3773 for (i, arm) in self.arms.iter().enumerate() {
3774 arm.to_tokens(tokens);
3775 let is_last = i == self.arms.len() - 1;
3778 if !is_last
3779 && classify::requires_comma_to_be_match_arm(&arm.body)
3780 && arm.comma.is_none()
3781 {
3782 <Token![,]>::default().to_tokens(tokens);
3783 }
3784 }
3785 });
3786 }
3787 }
3788
3789 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3790 impl ToTokens for ExprMethodCall {
3791 fn to_tokens(&self, tokens: &mut TokenStream) {
3792 print_expr_method_call(self, tokens, FixupContext::NONE);
3793 }
3794 }
3795
3796 fn print_expr_method_call(e: &ExprMethodCall, tokens: &mut TokenStream, fixup: FixupContext) {
3797 outer_attrs_to_tokens(&e.attrs, tokens);
3798 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.receiver);
3799 print_subexpression(
3800 &e.receiver,
3801 left_prec < Precedence::Unambiguous,
3802 tokens,
3803 left_fixup,
3804 );
3805 e.dot_token.to_tokens(tokens);
3806 e.method.to_tokens(tokens);
3807 if let Some(turbofish) = &e.turbofish {
3808 path::printing::print_angle_bracketed_generic_arguments(
3809 tokens,
3810 turbofish,
3811 PathStyle::Expr,
3812 );
3813 }
3814 e.paren_token.surround(tokens, |tokens| {
3815 e.args.to_tokens(tokens);
3816 });
3817 }
3818
3819 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3820 impl ToTokens for ExprParen {
3821 fn to_tokens(&self, tokens: &mut TokenStream) {
3822 outer_attrs_to_tokens(&self.attrs, tokens);
3823 self.paren_token.surround(tokens, |tokens| {
3824 self.expr.to_tokens(tokens);
3825 });
3826 }
3827 }
3828
3829 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3830 impl ToTokens for ExprPath {
3831 fn to_tokens(&self, tokens: &mut TokenStream) {
3832 outer_attrs_to_tokens(&self.attrs, tokens);
3833 path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
3834 }
3835 }
3836
3837 #[cfg(feature = "full")]
3838 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3839 impl ToTokens for ExprRange {
3840 fn to_tokens(&self, tokens: &mut TokenStream) {
3841 print_expr_range(self, tokens, FixupContext::NONE);
3842 }
3843 }
3844
3845 #[cfg(feature = "full")]
3846 fn print_expr_range(e: &ExprRange, tokens: &mut TokenStream, mut fixup: FixupContext) {
3847 outer_attrs_to_tokens(&e.attrs, tokens);
3848
3849 let needs_group = !e.attrs.is_empty();
3850 if needs_group {
3851 fixup = FixupContext::NONE;
3852 }
3853
3854 let do_print_expr = |tokens: &mut TokenStream| {
3855 if let Some(start) = &e.start {
3856 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
3857 start,
3858 true,
3859 false,
3860 Precedence::Range,
3861 );
3862 print_subexpression(start, left_prec <= Precedence::Range, tokens, left_fixup);
3863 }
3864 e.limits.to_tokens(tokens);
3865 if let Some(end) = &e.end {
3866 let right_fixup =
3867 fixup.rightmost_subexpression_fixup(false, true, Precedence::Range);
3868 let right_prec = right_fixup.rightmost_subexpression_precedence(end);
3869 print_subexpression(end, right_prec <= Precedence::Range, tokens, right_fixup);
3870 }
3871 };
3872
3873 if needs_group {
3874 token::Paren::default().surround(tokens, do_print_expr);
3875 } else {
3876 do_print_expr(tokens);
3877 }
3878 }
3879
3880 #[cfg(feature = "full")]
3881 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3882 impl ToTokens for ExprRawAddr {
3883 fn to_tokens(&self, tokens: &mut TokenStream) {
3884 print_expr_raw_addr(self, tokens, FixupContext::NONE);
3885 }
3886 }
3887
3888 #[cfg(feature = "full")]
3889 fn print_expr_raw_addr(e: &ExprRawAddr, tokens: &mut TokenStream, fixup: FixupContext) {
3890 outer_attrs_to_tokens(&e.attrs, tokens);
3891 e.and_token.to_tokens(tokens);
3892 e.raw.to_tokens(tokens);
3893 e.mutability.to_tokens(tokens);
3894 let (right_prec, right_fixup) = fixup.rightmost_subexpression(&e.expr, Precedence::Prefix);
3895 print_subexpression(
3896 &e.expr,
3897 right_prec < Precedence::Prefix,
3898 tokens,
3899 right_fixup,
3900 );
3901 }
3902
3903 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3904 impl ToTokens for ExprReference {
3905 fn to_tokens(&self, tokens: &mut TokenStream) {
3906 print_expr_reference(self, tokens, FixupContext::NONE);
3907 }
3908 }
3909
3910 fn print_expr_reference(e: &ExprReference, tokens: &mut TokenStream, fixup: FixupContext) {
3911 outer_attrs_to_tokens(&e.attrs, tokens);
3912 e.and_token.to_tokens(tokens);
3913 e.mutability.to_tokens(tokens);
3914 let (right_prec, right_fixup) = fixup.rightmost_subexpression(
3915 &e.expr,
3916 #[cfg(feature = "full")]
3917 Precedence::Prefix,
3918 );
3919 print_subexpression(
3920 &e.expr,
3921 right_prec < Precedence::Prefix,
3922 tokens,
3923 right_fixup,
3924 );
3925 }
3926
3927 #[cfg(feature = "full")]
3928 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3929 impl ToTokens for ExprRepeat {
3930 fn to_tokens(&self, tokens: &mut TokenStream) {
3931 outer_attrs_to_tokens(&self.attrs, tokens);
3932 self.bracket_token.surround(tokens, |tokens| {
3933 self.expr.to_tokens(tokens);
3934 self.semi_token.to_tokens(tokens);
3935 self.len.to_tokens(tokens);
3936 });
3937 }
3938 }
3939
3940 #[cfg(feature = "full")]
3941 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3942 impl ToTokens for ExprReturn {
3943 fn to_tokens(&self, tokens: &mut TokenStream) {
3944 print_expr_return(self, tokens, FixupContext::NONE);
3945 }
3946 }
3947
3948 #[cfg(feature = "full")]
3949 fn print_expr_return(e: &ExprReturn, tokens: &mut TokenStream, fixup: FixupContext) {
3950 outer_attrs_to_tokens(&e.attrs, tokens);
3951 e.return_token.to_tokens(tokens);
3952 if let Some(expr) = &e.expr {
3953 print_expr(
3954 expr,
3955 tokens,
3956 fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
3957 );
3958 }
3959 }
3960
3961 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3962 impl ToTokens for ExprStruct {
3963 fn to_tokens(&self, tokens: &mut TokenStream) {
3964 outer_attrs_to_tokens(&self.attrs, tokens);
3965 path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
3966 self.brace_token.surround(tokens, |tokens| {
3967 self.fields.to_tokens(tokens);
3968 if let Some(dot2_token) = &self.dot2_token {
3969 dot2_token.to_tokens(tokens);
3970 } else if self.rest.is_some() {
3971 Token).to_tokens(tokens);
3972 }
3973 self.rest.to_tokens(tokens);
3974 });
3975 }
3976 }
3977
3978 #[cfg(feature = "full")]
3979 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
3980 impl ToTokens for ExprTry {
3981 fn to_tokens(&self, tokens: &mut TokenStream) {
3982 print_expr_try(self, tokens, FixupContext::NONE);
3983 }
3984 }
3985
3986 #[cfg(feature = "full")]
3987 fn print_expr_try(e: &ExprTry, tokens: &mut TokenStream, fixup: FixupContext) {
3988 outer_attrs_to_tokens(&e.attrs, tokens);
3989 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&e.expr);
3990 print_subexpression(
3991 &e.expr,
3992 left_prec < Precedence::Unambiguous,
3993 tokens,
3994 left_fixup,
3995 );
3996 e.question_token.to_tokens(tokens);
3997 }
3998
3999 #[cfg(feature = "full")]
4000 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4001 impl ToTokens for ExprTryBlock {
4002 fn to_tokens(&self, tokens: &mut TokenStream) {
4003 outer_attrs_to_tokens(&self.attrs, tokens);
4004 self.try_token.to_tokens(tokens);
4005 self.block.to_tokens(tokens);
4006 }
4007 }
4008
4009 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4010 impl ToTokens for ExprTuple {
4011 fn to_tokens(&self, tokens: &mut TokenStream) {
4012 outer_attrs_to_tokens(&self.attrs, tokens);
4013 self.paren_token.surround(tokens, |tokens| {
4014 self.elems.to_tokens(tokens);
4015 if self.elems.len() == 1 && !self.elems.trailing_punct() {
4018 <Token![,]>::default().to_tokens(tokens);
4019 }
4020 });
4021 }
4022 }
4023
4024 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4025 impl ToTokens for ExprUnary {
4026 fn to_tokens(&self, tokens: &mut TokenStream) {
4027 print_expr_unary(self, tokens, FixupContext::NONE);
4028 }
4029 }
4030
4031 fn print_expr_unary(e: &ExprUnary, tokens: &mut TokenStream, fixup: FixupContext) {
4032 outer_attrs_to_tokens(&e.attrs, tokens);
4033 e.op.to_tokens(tokens);
4034 let (right_prec, right_fixup) = fixup.rightmost_subexpression(
4035 &e.expr,
4036 #[cfg(feature = "full")]
4037 Precedence::Prefix,
4038 );
4039 print_subexpression(
4040 &e.expr,
4041 right_prec < Precedence::Prefix,
4042 tokens,
4043 right_fixup,
4044 );
4045 }
4046
4047 #[cfg(feature = "full")]
4048 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4049 impl ToTokens for ExprUnsafe {
4050 fn to_tokens(&self, tokens: &mut TokenStream) {
4051 outer_attrs_to_tokens(&self.attrs, tokens);
4052 self.unsafe_token.to_tokens(tokens);
4053 self.block.brace_token.surround(tokens, |tokens| {
4054 inner_attrs_to_tokens(&self.attrs, tokens);
4055 tokens.append_all(&self.block.stmts);
4056 });
4057 }
4058 }
4059
4060 #[cfg(feature = "full")]
4061 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4062 impl ToTokens for ExprWhile {
4063 fn to_tokens(&self, tokens: &mut TokenStream) {
4064 outer_attrs_to_tokens(&self.attrs, tokens);
4065 self.label.to_tokens(tokens);
4066 self.while_token.to_tokens(tokens);
4067 print_expr(&self.cond, tokens, FixupContext::new_condition());
4068 self.body.brace_token.surround(tokens, |tokens| {
4069 inner_attrs_to_tokens(&self.attrs, tokens);
4070 tokens.append_all(&self.body.stmts);
4071 });
4072 }
4073 }
4074
4075 #[cfg(feature = "full")]
4076 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4077 impl ToTokens for ExprYield {
4078 fn to_tokens(&self, tokens: &mut TokenStream) {
4079 print_expr_yield(self, tokens, FixupContext::NONE);
4080 }
4081 }
4082
4083 #[cfg(feature = "full")]
4084 fn print_expr_yield(e: &ExprYield, tokens: &mut TokenStream, fixup: FixupContext) {
4085 outer_attrs_to_tokens(&e.attrs, tokens);
4086 e.yield_token.to_tokens(tokens);
4087 if let Some(expr) = &e.expr {
4088 print_expr(
4089 expr,
4090 tokens,
4091 fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
4092 );
4093 }
4094 }
4095
4096 #[cfg(feature = "full")]
4097 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4098 impl ToTokens for Arm {
4099 fn to_tokens(&self, tokens: &mut TokenStream) {
4100 tokens.append_all(&self.attrs);
4101 self.pat.to_tokens(tokens);
4102 if let Some((if_token, guard)) = &self.guard {
4103 if_token.to_tokens(tokens);
4104 guard.to_tokens(tokens);
4105 }
4106 self.fat_arrow_token.to_tokens(tokens);
4107 print_expr(&self.body, tokens, FixupContext::new_match_arm());
4108 self.comma.to_tokens(tokens);
4109 }
4110 }
4111
4112 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4113 impl ToTokens for FieldValue {
4114 fn to_tokens(&self, tokens: &mut TokenStream) {
4115 outer_attrs_to_tokens(&self.attrs, tokens);
4116 self.member.to_tokens(tokens);
4117 if let Some(colon_token) = &self.colon_token {
4118 colon_token.to_tokens(tokens);
4119 self.expr.to_tokens(tokens);
4120 }
4121 }
4122 }
4123
4124 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4125 impl ToTokens for Index {
4126 fn to_tokens(&self, tokens: &mut TokenStream) {
4127 let mut lit = Literal::i64_unsuffixed(i64::from(self.index));
4128 lit.set_span(self.span);
4129 tokens.append(lit);
4130 }
4131 }
4132
4133 #[cfg(feature = "full")]
4134 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4135 impl ToTokens for Label {
4136 fn to_tokens(&self, tokens: &mut TokenStream) {
4137 self.name.to_tokens(tokens);
4138 self.colon_token.to_tokens(tokens);
4139 }
4140 }
4141
4142 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4143 impl ToTokens for Member {
4144 fn to_tokens(&self, tokens: &mut TokenStream) {
4145 match self {
4146 Member::Named(ident) => ident.to_tokens(tokens),
4147 Member::Unnamed(index) => index.to_tokens(tokens),
4148 }
4149 }
4150 }
4151
4152 #[cfg(feature = "full")]
4153 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4154 impl ToTokens for RangeLimits {
4155 fn to_tokens(&self, tokens: &mut TokenStream) {
4156 match self {
4157 RangeLimits::HalfOpen(t) => t.to_tokens(tokens),
4158 RangeLimits::Closed(t) => t.to_tokens(tokens),
4159 }
4160 }
4161 }
4162
4163 #[cfg(feature = "full")]
4164 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
4165 impl ToTokens for PointerMutability {
4166 fn to_tokens(&self, tokens: &mut TokenStream) {
4167 match self {
4168 PointerMutability::Const(const_token) => const_token.to_tokens(tokens),
4169 PointerMutability::Mut(mut_token) => mut_token.to_tokens(tokens),
4170 }
4171 }
4172 }
4173}