1use crate::algorithm::{BreakToken, Printer};
2use crate::attr;
3use crate::classify;
4use crate::fixup::FixupContext;
5use crate::iter::IterDelimited;
6use crate::path::PathKind;
7use crate::precedence::Precedence;
8use crate::stmt;
9use crate::INDENT;
10use proc_macro2::TokenStream;
11use syn::punctuated::Punctuated;
12use syn::{
13 token, Arm, Attribute, BinOp, Block, Expr, ExprArray, ExprAssign, ExprAsync, ExprAwait,
14 ExprBinary, ExprBlock, ExprBreak, ExprCall, ExprCast, ExprClosure, ExprConst, ExprContinue,
15 ExprField, ExprForLoop, ExprGroup, ExprIf, ExprIndex, ExprInfer, ExprLet, ExprLit, ExprLoop,
16 ExprMacro, ExprMatch, ExprMethodCall, ExprParen, ExprPath, ExprRange, ExprRawAddr,
17 ExprReference, ExprRepeat, ExprReturn, ExprStruct, ExprTry, ExprTryBlock, ExprTuple, ExprUnary,
18 ExprUnsafe, ExprWhile, ExprYield, FieldValue, Index, Label, Member, PointerMutability,
19 RangeLimits, ReturnType, Stmt, Token, UnOp,
20};
21
22impl Printer {
23 pub fn expr(&mut self, expr: &Expr, mut fixup: FixupContext) {
24 let needs_paren = fixup.parenthesize(expr);
25 if needs_paren {
26 self.word("(");
27 fixup = FixupContext::NONE;
28 }
29
30 let beginning_of_line = false;
31
32 match expr {
33 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
34 Expr::Array(expr) => self.expr_array(expr),
35 Expr::Assign(expr) => self.expr_assign(expr, fixup),
36 Expr::Async(expr) => self.expr_async(expr),
37 Expr::Await(expr) => self.expr_await(expr, beginning_of_line, fixup),
38 Expr::Binary(expr) => self.expr_binary(expr, fixup),
39 Expr::Block(expr) => self.expr_block(expr),
40 Expr::Break(expr) => self.expr_break(expr, fixup),
41 Expr::Call(expr) => self.expr_call(expr, beginning_of_line, fixup),
42 Expr::Cast(expr) => self.expr_cast(expr, fixup),
43 Expr::Closure(expr) => self.expr_closure(expr, fixup),
44 Expr::Const(expr) => self.expr_const(expr),
45 Expr::Continue(expr) => self.expr_continue(expr),
46 Expr::Field(expr) => self.expr_field(expr, beginning_of_line, fixup),
47 Expr::ForLoop(expr) => self.expr_for_loop(expr),
48 Expr::Group(expr) => self.expr_group(expr, fixup),
49 Expr::If(expr) => self.expr_if(expr),
50 Expr::Index(expr) => self.expr_index(expr, beginning_of_line, fixup),
51 Expr::Infer(expr) => self.expr_infer(expr),
52 Expr::Let(expr) => self.expr_let(expr, fixup),
53 Expr::Lit(expr) => self.expr_lit(expr),
54 Expr::Loop(expr) => self.expr_loop(expr),
55 Expr::Macro(expr) => self.expr_macro(expr),
56 Expr::Match(expr) => self.expr_match(expr),
57 Expr::MethodCall(expr) => self.expr_method_call(expr, beginning_of_line, fixup),
58 Expr::Paren(expr) => self.expr_paren(expr),
59 Expr::Path(expr) => self.expr_path(expr),
60 Expr::Range(expr) => self.expr_range(expr, fixup),
61 Expr::RawAddr(expr) => self.expr_raw_addr(expr, fixup),
62 Expr::Reference(expr) => self.expr_reference(expr, fixup),
63 Expr::Repeat(expr) => self.expr_repeat(expr),
64 Expr::Return(expr) => self.expr_return(expr, fixup),
65 Expr::Struct(expr) => self.expr_struct(expr),
66 Expr::Try(expr) => self.expr_try(expr, beginning_of_line, fixup),
67 Expr::TryBlock(expr) => self.expr_try_block(expr),
68 Expr::Tuple(expr) => self.expr_tuple(expr),
69 Expr::Unary(expr) => self.expr_unary(expr, fixup),
70 Expr::Unsafe(expr) => self.expr_unsafe(expr),
71 Expr::Verbatim(expr) => self.expr_verbatim(expr, fixup),
72 Expr::While(expr) => self.expr_while(expr),
73 Expr::Yield(expr) => self.expr_yield(expr, fixup),
74 _ => unimplemented!("unknown Expr"),
75 }
76
77 if needs_paren {
78 self.word(")");
79 }
80 }
81
82 pub fn expr_beginning_of_line(
83 &mut self,
84 expr: &Expr,
85 mut needs_paren: bool,
86 beginning_of_line: bool,
87 mut fixup: FixupContext,
88 ) {
89 needs_paren |= fixup.parenthesize(expr);
90 if needs_paren {
91 self.word("(");
92 fixup = FixupContext::NONE;
93 }
94
95 match expr {
96 Expr::Await(expr) => self.expr_await(expr, beginning_of_line, fixup),
97 Expr::Field(expr) => self.expr_field(expr, beginning_of_line, fixup),
98 Expr::Index(expr) => self.expr_index(expr, beginning_of_line, fixup),
99 Expr::MethodCall(expr) => self.expr_method_call(expr, beginning_of_line, fixup),
100 Expr::Try(expr) => self.expr_try(expr, beginning_of_line, fixup),
101 _ => self.expr(expr, fixup),
102 }
103
104 if needs_paren {
105 self.word(")");
106 }
107 }
108
109 fn prefix_subexpr(
110 &mut self,
111 expr: &Expr,
112 mut needs_paren: bool,
113 beginning_of_line: bool,
114 mut fixup: FixupContext,
115 ) {
116 needs_paren |= fixup.parenthesize(expr);
117 if needs_paren {
118 self.word("(");
119 fixup = FixupContext::NONE;
120 }
121
122 match expr {
123 Expr::Await(expr) => self.prefix_subexpr_await(expr, beginning_of_line, fixup),
124 Expr::Call(expr) => self.prefix_subexpr_call(expr, fixup),
125 Expr::Field(expr) => self.prefix_subexpr_field(expr, beginning_of_line, fixup),
126 Expr::Index(expr) => self.prefix_subexpr_index(expr, beginning_of_line, fixup),
127 Expr::MethodCall(expr) => {
128 let unindent_call_args = false;
129 self.prefix_subexpr_method_call(expr, beginning_of_line, unindent_call_args, fixup);
130 }
131 Expr::Try(expr) => self.prefix_subexpr_try(expr, beginning_of_line, fixup),
132 _ => {
133 self.cbox(-INDENT);
134 self.expr(expr, fixup);
135 self.end();
136 }
137 }
138
139 if needs_paren {
140 self.word(")");
141 }
142 }
143
144 fn expr_condition(&mut self, expr: &Expr) {
145 self.cbox(0);
146 self.expr(expr, FixupContext::new_condition());
147 if needs_newline_if_wrap(expr) {
148 self.space();
149 } else {
150 self.nbsp();
151 }
152 self.end();
153 }
154
155 pub fn subexpr(&mut self, expr: &Expr, needs_paren: bool, mut fixup: FixupContext) {
156 if needs_paren {
157 self.word("(");
158 fixup = FixupContext::NONE;
159 }
160
161 self.expr(expr, fixup);
162
163 if needs_paren {
164 self.word(")");
165 }
166 }
167
168 fn expr_array(&mut self, expr: &ExprArray) {
169 self.outer_attrs(&expr.attrs);
170 self.word("[");
171 self.cbox(INDENT);
172 self.zerobreak();
173 for element in expr.elems.iter().delimited() {
174 self.expr(&element, FixupContext::NONE);
175 self.trailing_comma(element.is_last);
176 }
177 self.offset(-INDENT);
178 self.end();
179 self.word("]");
180 }
181
182 fn expr_assign(&mut self, expr: &ExprAssign, fixup: FixupContext) {
183 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
184 &expr.left,
185 false,
186 false,
187 Precedence::Assign,
188 );
189 let right_fixup = fixup.rightmost_subexpression_fixup(false, false, Precedence::Assign);
190
191 self.outer_attrs(&expr.attrs);
192 self.ibox(0);
193 self.subexpr(&expr.left, left_prec <= Precedence::Range, left_fixup);
194 self.word(" = ");
195 self.neverbreak();
196 self.expr(&expr.right, right_fixup);
197 self.end();
198 }
199
200 fn expr_async(&mut self, expr: &ExprAsync) {
201 self.outer_attrs(&expr.attrs);
202 self.word("async ");
203 if expr.capture.is_some() {
204 self.word("move ");
205 }
206 self.cbox(INDENT);
207 self.small_block(&expr.block, &expr.attrs);
208 self.end();
209 }
210
211 fn expr_await(&mut self, expr: &ExprAwait, beginning_of_line: bool, fixup: FixupContext) {
212 self.outer_attrs(&expr.attrs);
213 self.cbox(INDENT);
214 self.prefix_subexpr_await(expr, beginning_of_line, fixup);
215 self.end();
216 }
217
218 fn prefix_subexpr_await(
219 &mut self,
220 expr: &ExprAwait,
221 beginning_of_line: bool,
222 fixup: FixupContext,
223 ) {
224 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&expr.base);
225
226 self.prefix_subexpr(
227 &expr.base,
228 left_prec < Precedence::Unambiguous,
229 beginning_of_line,
230 left_fixup,
231 );
232 if !(beginning_of_line && is_short_ident(&expr.base)) {
233 self.scan_break(BreakToken {
234 no_break: self.ends_with('.').then_some(' '),
235 ..BreakToken::default()
236 });
237 }
238 self.word(".await");
239 }
240
241 fn expr_binary(&mut self, expr: &ExprBinary, fixup: FixupContext) {
242 let binop_prec = Precedence::of_binop(&expr.op);
243 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
244 &expr.left,
245 match &expr.op {
246 BinOp::Sub(_)
247 | BinOp::Mul(_)
248 | BinOp::And(_)
249 | BinOp::Or(_)
250 | BinOp::BitAnd(_)
251 | BinOp::BitOr(_)
252 | BinOp::Shl(_)
253 | BinOp::Lt(_) => true,
254 _ => false,
255 },
256 match &expr.op {
257 BinOp::Shl(_) | BinOp::Lt(_) => true,
258 _ => false,
259 },
260 binop_prec,
261 );
262 let left_needs_group = match binop_prec {
263 Precedence::Assign => left_prec <= Precedence::Range,
264 Precedence::Compare => left_prec <= binop_prec,
265 _ => left_prec < binop_prec,
266 };
267 let right_fixup = fixup.rightmost_subexpression_fixup(false, false, binop_prec);
268 let right_needs_group = binop_prec != Precedence::Assign
269 && right_fixup.rightmost_subexpression_precedence(&expr.right) <= binop_prec;
270
271 self.outer_attrs(&expr.attrs);
272 self.ibox(INDENT);
273 self.ibox(-INDENT);
274 self.subexpr(&expr.left, left_needs_group, left_fixup);
275 self.end();
276 self.space();
277 self.binary_operator(&expr.op);
278 self.nbsp();
279 self.subexpr(&expr.right, right_needs_group, right_fixup);
280 self.end();
281 }
282
283 pub fn expr_block(&mut self, expr: &ExprBlock) {
284 self.outer_attrs(&expr.attrs);
285 if let Some(label) = &expr.label {
286 self.label(label);
287 }
288 self.cbox(INDENT);
289 self.small_block(&expr.block, &expr.attrs);
290 self.end();
291 }
292
293 fn expr_break(&mut self, expr: &ExprBreak, fixup: FixupContext) {
294 self.outer_attrs(&expr.attrs);
295 self.word("break");
296 if let Some(lifetime) = &expr.label {
297 self.nbsp();
298 self.lifetime(lifetime);
299 }
300 if let Some(value) = &expr.expr {
301 self.nbsp();
302 self.subexpr(
303 value,
304 expr.label.is_none() && classify::expr_leading_label(value),
305 fixup.rightmost_subexpression_fixup(true, true, Precedence::Jump),
306 );
307 }
308 }
309
310 fn expr_call(&mut self, expr: &ExprCall, beginning_of_line: bool, fixup: FixupContext) {
311 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
312 &expr.func,
313 true,
314 false,
315 Precedence::Unambiguous,
316 );
317 let needs_paren = if let Expr::Field(func) = &*expr.func {
318 matches!(func.member, Member::Named(_))
319 } else {
320 left_prec < Precedence::Unambiguous
321 };
322
323 self.outer_attrs(&expr.attrs);
324 self.expr_beginning_of_line(&expr.func, needs_paren, beginning_of_line, left_fixup);
325 self.word("(");
326 self.call_args(&expr.args);
327 self.word(")");
328 }
329
330 fn prefix_subexpr_call(&mut self, expr: &ExprCall, fixup: FixupContext) {
331 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
332 &expr.func,
333 true,
334 false,
335 Precedence::Unambiguous,
336 );
337 let needs_paren = if let Expr::Field(func) = &*expr.func {
338 matches!(func.member, Member::Named(_))
339 } else {
340 left_prec < Precedence::Unambiguous
341 };
342
343 let beginning_of_line = false;
344 self.prefix_subexpr(&expr.func, needs_paren, beginning_of_line, left_fixup);
345 self.word("(");
346 self.call_args(&expr.args);
347 self.word(")");
348 }
349
350 fn expr_cast(&mut self, expr: &ExprCast, fixup: FixupContext) {
351 let (left_prec, left_fixup) =
352 fixup.leftmost_subexpression_with_operator(&expr.expr, false, false, Precedence::Cast);
353
354 self.outer_attrs(&expr.attrs);
355 self.ibox(INDENT);
356 self.ibox(-INDENT);
357 self.subexpr(&expr.expr, left_prec < Precedence::Cast, left_fixup);
358 self.end();
359 self.space();
360 self.word("as ");
361 self.ty(&expr.ty);
362 self.end();
363 }
364
365 fn expr_closure(&mut self, expr: &ExprClosure, fixup: FixupContext) {
366 self.outer_attrs(&expr.attrs);
367 self.ibox(0);
368 if let Some(bound_lifetimes) = &expr.lifetimes {
369 self.bound_lifetimes(bound_lifetimes);
370 }
371 if expr.constness.is_some() {
372 self.word("const ");
373 }
374 if expr.movability.is_some() {
375 self.word("static ");
376 }
377 if expr.asyncness.is_some() {
378 self.word("async ");
379 }
380 if expr.capture.is_some() {
381 self.word("move ");
382 }
383 self.cbox(INDENT);
384 self.word("|");
385 for pat in expr.inputs.iter().delimited() {
386 if pat.is_first {
387 self.zerobreak();
388 }
389 self.pat(&pat);
390 if !pat.is_last {
391 self.word(",");
392 self.space();
393 }
394 }
395 match &expr.output {
396 ReturnType::Default => {
397 self.word("|");
398 self.space();
399 self.offset(-INDENT);
400 self.end();
401 self.neverbreak();
402 let wrap_in_brace = match &*expr.body {
403 Expr::Match(ExprMatch { attrs, .. }) | Expr::Call(ExprCall { attrs, .. }) => {
404 attr::has_outer(attrs)
405 }
406 body => !is_blocklike(body),
407 };
408 if wrap_in_brace {
409 self.cbox(INDENT);
410 let okay_to_brace = parseable_as_stmt(&expr.body);
411 self.scan_break(BreakToken {
412 pre_break: Some(if okay_to_brace { '{' } else { '(' }),
413 ..BreakToken::default()
414 });
415 self.expr(
416 &expr.body,
417 fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump),
418 );
419 self.scan_break(BreakToken {
420 offset: -INDENT,
421 pre_break: (okay_to_brace && stmt::add_semi(&expr.body)).then_some(';'),
422 post_break: if okay_to_brace { "}" } else { ")" },
423 ..BreakToken::default()
424 });
425 self.end();
426 } else {
427 self.expr(
428 &expr.body,
429 fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump),
430 );
431 }
432 }
433 ReturnType::Type(_arrow, ty) => {
434 if !expr.inputs.is_empty() {
435 self.trailing_comma(true);
436 self.offset(-INDENT);
437 }
438 self.word("|");
439 self.end();
440 self.word(" -> ");
441 self.ty(ty);
442 self.nbsp();
443 self.neverbreak();
444 if matches!(&*expr.body, Expr::Block(body) if body.attrs.is_empty() && body.label.is_none())
445 {
446 self.expr(
447 &expr.body,
448 fixup.rightmost_subexpression_fixup(false, false, Precedence::Jump),
449 );
450 } else {
451 self.cbox(INDENT);
452 self.expr_as_small_block(&expr.body, 0);
453 self.end();
454 }
455 }
456 }
457 self.end();
458 }
459
460 pub fn expr_const(&mut self, expr: &ExprConst) {
461 self.outer_attrs(&expr.attrs);
462 self.word("const ");
463 self.cbox(INDENT);
464 self.small_block(&expr.block, &expr.attrs);
465 self.end();
466 }
467
468 fn expr_continue(&mut self, expr: &ExprContinue) {
469 self.outer_attrs(&expr.attrs);
470 self.word("continue");
471 if let Some(lifetime) = &expr.label {
472 self.nbsp();
473 self.lifetime(lifetime);
474 }
475 }
476
477 fn expr_field(&mut self, expr: &ExprField, beginning_of_line: bool, fixup: FixupContext) {
478 self.outer_attrs(&expr.attrs);
479 self.cbox(INDENT);
480 self.prefix_subexpr_field(expr, beginning_of_line, fixup);
481 self.end();
482 }
483
484 fn prefix_subexpr_field(
485 &mut self,
486 expr: &ExprField,
487 beginning_of_line: bool,
488 fixup: FixupContext,
489 ) {
490 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&expr.base);
491
492 self.prefix_subexpr(
493 &expr.base,
494 left_prec < Precedence::Unambiguous,
495 beginning_of_line,
496 left_fixup,
497 );
498 if !(beginning_of_line && is_short_ident(&expr.base)) {
499 self.scan_break(BreakToken {
500 no_break: self.ends_with('.').then_some(' '),
501 ..BreakToken::default()
502 });
503 }
504 self.word(".");
505 self.member(&expr.member);
506 }
507
508 fn expr_for_loop(&mut self, expr: &ExprForLoop) {
509 self.outer_attrs(&expr.attrs);
510 self.ibox(0);
511 if let Some(label) = &expr.label {
512 self.label(label);
513 }
514 self.word("for ");
515 self.pat(&expr.pat);
516 self.word(" in ");
517 self.neverbreak();
518 self.expr_condition(&expr.expr);
519 self.word("{");
520 self.neverbreak();
521 self.cbox(INDENT);
522 self.hardbreak_if_nonempty();
523 self.inner_attrs(&expr.attrs);
524 for stmt in expr.body.stmts.iter().delimited() {
525 self.stmt(&stmt, stmt.is_last);
526 }
527 self.offset(-INDENT);
528 self.end();
529 self.word("}");
530 self.end();
531 }
532
533 fn expr_group(&mut self, expr: &ExprGroup, fixup: FixupContext) {
534 self.outer_attrs(&expr.attrs);
535 self.expr(&expr.expr, fixup);
536 }
537
538 fn expr_if(&mut self, expr: &ExprIf) {
539 self.outer_attrs(&expr.attrs);
540 self.cbox(INDENT);
541 self.word("if ");
542 self.cbox(-INDENT);
543 self.expr_condition(&expr.cond);
544 self.end();
545 if let Some((_else_token, else_branch)) = &expr.else_branch {
546 let mut else_branch = &**else_branch;
547 self.small_block(&expr.then_branch, &[]);
548 loop {
549 self.word(" else ");
550 match else_branch {
551 Expr::If(expr) => {
552 self.word("if ");
553 self.cbox(-INDENT);
554 self.expr_condition(&expr.cond);
555 self.end();
556 self.small_block(&expr.then_branch, &[]);
557 if let Some((_else_token, next)) = &expr.else_branch {
558 else_branch = next;
559 continue;
560 }
561 }
562 Expr::Block(expr) => {
563 self.small_block(&expr.block, &[]);
564 }
565 other => self.expr_as_small_block(other, INDENT),
568 }
569 break;
570 }
571 } else if expr.then_branch.stmts.is_empty() {
572 self.word("{}");
573 } else {
574 self.word("{");
575 self.hardbreak();
576 for stmt in expr.then_branch.stmts.iter().delimited() {
577 self.stmt(&stmt, stmt.is_last);
578 }
579 self.offset(-INDENT);
580 self.word("}");
581 }
582 self.end();
583 }
584
585 fn expr_index(&mut self, expr: &ExprIndex, beginning_of_line: bool, fixup: FixupContext) {
586 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
587 &expr.expr,
588 true,
589 false,
590 Precedence::Unambiguous,
591 );
592
593 self.outer_attrs(&expr.attrs);
594 self.expr_beginning_of_line(
595 &expr.expr,
596 left_prec < Precedence::Unambiguous,
597 beginning_of_line,
598 left_fixup,
599 );
600 self.word("[");
601 self.expr(&expr.index, FixupContext::NONE);
602 self.word("]");
603 }
604
605 fn prefix_subexpr_index(
606 &mut self,
607 expr: &ExprIndex,
608 beginning_of_line: bool,
609 fixup: FixupContext,
610 ) {
611 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_operator(
612 &expr.expr,
613 true,
614 false,
615 Precedence::Unambiguous,
616 );
617
618 self.prefix_subexpr(
619 &expr.expr,
620 left_prec < Precedence::Unambiguous,
621 beginning_of_line,
622 left_fixup,
623 );
624 self.word("[");
625 self.expr(&expr.index, FixupContext::NONE);
626 self.word("]");
627 }
628
629 fn expr_infer(&mut self, expr: &ExprInfer) {
630 self.outer_attrs(&expr.attrs);
631 self.word("_");
632 }
633
634 fn expr_let(&mut self, expr: &ExprLet, fixup: FixupContext) {
635 let (right_prec, right_fixup) = fixup.rightmost_subexpression(&expr.expr, Precedence::Let);
636
637 self.outer_attrs(&expr.attrs);
638 self.ibox(0);
639 self.word("let ");
640 self.ibox(0);
641 self.pat(&expr.pat);
642 self.end();
643 self.word(" = ");
644 self.neverbreak();
645 self.ibox(0);
646 self.subexpr(&expr.expr, right_prec < Precedence::Let, right_fixup);
647 self.end();
648 self.end();
649 }
650
651 pub fn expr_lit(&mut self, expr: &ExprLit) {
652 self.outer_attrs(&expr.attrs);
653 self.lit(&expr.lit);
654 }
655
656 fn expr_loop(&mut self, expr: &ExprLoop) {
657 self.outer_attrs(&expr.attrs);
658 if let Some(label) = &expr.label {
659 self.label(label);
660 }
661 self.word("loop {");
662 self.cbox(INDENT);
663 self.hardbreak_if_nonempty();
664 self.inner_attrs(&expr.attrs);
665 for stmt in expr.body.stmts.iter().delimited() {
666 self.stmt(&stmt, stmt.is_last);
667 }
668 self.offset(-INDENT);
669 self.end();
670 self.word("}");
671 }
672
673 pub fn expr_macro(&mut self, expr: &ExprMacro) {
674 self.outer_attrs(&expr.attrs);
675 let semicolon = false;
676 self.mac(&expr.mac, None, semicolon);
677 }
678
679 fn expr_match(&mut self, expr: &ExprMatch) {
680 self.outer_attrs(&expr.attrs);
681 self.ibox(0);
682 self.word("match ");
683 self.expr_condition(&expr.expr);
684 self.word("{");
685 self.neverbreak();
686 self.cbox(INDENT);
687 self.hardbreak_if_nonempty();
688 self.inner_attrs(&expr.attrs);
689 for arm in &expr.arms {
690 self.arm(arm);
691 self.hardbreak();
692 }
693 self.offset(-INDENT);
694 self.end();
695 self.word("}");
696 self.end();
697 }
698
699 fn expr_method_call(
700 &mut self,
701 expr: &ExprMethodCall,
702 beginning_of_line: bool,
703 fixup: FixupContext,
704 ) {
705 self.outer_attrs(&expr.attrs);
706 self.cbox(INDENT);
707 let unindent_call_args = beginning_of_line && is_short_ident(&expr.receiver);
708 self.prefix_subexpr_method_call(expr, beginning_of_line, unindent_call_args, fixup);
709 self.end();
710 }
711
712 fn prefix_subexpr_method_call(
713 &mut self,
714 expr: &ExprMethodCall,
715 beginning_of_line: bool,
716 unindent_call_args: bool,
717 fixup: FixupContext,
718 ) {
719 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&expr.receiver);
720
721 self.prefix_subexpr(
722 &expr.receiver,
723 left_prec < Precedence::Unambiguous,
724 beginning_of_line,
725 left_fixup,
726 );
727 if !(beginning_of_line && is_short_ident(&expr.receiver)) {
728 self.scan_break(BreakToken {
729 no_break: self.ends_with('.').then_some(' '),
730 ..BreakToken::default()
731 });
732 }
733 self.word(".");
734 self.ident(&expr.method);
735 if let Some(turbofish) = &expr.turbofish {
736 self.angle_bracketed_generic_arguments(turbofish, PathKind::Expr);
737 }
738 self.cbox(if unindent_call_args { -INDENT } else { 0 });
739 self.word("(");
740 self.call_args(&expr.args);
741 self.word(")");
742 self.end();
743 }
744
745 fn expr_paren(&mut self, expr: &ExprParen) {
746 self.outer_attrs(&expr.attrs);
747 self.word("(");
748 self.expr(&expr.expr, FixupContext::NONE);
749 self.word(")");
750 }
751
752 pub fn expr_path(&mut self, expr: &ExprPath) {
753 self.outer_attrs(&expr.attrs);
754 self.qpath(&expr.qself, &expr.path, PathKind::Expr);
755 }
756
757 pub fn expr_range(&mut self, expr: &ExprRange, fixup: FixupContext) {
758 self.outer_attrs(&expr.attrs);
759 if let Some(start) = &expr.start {
760 let (left_prec, left_fixup) =
761 fixup.leftmost_subexpression_with_operator(start, true, false, Precedence::Range);
762 self.subexpr(start, left_prec <= Precedence::Range, left_fixup);
763 } else if self.ends_with('.') {
764 self.nbsp();
765 }
766 self.word(match expr.limits {
767 RangeLimits::HalfOpen(_) => "..",
768 RangeLimits::Closed(_) => "..=",
769 });
770 if let Some(end) = &expr.end {
771 let right_fixup = fixup.rightmost_subexpression_fixup(false, true, Precedence::Range);
772 let right_prec = right_fixup.rightmost_subexpression_precedence(end);
773 self.subexpr(end, right_prec <= Precedence::Range, right_fixup);
774 }
775 }
776
777 fn expr_raw_addr(&mut self, expr: &ExprRawAddr, fixup: FixupContext) {
778 let (right_prec, right_fixup) =
779 fixup.rightmost_subexpression(&expr.expr, Precedence::Prefix);
780
781 self.outer_attrs(&expr.attrs);
782 self.word("&raw ");
783 self.pointer_mutability(&expr.mutability);
784 self.nbsp();
785 self.subexpr(&expr.expr, right_prec < Precedence::Prefix, right_fixup);
786 }
787
788 fn expr_reference(&mut self, expr: &ExprReference, fixup: FixupContext) {
789 let (right_prec, right_fixup) =
790 fixup.rightmost_subexpression(&expr.expr, Precedence::Prefix);
791
792 self.outer_attrs(&expr.attrs);
793 self.word("&");
794 if expr.mutability.is_some() {
795 self.word("mut ");
796 }
797 self.subexpr(&expr.expr, right_prec < Precedence::Prefix, right_fixup);
798 }
799
800 fn expr_repeat(&mut self, expr: &ExprRepeat) {
801 self.outer_attrs(&expr.attrs);
802 self.word("[");
803 self.expr(&expr.expr, FixupContext::NONE);
804 self.word("; ");
805 self.expr(&expr.len, FixupContext::NONE);
806 self.word("]");
807 }
808
809 fn expr_return(&mut self, expr: &ExprReturn, fixup: FixupContext) {
810 self.outer_attrs(&expr.attrs);
811 self.word("return");
812 if let Some(value) = &expr.expr {
813 self.nbsp();
814 self.expr(
815 value,
816 fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
817 );
818 }
819 }
820
821 fn expr_struct(&mut self, expr: &ExprStruct) {
822 self.outer_attrs(&expr.attrs);
823 self.cbox(INDENT);
824 self.ibox(-INDENT);
825 self.qpath(&expr.qself, &expr.path, PathKind::Expr);
826 self.end();
827 self.word(" {");
828 self.space_if_nonempty();
829 for field_value in expr.fields.iter().delimited() {
830 self.field_value(&field_value);
831 self.trailing_comma_or_space(field_value.is_last && expr.rest.is_none());
832 }
833 if let Some(rest) = &expr.rest {
834 self.word("..");
835 self.expr(rest, FixupContext::NONE);
836 self.space();
837 }
838 self.offset(-INDENT);
839 self.end_with_max_width(34);
840 self.word("}");
841 }
842
843 fn expr_try(&mut self, expr: &ExprTry, beginning_of_line: bool, fixup: FixupContext) {
844 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&expr.expr);
845
846 self.outer_attrs(&expr.attrs);
847 self.expr_beginning_of_line(
848 &expr.expr,
849 left_prec < Precedence::Unambiguous,
850 beginning_of_line,
851 left_fixup,
852 );
853 self.word("?");
854 }
855
856 fn prefix_subexpr_try(&mut self, expr: &ExprTry, beginning_of_line: bool, fixup: FixupContext) {
857 let (left_prec, left_fixup) = fixup.leftmost_subexpression_with_dot(&expr.expr);
858
859 self.prefix_subexpr(
860 &expr.expr,
861 left_prec < Precedence::Unambiguous,
862 beginning_of_line,
863 left_fixup,
864 );
865 self.word("?");
866 }
867
868 fn expr_try_block(&mut self, expr: &ExprTryBlock) {
869 self.outer_attrs(&expr.attrs);
870 self.word("try ");
871 self.cbox(INDENT);
872 self.small_block(&expr.block, &expr.attrs);
873 self.end();
874 }
875
876 fn expr_tuple(&mut self, expr: &ExprTuple) {
877 self.outer_attrs(&expr.attrs);
878 self.word("(");
879 self.cbox(INDENT);
880 self.zerobreak();
881 for elem in expr.elems.iter().delimited() {
882 self.expr(&elem, FixupContext::NONE);
883 if expr.elems.len() == 1 {
884 self.word(",");
885 self.zerobreak();
886 } else {
887 self.trailing_comma(elem.is_last);
888 }
889 }
890 self.offset(-INDENT);
891 self.end();
892 self.word(")");
893 }
894
895 fn expr_unary(&mut self, expr: &ExprUnary, fixup: FixupContext) {
896 let (right_prec, right_fixup) =
897 fixup.rightmost_subexpression(&expr.expr, Precedence::Prefix);
898
899 self.outer_attrs(&expr.attrs);
900 self.unary_operator(&expr.op);
901 self.subexpr(&expr.expr, right_prec < Precedence::Prefix, right_fixup);
902 }
903
904 fn expr_unsafe(&mut self, expr: &ExprUnsafe) {
905 self.outer_attrs(&expr.attrs);
906 self.word("unsafe ");
907 self.cbox(INDENT);
908 self.small_block(&expr.block, &expr.attrs);
909 self.end();
910 }
911
912 #[cfg(not(feature = "verbatim"))]
913 fn expr_verbatim(&mut self, expr: &TokenStream, _fixup: FixupContext) {
914 if !expr.is_empty() {
915 unimplemented!("Expr::Verbatim `{}`", expr);
916 }
917 }
918
919 #[cfg(feature = "verbatim")]
920 fn expr_verbatim(&mut self, tokens: &TokenStream, fixup: FixupContext) {
921 use syn::parse::discouraged::Speculative;
922 use syn::parse::{Parse, ParseStream, Result};
923 use syn::{parenthesized, Ident};
924
925 enum ExprVerbatim {
926 Empty,
927 Ellipsis,
928 Become(Become),
929 Builtin(Builtin),
930 }
931
932 struct Become {
933 attrs: Vec<Attribute>,
934 tail_call: Expr,
935 }
936
937 struct Builtin {
938 attrs: Vec<Attribute>,
939 name: Ident,
940 args: TokenStream,
941 }
942
943 mod kw {
944 syn::custom_keyword!(builtin);
945 syn::custom_keyword!(raw);
946 }
947
948 impl Parse for ExprVerbatim {
949 fn parse(input: ParseStream) -> Result<Self> {
950 let ahead = input.fork();
951 let attrs = ahead.call(Attribute::parse_outer)?;
952 let lookahead = ahead.lookahead1();
953 if input.is_empty() {
954 Ok(ExprVerbatim::Empty)
955 } else if lookahead.peek(Token![become]) {
956 input.advance_to(&ahead);
957 input.parse::<Token![become]>()?;
958 let tail_call: Expr = input.parse()?;
959 Ok(ExprVerbatim::Become(Become { attrs, tail_call }))
960 } else if lookahead.peek(kw::builtin) {
961 input.advance_to(&ahead);
962 input.parse::<kw::builtin>()?;
963 input.parse::<Token![#]>()?;
964 let name: Ident = input.parse()?;
965 let args;
966 parenthesized!(args in input);
967 let args: TokenStream = args.parse()?;
968 Ok(ExprVerbatim::Builtin(Builtin { attrs, name, args }))
969 } else if lookahead.peek(Token![...]) {
970 input.parse::<Token![...]>()?;
971 Ok(ExprVerbatim::Ellipsis)
972 } else {
973 Err(lookahead.error())
974 }
975 }
976 }
977
978 let expr: ExprVerbatim = match syn::parse2(tokens.clone()) {
979 Ok(expr) => expr,
980 Err(_) => unimplemented!("Expr::Verbatim `{}`", tokens),
981 };
982
983 match expr {
984 ExprVerbatim::Empty => {}
985 ExprVerbatim::Ellipsis => {
986 self.word("...");
987 }
988 ExprVerbatim::Become(expr) => {
989 self.outer_attrs(&expr.attrs);
990 self.word("become");
991 self.nbsp();
992 self.expr(
993 &expr.tail_call,
994 fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
995 );
996 }
997 ExprVerbatim::Builtin(expr) => {
998 self.outer_attrs(&expr.attrs);
999 self.word("builtin # ");
1000 self.ident(&expr.name);
1001 self.word("(");
1002 if !expr.args.is_empty() {
1003 self.cbox(INDENT);
1004 self.zerobreak();
1005 self.ibox(0);
1006 self.macro_rules_tokens(expr.args, false);
1007 self.end();
1008 self.zerobreak();
1009 self.offset(-INDENT);
1010 self.end();
1011 }
1012 self.word(")");
1013 }
1014 }
1015 }
1016
1017 fn expr_while(&mut self, expr: &ExprWhile) {
1018 self.outer_attrs(&expr.attrs);
1019 if let Some(label) = &expr.label {
1020 self.label(label);
1021 }
1022 self.word("while ");
1023 self.expr_condition(&expr.cond);
1024 self.word("{");
1025 self.neverbreak();
1026 self.cbox(INDENT);
1027 self.hardbreak_if_nonempty();
1028 self.inner_attrs(&expr.attrs);
1029 for stmt in expr.body.stmts.iter().delimited() {
1030 self.stmt(&stmt, stmt.is_last);
1031 }
1032 self.offset(-INDENT);
1033 self.end();
1034 self.word("}");
1035 }
1036
1037 fn expr_yield(&mut self, expr: &ExprYield, fixup: FixupContext) {
1038 self.outer_attrs(&expr.attrs);
1039 self.word("yield");
1040 if let Some(value) = &expr.expr {
1041 self.nbsp();
1042 self.expr(
1043 value,
1044 fixup.rightmost_subexpression_fixup(true, false, Precedence::Jump),
1045 );
1046 }
1047 }
1048
1049 fn label(&mut self, label: &Label) {
1050 self.lifetime(&label.name);
1051 self.word(": ");
1052 }
1053
1054 fn field_value(&mut self, field_value: &FieldValue) {
1055 self.outer_attrs(&field_value.attrs);
1056 self.member(&field_value.member);
1057 if field_value.colon_token.is_some() {
1058 self.word(": ");
1059 self.ibox(0);
1060 self.expr(&field_value.expr, FixupContext::NONE);
1061 self.end();
1062 }
1063 }
1064
1065 fn arm(&mut self, arm: &Arm) {
1066 self.outer_attrs(&arm.attrs);
1067 self.ibox(0);
1068 self.pat(&arm.pat);
1069 if let Some((_if_token, guard)) = &arm.guard {
1070 self.word(" if ");
1071 self.expr(guard, FixupContext::NONE);
1072 }
1073 self.word(" => ");
1074 let empty_block;
1075 let mut body = &*arm.body;
1076 while let Expr::Block(expr) = body {
1077 if expr.attrs.is_empty() && expr.label.is_none() {
1078 let mut stmts = expr.block.stmts.iter();
1079 if let (Some(Stmt::Expr(inner, None)), None) = (stmts.next(), stmts.next()) {
1080 body = inner;
1081 continue;
1082 }
1083 }
1084 break;
1085 }
1086 if let Expr::Tuple(expr) = body {
1087 if expr.elems.is_empty() && expr.attrs.is_empty() {
1088 empty_block = Expr::Block(ExprBlock {
1089 attrs: Vec::new(),
1090 label: None,
1091 block: Block {
1092 brace_token: token::Brace::default(),
1093 stmts: Vec::new(),
1094 },
1095 });
1096 body = &empty_block;
1097 }
1098 }
1099 if let Expr::Block(body) = body {
1100 if let Some(label) = &body.label {
1101 self.label(label);
1102 }
1103 self.word("{");
1104 self.neverbreak();
1105 self.cbox(INDENT);
1106 self.hardbreak_if_nonempty();
1107 self.inner_attrs(&body.attrs);
1108 for stmt in body.block.stmts.iter().delimited() {
1109 self.stmt(&stmt, stmt.is_last);
1110 }
1111 self.offset(-INDENT);
1112 self.end();
1113 self.word("}");
1114 } else {
1115 self.neverbreak();
1116 self.cbox(INDENT);
1117 let okay_to_brace = parseable_as_stmt(body);
1118 self.scan_break(BreakToken {
1119 pre_break: Some(if okay_to_brace { '{' } else { '(' }),
1120 ..BreakToken::default()
1121 });
1122 self.expr_beginning_of_line(body, false, true, FixupContext::new_match_arm());
1123 self.scan_break(BreakToken {
1124 offset: -INDENT,
1125 pre_break: (okay_to_brace && stmt::add_semi(body)).then_some(';'),
1126 post_break: if okay_to_brace { "}" } else { ")," },
1127 no_break: classify::requires_comma_to_be_match_arm(body).then_some(','),
1128 ..BreakToken::default()
1129 });
1130 self.end();
1131 }
1132 self.end();
1133 }
1134
1135 fn call_args(&mut self, args: &Punctuated<Expr, Token![,]>) {
1136 let mut iter = args.iter();
1137 match (iter.next(), iter.next()) {
1138 (Some(expr), None) if is_blocklike(expr) => {
1139 self.expr(expr, FixupContext::NONE);
1140 }
1141 _ => {
1142 self.cbox(INDENT);
1143 self.zerobreak();
1144 for arg in args.iter().delimited() {
1145 self.expr(&arg, FixupContext::NONE);
1146 self.trailing_comma(arg.is_last);
1147 }
1148 self.offset(-INDENT);
1149 self.end();
1150 }
1151 }
1152 }
1153
1154 pub fn small_block(&mut self, block: &Block, attrs: &[Attribute]) {
1155 self.word("{");
1156 if attr::has_inner(attrs) || !block.stmts.is_empty() {
1157 self.space();
1158 self.inner_attrs(attrs);
1159 match block.stmts.as_slice() {
1160 [Stmt::Expr(expr, None)] if stmt::break_after(expr) => {
1161 self.ibox(0);
1162 self.expr_beginning_of_line(expr, false, true, FixupContext::new_stmt());
1163 self.end();
1164 self.space();
1165 }
1166 _ => {
1167 for stmt in block.stmts.iter().delimited() {
1168 self.stmt(&stmt, stmt.is_last);
1169 }
1170 }
1171 }
1172 self.offset(-INDENT);
1173 }
1174 self.word("}");
1175 }
1176
1177 pub fn expr_as_small_block(&mut self, expr: &Expr, indent: isize) {
1178 self.word("{");
1179 self.space();
1180 self.ibox(indent);
1181 self.expr_beginning_of_line(expr, false, true, FixupContext::new_stmt());
1182 self.end();
1183 self.space();
1184 self.offset(-INDENT);
1185 self.word("}");
1186 }
1187
1188 pub fn member(&mut self, member: &Member) {
1189 match member {
1190 Member::Named(ident) => self.ident(ident),
1191 Member::Unnamed(index) => self.index(index),
1192 }
1193 }
1194
1195 fn index(&mut self, member: &Index) {
1196 self.word(member.index.to_string());
1197 }
1198
1199 fn binary_operator(&mut self, op: &BinOp) {
1200 self.word(
1201 match op {
1202 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
1203 BinOp::Add(_) => "+",
1204 BinOp::Sub(_) => "-",
1205 BinOp::Mul(_) => "*",
1206 BinOp::Div(_) => "/",
1207 BinOp::Rem(_) => "%",
1208 BinOp::And(_) => "&&",
1209 BinOp::Or(_) => "||",
1210 BinOp::BitXor(_) => "^",
1211 BinOp::BitAnd(_) => "&",
1212 BinOp::BitOr(_) => "|",
1213 BinOp::Shl(_) => "<<",
1214 BinOp::Shr(_) => ">>",
1215 BinOp::Eq(_) => "==",
1216 BinOp::Lt(_) => "<",
1217 BinOp::Le(_) => "<=",
1218 BinOp::Ne(_) => "!=",
1219 BinOp::Ge(_) => ">=",
1220 BinOp::Gt(_) => ">",
1221 BinOp::AddAssign(_) => "+=",
1222 BinOp::SubAssign(_) => "-=",
1223 BinOp::MulAssign(_) => "*=",
1224 BinOp::DivAssign(_) => "/=",
1225 BinOp::RemAssign(_) => "%=",
1226 BinOp::BitXorAssign(_) => "^=",
1227 BinOp::BitAndAssign(_) => "&=",
1228 BinOp::BitOrAssign(_) => "|=",
1229 BinOp::ShlAssign(_) => "<<=",
1230 BinOp::ShrAssign(_) => ">>=",
1231 _ => unimplemented!("unknown BinOp"),
1232 },
1233 );
1234 }
1235
1236 fn unary_operator(&mut self, op: &UnOp) {
1237 self.word(
1238 match op {
1239 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
1240 UnOp::Deref(_) => "*",
1241 UnOp::Not(_) => "!",
1242 UnOp::Neg(_) => "-",
1243 _ => unimplemented!("unknown UnOp"),
1244 },
1245 );
1246 }
1247
1248 fn pointer_mutability(&mut self, mutability: &PointerMutability) {
1249 match mutability {
1250 PointerMutability::Const(_) => self.word("const"),
1251 PointerMutability::Mut(_) => self.word("mut"),
1252 }
1253 }
1254}
1255
1256fn needs_newline_if_wrap(expr: &Expr) -> bool {
1257 match expr {
1258 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
1259 Expr::Array(_)
1260 | Expr::Async(_)
1261 | Expr::Block(_)
1262 | Expr::Break(ExprBreak { expr: None, .. })
1263 | Expr::Closure(_)
1264 | Expr::Const(_)
1265 | Expr::Continue(_)
1266 | Expr::ForLoop(_)
1267 | Expr::If(_)
1268 | Expr::Infer(_)
1269 | Expr::Lit(_)
1270 | Expr::Loop(_)
1271 | Expr::Macro(_)
1272 | Expr::Match(_)
1273 | Expr::Path(_)
1274 | Expr::Range(ExprRange { end: None, .. })
1275 | Expr::Repeat(_)
1276 | Expr::Return(ExprReturn { expr: None, .. })
1277 | Expr::Struct(_)
1278 | Expr::TryBlock(_)
1279 | Expr::Tuple(_)
1280 | Expr::Unsafe(_)
1281 | Expr::Verbatim(_)
1282 | Expr::While(_)
1283 | Expr::Yield(ExprYield { expr: None, .. }) => false,
1284
1285 Expr::Assign(_)
1286 | Expr::Await(_)
1287 | Expr::Binary(_)
1288 | Expr::Cast(_)
1289 | Expr::Field(_)
1290 | Expr::Index(_)
1291 | Expr::MethodCall(_) => true,
1292
1293 Expr::Break(ExprBreak { expr: Some(e), .. })
1294 | Expr::Call(ExprCall { func: e, .. })
1295 | Expr::Group(ExprGroup { expr: e, .. })
1296 | Expr::Let(ExprLet { expr: e, .. })
1297 | Expr::Paren(ExprParen { expr: e, .. })
1298 | Expr::Range(ExprRange { end: Some(e), .. })
1299 | Expr::RawAddr(ExprRawAddr { expr: e, .. })
1300 | Expr::Reference(ExprReference { expr: e, .. })
1301 | Expr::Return(ExprReturn { expr: Some(e), .. })
1302 | Expr::Try(ExprTry { expr: e, .. })
1303 | Expr::Unary(ExprUnary { expr: e, .. })
1304 | Expr::Yield(ExprYield { expr: Some(e), .. }) => needs_newline_if_wrap(e),
1305
1306 _ => false,
1307 }
1308}
1309
1310fn is_short_ident(expr: &Expr) -> bool {
1311 if let Expr::Path(expr) = expr {
1312 return expr.attrs.is_empty()
1313 && expr.qself.is_none()
1314 && expr
1315 .path
1316 .get_ident()
1317 .map_or(false, |ident| ident.to_string().len() as isize <= INDENT);
1318 }
1319 false
1320}
1321
1322fn is_blocklike(expr: &Expr) -> bool {
1323 match expr {
1324 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
1325 Expr::Array(ExprArray { attrs, .. })
1326 | Expr::Async(ExprAsync { attrs, .. })
1327 | Expr::Block(ExprBlock { attrs, .. })
1328 | Expr::Closure(ExprClosure { attrs, .. })
1329 | Expr::Const(ExprConst { attrs, .. })
1330 | Expr::Struct(ExprStruct { attrs, .. })
1331 | Expr::TryBlock(ExprTryBlock { attrs, .. })
1332 | Expr::Tuple(ExprTuple { attrs, .. })
1333 | Expr::Unsafe(ExprUnsafe { attrs, .. }) => !attr::has_outer(attrs),
1334
1335 Expr::Assign(_)
1336 | Expr::Await(_)
1337 | Expr::Binary(_)
1338 | Expr::Break(_)
1339 | Expr::Call(_)
1340 | Expr::Cast(_)
1341 | Expr::Continue(_)
1342 | Expr::Field(_)
1343 | Expr::ForLoop(_)
1344 | Expr::If(_)
1345 | Expr::Index(_)
1346 | Expr::Infer(_)
1347 | Expr::Let(_)
1348 | Expr::Lit(_)
1349 | Expr::Loop(_)
1350 | Expr::Macro(_)
1351 | Expr::Match(_)
1352 | Expr::MethodCall(_)
1353 | Expr::Paren(_)
1354 | Expr::Path(_)
1355 | Expr::Range(_)
1356 | Expr::RawAddr(_)
1357 | Expr::Reference(_)
1358 | Expr::Repeat(_)
1359 | Expr::Return(_)
1360 | Expr::Try(_)
1361 | Expr::Unary(_)
1362 | Expr::Verbatim(_)
1363 | Expr::While(_)
1364 | Expr::Yield(_) => false,
1365
1366 Expr::Group(e) => is_blocklike(&e.expr),
1367
1368 _ => false,
1369 }
1370}
1371
1372pub fn simple_block(expr: &Expr) -> Option<&ExprBlock> {
1373 if let Expr::Block(expr) = expr {
1374 if expr.attrs.is_empty() && expr.label.is_none() {
1375 return Some(expr);
1376 }
1377 }
1378 None
1379}
1380
1381fn parseable_as_stmt(mut expr: &Expr) -> bool {
1386 loop {
1387 match expr {
1388 #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
1389 Expr::Array(_)
1390 | Expr::Async(_)
1391 | Expr::Block(_)
1392 | Expr::Break(_)
1393 | Expr::Closure(_)
1394 | Expr::Const(_)
1395 | Expr::Continue(_)
1396 | Expr::ForLoop(_)
1397 | Expr::If(_)
1398 | Expr::Infer(_)
1399 | Expr::Lit(_)
1400 | Expr::Loop(_)
1401 | Expr::Macro(_)
1402 | Expr::Match(_)
1403 | Expr::Paren(_)
1404 | Expr::Path(_)
1405 | Expr::RawAddr(_)
1406 | Expr::Reference(_)
1407 | Expr::Repeat(_)
1408 | Expr::Return(_)
1409 | Expr::Struct(_)
1410 | Expr::TryBlock(_)
1411 | Expr::Tuple(_)
1412 | Expr::Unary(_)
1413 | Expr::Unsafe(_)
1414 | Expr::Verbatim(_)
1415 | Expr::While(_)
1416 | Expr::Yield(_) => return true,
1417
1418 Expr::Let(_) => return false,
1419
1420 Expr::Assign(e) => {
1421 if !classify::requires_semi_to_be_stmt(&e.left) {
1422 return false;
1423 }
1424 expr = &e.left;
1425 }
1426 Expr::Await(e) => expr = &e.base,
1427 Expr::Binary(e) => {
1428 if !classify::requires_semi_to_be_stmt(&e.left) {
1429 return false;
1430 }
1431 expr = &e.left;
1432 }
1433 Expr::Call(e) => {
1434 if !classify::requires_semi_to_be_stmt(&e.func) {
1435 return false;
1436 }
1437 expr = &e.func;
1438 }
1439 Expr::Cast(e) => {
1440 if !classify::requires_semi_to_be_stmt(&e.expr) {
1441 return false;
1442 }
1443 expr = &e.expr;
1444 }
1445 Expr::Field(e) => expr = &e.base,
1446 Expr::Group(e) => expr = &e.expr,
1447 Expr::Index(e) => {
1448 if !classify::requires_semi_to_be_stmt(&e.expr) {
1449 return false;
1450 }
1451 expr = &e.expr;
1452 }
1453 Expr::MethodCall(e) => expr = &e.receiver,
1454 Expr::Range(e) => match &e.start {
1455 None => return true,
1456 Some(start) => {
1457 if !classify::requires_semi_to_be_stmt(start) {
1458 return false;
1459 }
1460 expr = start;
1461 }
1462 },
1463 Expr::Try(e) => expr = &e.expr,
1464
1465 _ => return false,
1466 }
1467 }
1468}