1use std::fmt::Write;
2
3use ast::{ForLoopKind, MatchKind};
4use itertools::{Itertools, Position};
5use rustc_ast::ptr::P;
6use rustc_ast::util::classify;
7use rustc_ast::util::literal::escape_byte_str_symbol;
8use rustc_ast::util::parser::{self, ExprPrecedence, Fixity};
9use rustc_ast::{
10 self as ast, BlockCheckMode, FormatAlignment, FormatArgPosition, FormatArgsPiece, FormatCount,
11 FormatDebugHex, FormatSign, FormatTrait, YieldKind, token,
12};
13
14use crate::pp::Breaks::Inconsistent;
15use crate::pprust::state::fixup::FixupContext;
16use crate::pprust::state::{AnnNode, INDENT_UNIT, PrintState, State};
17
18impl<'a> State<'a> {
19 fn print_else(&mut self, els: Option<&ast::Expr>) {
20 if let Some(_else) = els {
21 match &_else.kind {
22 ast::ExprKind::If(i, then, e) => {
24 self.cbox(INDENT_UNIT - 1);
25 self.ibox(0);
26 self.word(" else if ");
27 self.print_expr_as_cond(i);
28 self.space();
29 self.print_block(then);
30 self.print_else(e.as_deref())
31 }
32 ast::ExprKind::Block(b, _) => {
34 self.cbox(INDENT_UNIT - 1);
35 self.ibox(0);
36 self.word(" else ");
37 self.print_block(b)
38 }
39 _ => {
41 panic!("print_if saw if with weird alternative");
42 }
43 }
44 }
45 }
46
47 fn print_if(&mut self, test: &ast::Expr, blk: &ast::Block, elseopt: Option<&ast::Expr>) {
48 self.head("if");
49 self.print_expr_as_cond(test);
50 self.space();
51 self.print_block(blk);
52 self.print_else(elseopt)
53 }
54
55 fn print_call_post(&mut self, args: &[P<ast::Expr>]) {
56 self.popen();
57 self.commasep_exprs(Inconsistent, args);
58 self.pclose()
59 }
60
61 fn print_expr_as_cond(&mut self, expr: &ast::Expr) {
64 self.print_expr_cond_paren(expr, Self::cond_needs_par(expr), FixupContext::new_cond())
65 }
66
67 fn cond_needs_par(expr: &ast::Expr) -> bool {
72 match expr.kind {
73 ast::ExprKind::Break(..)
74 | ast::ExprKind::Closure(..)
75 | ast::ExprKind::Ret(..)
76 | ast::ExprKind::Yeet(..) => true,
77 _ => parser::contains_exterior_struct_lit(expr),
78 }
79 }
80
81 pub(super) fn print_expr_cond_paren(
83 &mut self,
84 expr: &ast::Expr,
85 needs_par: bool,
86 mut fixup: FixupContext,
87 ) {
88 if needs_par {
89 self.popen();
90
91 fixup = FixupContext::default();
103 }
104
105 self.print_expr(expr, fixup);
106
107 if needs_par {
108 self.pclose();
109 }
110 }
111
112 fn print_expr_vec(&mut self, exprs: &[P<ast::Expr>]) {
113 self.ibox(INDENT_UNIT);
114 self.word("[");
115 self.commasep_exprs(Inconsistent, exprs);
116 self.word("]");
117 self.end();
118 }
119
120 pub(super) fn print_expr_anon_const(
121 &mut self,
122 expr: &ast::AnonConst,
123 attrs: &[ast::Attribute],
124 ) {
125 self.ibox(INDENT_UNIT);
126 self.word("const");
127 self.nbsp();
128 if let ast::ExprKind::Block(block, None) = &expr.value.kind {
129 self.cbox(0);
130 self.ibox(0);
131 self.print_block_with_attrs(block, attrs);
132 } else {
133 self.print_expr(&expr.value, FixupContext::default());
134 }
135 self.end();
136 }
137
138 fn print_expr_repeat(&mut self, element: &ast::Expr, count: &ast::AnonConst) {
139 self.ibox(INDENT_UNIT);
140 self.word("[");
141 self.print_expr(element, FixupContext::default());
142 self.word_space(";");
143 self.print_expr(&count.value, FixupContext::default());
144 self.word("]");
145 self.end();
146 }
147
148 fn print_expr_struct(
149 &mut self,
150 qself: &Option<P<ast::QSelf>>,
151 path: &ast::Path,
152 fields: &[ast::ExprField],
153 rest: &ast::StructRest,
154 ) {
155 if let Some(qself) = qself {
156 self.print_qpath(path, qself, true);
157 } else {
158 self.print_path(path, true, 0);
159 }
160 self.nbsp();
161 self.word("{");
162 let has_rest = match rest {
163 ast::StructRest::Base(_) | ast::StructRest::Rest(_) => true,
164 ast::StructRest::None => false,
165 };
166 if fields.is_empty() && !has_rest {
167 self.word("}");
168 return;
169 }
170 self.cbox(0);
171 for (pos, field) in fields.iter().with_position() {
172 let is_first = matches!(pos, Position::First | Position::Only);
173 let is_last = matches!(pos, Position::Last | Position::Only);
174 self.maybe_print_comment(field.span.hi());
175 self.print_outer_attributes(&field.attrs);
176 if is_first {
177 self.space_if_not_bol();
178 }
179 if !field.is_shorthand {
180 self.print_ident(field.ident);
181 self.word_nbsp(":");
182 }
183 self.print_expr(&field.expr, FixupContext::default());
184 if !is_last || has_rest {
185 self.word_space(",");
186 } else {
187 self.trailing_comma_or_space();
188 }
189 }
190 if has_rest {
191 if fields.is_empty() {
192 self.space();
193 }
194 self.word("..");
195 if let ast::StructRest::Base(expr) = rest {
196 self.print_expr(expr, FixupContext::default());
197 }
198 self.space();
199 }
200 self.offset(-INDENT_UNIT);
201 self.end();
202 self.word("}");
203 }
204
205 fn print_expr_tup(&mut self, exprs: &[P<ast::Expr>]) {
206 self.popen();
207 self.commasep_exprs(Inconsistent, exprs);
208 if exprs.len() == 1 {
209 self.word(",");
210 }
211 self.pclose()
212 }
213
214 fn print_expr_call(&mut self, func: &ast::Expr, args: &[P<ast::Expr>], fixup: FixupContext) {
215 let needs_paren = match func.kind {
216 ast::ExprKind::Field(_, name) => !name.is_numeric(),
219 _ => func.precedence() < ExprPrecedence::Unambiguous,
220 };
221
222 self.print_expr_cond_paren(func, needs_paren, fixup.leftmost_subexpression());
239
240 self.print_call_post(args)
241 }
242
243 fn print_expr_method_call(
244 &mut self,
245 segment: &ast::PathSegment,
246 receiver: &ast::Expr,
247 base_args: &[P<ast::Expr>],
248 fixup: FixupContext,
249 ) {
250 self.print_expr_cond_paren(
262 receiver,
263 receiver.precedence() < ExprPrecedence::Unambiguous,
264 fixup.leftmost_subexpression_with_dot(),
265 );
266
267 self.word(".");
268 self.print_ident(segment.ident);
269 if let Some(args) = &segment.args {
270 self.print_generic_args(args, true);
271 }
272 self.print_call_post(base_args)
273 }
274
275 fn print_expr_binary(
276 &mut self,
277 op: ast::BinOp,
278 lhs: &ast::Expr,
279 rhs: &ast::Expr,
280 fixup: FixupContext,
281 ) {
282 let binop_prec = op.node.precedence();
283 let left_prec = lhs.precedence();
284 let right_prec = rhs.precedence();
285
286 let (mut left_needs_paren, right_needs_paren) = match op.node.fixity() {
287 Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec),
288 Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec),
289 Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec),
290 };
291
292 match (&lhs.kind, op.node) {
293 (&ast::ExprKind::Cast { .. }, ast::BinOpKind::Lt | ast::BinOpKind::Shl) => {
297 left_needs_paren = true;
298 }
299 (&ast::ExprKind::Let { .. }, _) if !parser::needs_par_as_let_scrutinee(binop_prec) => {
308 left_needs_paren = true;
309 }
310 _ => {}
311 }
312
313 self.print_expr_cond_paren(lhs, left_needs_paren, fixup.leftmost_subexpression());
314 self.space();
315 self.word_space(op.node.as_str());
316 self.print_expr_cond_paren(rhs, right_needs_paren, fixup.subsequent_subexpression());
317 }
318
319 fn print_expr_unary(&mut self, op: ast::UnOp, expr: &ast::Expr, fixup: FixupContext) {
320 self.word(op.as_str());
321 self.print_expr_cond_paren(
322 expr,
323 expr.precedence() < ExprPrecedence::Prefix,
324 fixup.subsequent_subexpression(),
325 );
326 }
327
328 fn print_expr_addr_of(
329 &mut self,
330 kind: ast::BorrowKind,
331 mutability: ast::Mutability,
332 expr: &ast::Expr,
333 fixup: FixupContext,
334 ) {
335 self.word("&");
336 match kind {
337 ast::BorrowKind::Ref => self.print_mutability(mutability, false),
338 ast::BorrowKind::Raw => {
339 self.word_nbsp("raw");
340 self.print_mutability(mutability, true);
341 }
342 }
343 self.print_expr_cond_paren(
344 expr,
345 expr.precedence() < ExprPrecedence::Prefix,
346 fixup.subsequent_subexpression(),
347 );
348 }
349
350 pub(super) fn print_expr(&mut self, expr: &ast::Expr, fixup: FixupContext) {
351 self.print_expr_outer_attr_style(expr, true, fixup)
352 }
353
354 pub(super) fn print_expr_outer_attr_style(
355 &mut self,
356 expr: &ast::Expr,
357 is_inline: bool,
358 mut fixup: FixupContext,
359 ) {
360 self.maybe_print_comment(expr.span.lo());
361
362 let attrs = &expr.attrs;
363 if is_inline {
364 self.print_outer_attributes_inline(attrs);
365 } else {
366 self.print_outer_attributes(attrs);
367 }
368
369 self.ibox(INDENT_UNIT);
370
371 let needs_par = fixup.would_cause_statement_boundary(expr);
383 if needs_par {
384 self.popen();
385 fixup = FixupContext::default();
386 }
387
388 self.ann.pre(self, AnnNode::Expr(expr));
389
390 match &expr.kind {
391 ast::ExprKind::Array(exprs) => {
392 self.print_expr_vec(exprs);
393 }
394 ast::ExprKind::ConstBlock(anon_const) => {
395 self.print_expr_anon_const(anon_const, attrs);
396 }
397 ast::ExprKind::Repeat(element, count) => {
398 self.print_expr_repeat(element, count);
399 }
400 ast::ExprKind::Struct(se) => {
401 self.print_expr_struct(&se.qself, &se.path, &se.fields, &se.rest);
402 }
403 ast::ExprKind::Tup(exprs) => {
404 self.print_expr_tup(exprs);
405 }
406 ast::ExprKind::Call(func, args) => {
407 self.print_expr_call(func, args, fixup);
408 }
409 ast::ExprKind::MethodCall(box ast::MethodCall { seg, receiver, args, .. }) => {
410 self.print_expr_method_call(seg, receiver, args, fixup);
411 }
412 ast::ExprKind::Binary(op, lhs, rhs) => {
413 self.print_expr_binary(*op, lhs, rhs, fixup);
414 }
415 ast::ExprKind::Unary(op, expr) => {
416 self.print_expr_unary(*op, expr, fixup);
417 }
418 ast::ExprKind::AddrOf(k, m, expr) => {
419 self.print_expr_addr_of(*k, *m, expr, fixup);
420 }
421 ast::ExprKind::Lit(token_lit) => {
422 self.print_token_literal(*token_lit, expr.span);
423 }
424 ast::ExprKind::IncludedBytes(bytes) => {
425 let lit = token::Lit::new(token::ByteStr, escape_byte_str_symbol(bytes), None);
426 self.print_token_literal(lit, expr.span)
427 }
428 ast::ExprKind::Cast(expr, ty) => {
429 self.print_expr_cond_paren(
430 expr,
431 expr.precedence() < ExprPrecedence::Cast,
432 fixup.leftmost_subexpression(),
433 );
434 self.space();
435 self.word_space("as");
436 self.print_type(ty);
437 }
438 ast::ExprKind::Type(expr, ty) => {
439 self.word("builtin # type_ascribe");
440 self.popen();
441 self.ibox(0);
442 self.print_expr(expr, FixupContext::default());
443
444 self.word(",");
445 self.space_if_not_bol();
446 self.print_type(ty);
447
448 self.end();
449 self.pclose();
450 }
451 ast::ExprKind::Let(pat, scrutinee, _, _) => {
452 self.print_let(pat, scrutinee, fixup);
453 }
454 ast::ExprKind::If(test, blk, elseopt) => self.print_if(test, blk, elseopt.as_deref()),
455 ast::ExprKind::While(test, blk, opt_label) => {
456 if let Some(label) = opt_label {
457 self.print_ident(label.ident);
458 self.word_space(":");
459 }
460 self.cbox(0);
461 self.ibox(0);
462 self.word_nbsp("while");
463 self.print_expr_as_cond(test);
464 self.space();
465 self.print_block_with_attrs(blk, attrs);
466 }
467 ast::ExprKind::ForLoop { pat, iter, body, label, kind } => {
468 if let Some(label) = label {
469 self.print_ident(label.ident);
470 self.word_space(":");
471 }
472 self.cbox(0);
473 self.ibox(0);
474 self.word_nbsp("for");
475 if kind == &ForLoopKind::ForAwait {
476 self.word_nbsp("await");
477 }
478 self.print_pat(pat);
479 self.space();
480 self.word_space("in");
481 self.print_expr_as_cond(iter);
482 self.space();
483 self.print_block_with_attrs(body, attrs);
484 }
485 ast::ExprKind::Loop(blk, opt_label, _) => {
486 if let Some(label) = opt_label {
487 self.print_ident(label.ident);
488 self.word_space(":");
489 }
490 self.cbox(0);
491 self.ibox(0);
492 self.word_nbsp("loop");
493 self.print_block_with_attrs(blk, attrs);
494 }
495 ast::ExprKind::Match(expr, arms, match_kind) => {
496 self.cbox(0);
497 self.ibox(0);
498
499 match match_kind {
500 MatchKind::Prefix => {
501 self.word_nbsp("match");
502 self.print_expr_as_cond(expr);
503 self.space();
504 }
505 MatchKind::Postfix => {
506 self.print_expr_cond_paren(
507 expr,
508 expr.precedence() < ExprPrecedence::Unambiguous,
509 fixup.leftmost_subexpression_with_dot(),
510 );
511 self.word_nbsp(".match");
512 }
513 }
514
515 self.bopen();
516 self.print_inner_attributes_no_trailing_hardbreak(attrs);
517 for arm in arms {
518 self.print_arm(arm);
519 }
520 let empty = attrs.is_empty() && arms.is_empty();
521 self.bclose(expr.span, empty);
522 }
523 ast::ExprKind::Closure(box ast::Closure {
524 binder,
525 capture_clause,
526 constness,
527 coroutine_kind,
528 movability,
529 fn_decl,
530 body,
531 fn_decl_span: _,
532 fn_arg_span: _,
533 }) => {
534 self.print_closure_binder(binder);
535 self.print_constness(*constness);
536 self.print_movability(*movability);
537 coroutine_kind.map(|coroutine_kind| self.print_coroutine_kind(coroutine_kind));
538 self.print_capture_clause(*capture_clause);
539
540 self.print_fn_params_and_ret(fn_decl, true);
541 self.space();
542 self.print_expr(body, FixupContext::default());
543 self.end(); self.ibox(0);
549 }
550 ast::ExprKind::Block(blk, opt_label) => {
551 if let Some(label) = opt_label {
552 self.print_ident(label.ident);
553 self.word_space(":");
554 }
555 self.cbox(0);
557 self.ibox(0);
559 self.print_block_with_attrs(blk, attrs);
560 }
561 ast::ExprKind::Gen(capture_clause, blk, kind, _decl_span) => {
562 self.word_nbsp(kind.modifier());
563 self.print_capture_clause(*capture_clause);
564 self.cbox(0);
566 self.ibox(0);
567 self.print_block_with_attrs(blk, attrs);
568 }
569 ast::ExprKind::Await(expr, _) => {
570 self.print_expr_cond_paren(
571 expr,
572 expr.precedence() < ExprPrecedence::Unambiguous,
573 fixup.leftmost_subexpression_with_dot(),
574 );
575 self.word(".await");
576 }
577 ast::ExprKind::Use(expr, _) => {
578 self.print_expr_cond_paren(
579 expr,
580 expr.precedence() < ExprPrecedence::Unambiguous,
581 fixup,
582 );
583 self.word(".use");
584 }
585 ast::ExprKind::Assign(lhs, rhs, _) => {
586 self.print_expr_cond_paren(
587 lhs,
588 lhs.precedence() <= ExprPrecedence::Range,
591 fixup.leftmost_subexpression(),
592 );
593 self.space();
594 self.word_space("=");
595 self.print_expr_cond_paren(
596 rhs,
597 rhs.precedence() < ExprPrecedence::Assign,
598 fixup.subsequent_subexpression(),
599 );
600 }
601 ast::ExprKind::AssignOp(op, lhs, rhs) => {
602 self.print_expr_cond_paren(
603 lhs,
604 lhs.precedence() <= ExprPrecedence::Range,
605 fixup.leftmost_subexpression(),
606 );
607 self.space();
608 self.word(op.node.as_str());
609 self.word_space("=");
610 self.print_expr_cond_paren(
611 rhs,
612 rhs.precedence() < ExprPrecedence::Assign,
613 fixup.subsequent_subexpression(),
614 );
615 }
616 ast::ExprKind::Field(expr, ident) => {
617 self.print_expr_cond_paren(
618 expr,
619 expr.precedence() < ExprPrecedence::Unambiguous,
620 fixup.leftmost_subexpression_with_dot(),
621 );
622 self.word(".");
623 self.print_ident(*ident);
624 }
625 ast::ExprKind::Index(expr, index, _) => {
626 self.print_expr_cond_paren(
627 expr,
628 expr.precedence() < ExprPrecedence::Unambiguous,
629 fixup.leftmost_subexpression(),
630 );
631 self.word("[");
632 self.print_expr(index, FixupContext::default());
633 self.word("]");
634 }
635 ast::ExprKind::Range(start, end, limits) => {
636 let fake_prec = ExprPrecedence::LOr;
641 if let Some(e) = start {
642 self.print_expr_cond_paren(
643 e,
644 e.precedence() < fake_prec,
645 fixup.leftmost_subexpression(),
646 );
647 }
648 match limits {
649 ast::RangeLimits::HalfOpen => self.word(".."),
650 ast::RangeLimits::Closed => self.word("..="),
651 }
652 if let Some(e) = end {
653 self.print_expr_cond_paren(
654 e,
655 e.precedence() < fake_prec,
656 fixup.subsequent_subexpression(),
657 );
658 }
659 }
660 ast::ExprKind::Underscore => self.word("_"),
661 ast::ExprKind::Path(None, path) => self.print_path(path, true, 0),
662 ast::ExprKind::Path(Some(qself), path) => self.print_qpath(path, qself, true),
663 ast::ExprKind::Break(opt_label, opt_expr) => {
664 self.word("break");
665 if let Some(label) = opt_label {
666 self.space();
667 self.print_ident(label.ident);
668 }
669 if let Some(expr) = opt_expr {
670 self.space();
671 self.print_expr_cond_paren(
672 expr,
673 expr.precedence() < ExprPrecedence::Jump
676 || (opt_label.is_none() && classify::leading_labeled_expr(expr)),
677 fixup.subsequent_subexpression(),
678 );
679 }
680 }
681 ast::ExprKind::Continue(opt_label) => {
682 self.word("continue");
683 if let Some(label) = opt_label {
684 self.space();
685 self.print_ident(label.ident);
686 }
687 }
688 ast::ExprKind::Ret(result) => {
689 self.word("return");
690 if let Some(expr) = result {
691 self.word(" ");
692 self.print_expr_cond_paren(
693 expr,
694 expr.precedence() < ExprPrecedence::Jump,
695 fixup.subsequent_subexpression(),
696 );
697 }
698 }
699 ast::ExprKind::Yeet(result) => {
700 self.word("do");
701 self.word(" ");
702 self.word("yeet");
703 if let Some(expr) = result {
704 self.word(" ");
705 self.print_expr_cond_paren(
706 expr,
707 expr.precedence() < ExprPrecedence::Jump,
708 fixup.subsequent_subexpression(),
709 );
710 }
711 }
712 ast::ExprKind::Become(result) => {
713 self.word("become");
714 self.word(" ");
715 self.print_expr_cond_paren(
716 result,
717 result.precedence() < ExprPrecedence::Jump,
718 fixup.subsequent_subexpression(),
719 );
720 }
721 ast::ExprKind::InlineAsm(a) => {
722 self.word("asm!");
724 self.print_inline_asm(a);
725 }
726 ast::ExprKind::FormatArgs(fmt) => {
727 self.word("format_args!");
729 self.popen();
730 self.ibox(0);
731 self.word(reconstruct_format_args_template_string(&fmt.template));
732 for arg in fmt.arguments.all_args() {
733 self.word_space(",");
734 self.print_expr(&arg.expr, FixupContext::default());
735 }
736 self.end();
737 self.pclose();
738 }
739 ast::ExprKind::OffsetOf(container, fields) => {
740 self.word("builtin # offset_of");
741 self.popen();
742 self.ibox(0);
743 self.print_type(container);
744 self.word(",");
745 self.space();
746
747 if let Some((&first, rest)) = fields.split_first() {
748 self.print_ident(first);
749
750 for &field in rest {
751 self.word(".");
752 self.print_ident(field);
753 }
754 }
755 self.end();
756 self.pclose();
757 }
758 ast::ExprKind::MacCall(m) => self.print_mac(m),
759 ast::ExprKind::Paren(e) => {
760 self.popen();
761 self.print_expr(e, FixupContext::default());
762 self.pclose();
763 }
764 ast::ExprKind::Yield(YieldKind::Prefix(e)) => {
765 self.word("yield");
766
767 if let Some(expr) = e {
768 self.space();
769 self.print_expr_cond_paren(
770 expr,
771 expr.precedence() < ExprPrecedence::Jump,
772 fixup.subsequent_subexpression(),
773 );
774 }
775 }
776 ast::ExprKind::Yield(YieldKind::Postfix(e)) => {
777 self.print_expr_cond_paren(
778 e,
779 e.precedence() < ExprPrecedence::Unambiguous,
780 fixup.leftmost_subexpression_with_dot(),
781 );
782 self.word(".yield");
783 }
784 ast::ExprKind::Try(e) => {
785 self.print_expr_cond_paren(
786 e,
787 e.precedence() < ExprPrecedence::Unambiguous,
788 fixup.leftmost_subexpression_with_dot(),
789 );
790 self.word("?")
791 }
792 ast::ExprKind::TryBlock(blk) => {
793 self.cbox(0);
794 self.ibox(0);
795 self.word_nbsp("try");
796 self.print_block_with_attrs(blk, attrs)
797 }
798 ast::ExprKind::UnsafeBinderCast(kind, expr, ty) => {
799 self.word("builtin # ");
800 match kind {
801 ast::UnsafeBinderCastKind::Wrap => self.word("wrap_binder"),
802 ast::UnsafeBinderCastKind::Unwrap => self.word("unwrap_binder"),
803 }
804 self.popen();
805 self.ibox(0);
806 self.print_expr(expr, FixupContext::default());
807
808 if let Some(ty) = ty {
809 self.word(",");
810 self.space();
811 self.print_type(ty);
812 }
813
814 self.end();
815 self.pclose();
816 }
817 ast::ExprKind::Err(_) => {
818 self.popen();
819 self.word("/*ERROR*/");
820 self.pclose()
821 }
822 ast::ExprKind::Dummy => {
823 self.popen();
824 self.word("/*DUMMY*/");
825 self.pclose();
826 }
827 }
828
829 self.ann.post(self, AnnNode::Expr(expr));
830
831 if needs_par {
832 self.pclose();
833 }
834
835 self.end();
836 }
837
838 fn print_arm(&mut self, arm: &ast::Arm) {
839 if arm.attrs.is_empty() {
841 self.space();
842 }
843 self.cbox(INDENT_UNIT);
844 self.ibox(0);
845 self.maybe_print_comment(arm.pat.span.lo());
846 self.print_outer_attributes(&arm.attrs);
847 self.print_pat(&arm.pat);
848 self.space();
849 if let Some(e) = &arm.guard {
850 self.word_space("if");
851 self.print_expr(e, FixupContext::default());
852 self.space();
853 }
854
855 if let Some(body) = &arm.body {
856 self.word_space("=>");
857
858 match &body.kind {
859 ast::ExprKind::Block(blk, opt_label) => {
860 if let Some(label) = opt_label {
861 self.print_ident(label.ident);
862 self.word_space(":");
863 }
864
865 self.print_block_unclosed_indent(blk);
867
868 if let BlockCheckMode::Unsafe(ast::UserProvided) = blk.rules {
870 self.word(",");
871 }
872 }
873 _ => {
874 self.end(); self.print_expr(body, FixupContext::new_match_arm());
876 self.word(",");
877 }
878 }
879 } else {
880 self.word(",");
881 }
882 self.end(); }
884
885 fn print_closure_binder(&mut self, binder: &ast::ClosureBinder) {
886 match binder {
887 ast::ClosureBinder::NotPresent => {}
888 ast::ClosureBinder::For { generic_params, .. } => {
889 self.print_formal_generic_params(generic_params)
890 }
891 }
892 }
893
894 fn print_movability(&mut self, movability: ast::Movability) {
895 match movability {
896 ast::Movability::Static => self.word_space("static"),
897 ast::Movability::Movable => {}
898 }
899 }
900
901 fn print_capture_clause(&mut self, capture_clause: ast::CaptureBy) {
902 match capture_clause {
903 ast::CaptureBy::Value { .. } => self.word_space("move"),
904 ast::CaptureBy::Use { .. } => self.word_space("use"),
905 ast::CaptureBy::Ref => {}
906 }
907 }
908}
909
910fn reconstruct_format_args_template_string(pieces: &[FormatArgsPiece]) -> String {
911 let mut template = "\"".to_string();
912 for piece in pieces {
913 match piece {
914 FormatArgsPiece::Literal(s) => {
915 for c in s.as_str().chars() {
916 template.extend(c.escape_debug());
917 if let '{' | '}' = c {
918 template.push(c);
919 }
920 }
921 }
922 FormatArgsPiece::Placeholder(p) => {
923 template.push('{');
924 let (Ok(n) | Err(n)) = p.argument.index;
925 write!(template, "{n}").unwrap();
926 if p.format_options != Default::default() || p.format_trait != FormatTrait::Display
927 {
928 template.push(':');
929 }
930 if let Some(fill) = p.format_options.fill {
931 template.push(fill);
932 }
933 match p.format_options.alignment {
934 Some(FormatAlignment::Left) => template.push('<'),
935 Some(FormatAlignment::Right) => template.push('>'),
936 Some(FormatAlignment::Center) => template.push('^'),
937 None => {}
938 }
939 match p.format_options.sign {
940 Some(FormatSign::Plus) => template.push('+'),
941 Some(FormatSign::Minus) => template.push('-'),
942 None => {}
943 }
944 if p.format_options.alternate {
945 template.push('#');
946 }
947 if p.format_options.zero_pad {
948 template.push('0');
949 }
950 if let Some(width) = &p.format_options.width {
951 match width {
952 FormatCount::Literal(n) => write!(template, "{n}").unwrap(),
953 FormatCount::Argument(FormatArgPosition {
954 index: Ok(n) | Err(n), ..
955 }) => {
956 write!(template, "{n}$").unwrap();
957 }
958 }
959 }
960 if let Some(precision) = &p.format_options.precision {
961 template.push('.');
962 match precision {
963 FormatCount::Literal(n) => write!(template, "{n}").unwrap(),
964 FormatCount::Argument(FormatArgPosition {
965 index: Ok(n) | Err(n), ..
966 }) => {
967 write!(template, "{n}$").unwrap();
968 }
969 }
970 }
971 match p.format_options.debug_hex {
972 Some(FormatDebugHex::Lower) => template.push('x'),
973 Some(FormatDebugHex::Upper) => template.push('X'),
974 None => {}
975 }
976 template.push_str(match p.format_trait {
977 FormatTrait::Display => "",
978 FormatTrait::Debug => "?",
979 FormatTrait::LowerExp => "e",
980 FormatTrait::UpperExp => "E",
981 FormatTrait::Octal => "o",
982 FormatTrait::Pointer => "p",
983 FormatTrait::Binary => "b",
984 FormatTrait::LowerHex => "x",
985 FormatTrait::UpperHex => "X",
986 });
987 template.push('}');
988 }
989 }
990 }
991 template.push('"');
992 template
993}