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, AssocOp, ExprPrecedence, Fixity};
9use rustc_ast::{
10 self as ast, BlockCheckMode, FormatAlignment, FormatArgPosition, FormatArgsPiece, FormatCount,
11 FormatDebugHex, FormatSign, FormatTrait, 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 assoc_op = AssocOp::from_ast_binop(op.node);
283 let binop_prec = assoc_op.precedence();
284 let left_prec = lhs.precedence();
285 let right_prec = rhs.precedence();
286
287 let (mut left_needs_paren, right_needs_paren) = match assoc_op.fixity() {
288 Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec),
289 Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec),
290 Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec),
291 };
292
293 match (&lhs.kind, op.node) {
294 (&ast::ExprKind::Cast { .. }, ast::BinOpKind::Lt | ast::BinOpKind::Shl) => {
298 left_needs_paren = true;
299 }
300 (&ast::ExprKind::Let { .. }, _) if !parser::needs_par_as_let_scrutinee(binop_prec) => {
309 left_needs_paren = true;
310 }
311 _ => {}
312 }
313
314 self.print_expr_cond_paren(lhs, left_needs_paren, fixup.leftmost_subexpression());
315 self.space();
316 self.word_space(op.node.as_str());
317 self.print_expr_cond_paren(rhs, right_needs_paren, fixup.subsequent_subexpression());
318 }
319
320 fn print_expr_unary(&mut self, op: ast::UnOp, expr: &ast::Expr, fixup: FixupContext) {
321 self.word(op.as_str());
322 self.print_expr_cond_paren(
323 expr,
324 expr.precedence() < ExprPrecedence::Prefix,
325 fixup.subsequent_subexpression(),
326 );
327 }
328
329 fn print_expr_addr_of(
330 &mut self,
331 kind: ast::BorrowKind,
332 mutability: ast::Mutability,
333 expr: &ast::Expr,
334 fixup: FixupContext,
335 ) {
336 self.word("&");
337 match kind {
338 ast::BorrowKind::Ref => self.print_mutability(mutability, false),
339 ast::BorrowKind::Raw => {
340 self.word_nbsp("raw");
341 self.print_mutability(mutability, true);
342 }
343 }
344 self.print_expr_cond_paren(
345 expr,
346 expr.precedence() < ExprPrecedence::Prefix,
347 fixup.subsequent_subexpression(),
348 );
349 }
350
351 pub(super) fn print_expr(&mut self, expr: &ast::Expr, fixup: FixupContext) {
352 self.print_expr_outer_attr_style(expr, true, fixup)
353 }
354
355 pub(super) fn print_expr_outer_attr_style(
356 &mut self,
357 expr: &ast::Expr,
358 is_inline: bool,
359 mut fixup: FixupContext,
360 ) {
361 self.maybe_print_comment(expr.span.lo());
362
363 let attrs = &expr.attrs;
364 if is_inline {
365 self.print_outer_attributes_inline(attrs);
366 } else {
367 self.print_outer_attributes(attrs);
368 }
369
370 self.ibox(INDENT_UNIT);
371
372 let needs_par = fixup.would_cause_statement_boundary(expr);
384 if needs_par {
385 self.popen();
386 fixup = FixupContext::default();
387 }
388
389 self.ann.pre(self, AnnNode::Expr(expr));
390
391 match &expr.kind {
392 ast::ExprKind::Array(exprs) => {
393 self.print_expr_vec(exprs);
394 }
395 ast::ExprKind::ConstBlock(anon_const) => {
396 self.print_expr_anon_const(anon_const, attrs);
397 }
398 ast::ExprKind::Repeat(element, count) => {
399 self.print_expr_repeat(element, count);
400 }
401 ast::ExprKind::Struct(se) => {
402 self.print_expr_struct(&se.qself, &se.path, &se.fields, &se.rest);
403 }
404 ast::ExprKind::Tup(exprs) => {
405 self.print_expr_tup(exprs);
406 }
407 ast::ExprKind::Call(func, args) => {
408 self.print_expr_call(func, args, fixup);
409 }
410 ast::ExprKind::MethodCall(box ast::MethodCall { seg, receiver, args, .. }) => {
411 self.print_expr_method_call(seg, receiver, args, fixup);
412 }
413 ast::ExprKind::Binary(op, lhs, rhs) => {
414 self.print_expr_binary(*op, lhs, rhs, fixup);
415 }
416 ast::ExprKind::Unary(op, expr) => {
417 self.print_expr_unary(*op, expr, fixup);
418 }
419 ast::ExprKind::AddrOf(k, m, expr) => {
420 self.print_expr_addr_of(*k, *m, expr, fixup);
421 }
422 ast::ExprKind::Lit(token_lit) => {
423 self.print_token_literal(*token_lit, expr.span);
424 }
425 ast::ExprKind::IncludedBytes(bytes) => {
426 let lit = token::Lit::new(token::ByteStr, escape_byte_str_symbol(bytes), None);
427 self.print_token_literal(lit, expr.span)
428 }
429 ast::ExprKind::Cast(expr, ty) => {
430 self.print_expr_cond_paren(
431 expr,
432 expr.precedence() < ExprPrecedence::Cast,
433 fixup.leftmost_subexpression(),
434 );
435 self.space();
436 self.word_space("as");
437 self.print_type(ty);
438 }
439 ast::ExprKind::Type(expr, ty) => {
440 self.word("builtin # type_ascribe");
441 self.popen();
442 self.ibox(0);
443 self.print_expr(expr, FixupContext::default());
444
445 self.word(",");
446 self.space_if_not_bol();
447 self.print_type(ty);
448
449 self.end();
450 self.pclose();
451 }
452 ast::ExprKind::Let(pat, scrutinee, _, _) => {
453 self.print_let(pat, scrutinee, fixup);
454 }
455 ast::ExprKind::If(test, blk, elseopt) => self.print_if(test, blk, elseopt.as_deref()),
456 ast::ExprKind::While(test, blk, opt_label) => {
457 if let Some(label) = opt_label {
458 self.print_ident(label.ident);
459 self.word_space(":");
460 }
461 self.cbox(0);
462 self.ibox(0);
463 self.word_nbsp("while");
464 self.print_expr_as_cond(test);
465 self.space();
466 self.print_block_with_attrs(blk, attrs);
467 }
468 ast::ExprKind::ForLoop { pat, iter, body, label, kind } => {
469 if let Some(label) = label {
470 self.print_ident(label.ident);
471 self.word_space(":");
472 }
473 self.cbox(0);
474 self.ibox(0);
475 self.word_nbsp("for");
476 if kind == &ForLoopKind::ForAwait {
477 self.word_nbsp("await");
478 }
479 self.print_pat(pat);
480 self.space();
481 self.word_space("in");
482 self.print_expr_as_cond(iter);
483 self.space();
484 self.print_block_with_attrs(body, attrs);
485 }
486 ast::ExprKind::Loop(blk, opt_label, _) => {
487 if let Some(label) = opt_label {
488 self.print_ident(label.ident);
489 self.word_space(":");
490 }
491 self.cbox(0);
492 self.ibox(0);
493 self.word_nbsp("loop");
494 self.print_block_with_attrs(blk, attrs);
495 }
496 ast::ExprKind::Match(expr, arms, match_kind) => {
497 self.cbox(0);
498 self.ibox(0);
499
500 match match_kind {
501 MatchKind::Prefix => {
502 self.word_nbsp("match");
503 self.print_expr_as_cond(expr);
504 self.space();
505 }
506 MatchKind::Postfix => {
507 self.print_expr_cond_paren(
508 expr,
509 expr.precedence() < ExprPrecedence::Unambiguous,
510 fixup.leftmost_subexpression_with_dot(),
511 );
512 self.word_nbsp(".match");
513 }
514 }
515
516 self.bopen();
517 self.print_inner_attributes_no_trailing_hardbreak(attrs);
518 for arm in arms {
519 self.print_arm(arm);
520 }
521 let empty = attrs.is_empty() && arms.is_empty();
522 self.bclose(expr.span, empty);
523 }
524 ast::ExprKind::Closure(box ast::Closure {
525 binder,
526 capture_clause,
527 constness,
528 coroutine_kind,
529 movability,
530 fn_decl,
531 body,
532 fn_decl_span: _,
533 fn_arg_span: _,
534 }) => {
535 self.print_closure_binder(binder);
536 self.print_constness(*constness);
537 self.print_movability(*movability);
538 coroutine_kind.map(|coroutine_kind| self.print_coroutine_kind(coroutine_kind));
539 self.print_capture_clause(*capture_clause);
540
541 self.print_fn_params_and_ret(fn_decl, true);
542 self.space();
543 self.print_expr(body, FixupContext::default());
544 self.end(); self.ibox(0);
550 }
551 ast::ExprKind::Block(blk, opt_label) => {
552 if let Some(label) = opt_label {
553 self.print_ident(label.ident);
554 self.word_space(":");
555 }
556 self.cbox(0);
558 self.ibox(0);
560 self.print_block_with_attrs(blk, attrs);
561 }
562 ast::ExprKind::Gen(capture_clause, blk, kind, _decl_span) => {
563 self.word_nbsp(kind.modifier());
564 self.print_capture_clause(*capture_clause);
565 self.cbox(0);
567 self.ibox(0);
568 self.print_block_with_attrs(blk, attrs);
569 }
570 ast::ExprKind::Await(expr, _) => {
571 self.print_expr_cond_paren(
572 expr,
573 expr.precedence() < ExprPrecedence::Unambiguous,
574 fixup.leftmost_subexpression_with_dot(),
575 );
576 self.word(".await");
577 }
578 ast::ExprKind::Assign(lhs, rhs, _) => {
579 self.print_expr_cond_paren(
580 lhs,
581 lhs.precedence() <= ExprPrecedence::Range,
584 fixup.leftmost_subexpression(),
585 );
586 self.space();
587 self.word_space("=");
588 self.print_expr_cond_paren(
589 rhs,
590 rhs.precedence() < ExprPrecedence::Assign,
591 fixup.subsequent_subexpression(),
592 );
593 }
594 ast::ExprKind::AssignOp(op, lhs, rhs) => {
595 self.print_expr_cond_paren(
596 lhs,
597 lhs.precedence() <= ExprPrecedence::Range,
598 fixup.leftmost_subexpression(),
599 );
600 self.space();
601 self.word(op.node.as_str());
602 self.word_space("=");
603 self.print_expr_cond_paren(
604 rhs,
605 rhs.precedence() < ExprPrecedence::Assign,
606 fixup.subsequent_subexpression(),
607 );
608 }
609 ast::ExprKind::Field(expr, ident) => {
610 self.print_expr_cond_paren(
611 expr,
612 expr.precedence() < ExprPrecedence::Unambiguous,
613 fixup.leftmost_subexpression_with_dot(),
614 );
615 self.word(".");
616 self.print_ident(*ident);
617 }
618 ast::ExprKind::Index(expr, index, _) => {
619 self.print_expr_cond_paren(
620 expr,
621 expr.precedence() < ExprPrecedence::Unambiguous,
622 fixup.leftmost_subexpression(),
623 );
624 self.word("[");
625 self.print_expr(index, FixupContext::default());
626 self.word("]");
627 }
628 ast::ExprKind::Range(start, end, limits) => {
629 let fake_prec = ExprPrecedence::LOr;
634 if let Some(e) = start {
635 self.print_expr_cond_paren(
636 e,
637 e.precedence() < fake_prec,
638 fixup.leftmost_subexpression(),
639 );
640 }
641 match limits {
642 ast::RangeLimits::HalfOpen => self.word(".."),
643 ast::RangeLimits::Closed => self.word("..="),
644 }
645 if let Some(e) = end {
646 self.print_expr_cond_paren(
647 e,
648 e.precedence() < fake_prec,
649 fixup.subsequent_subexpression(),
650 );
651 }
652 }
653 ast::ExprKind::Underscore => self.word("_"),
654 ast::ExprKind::Path(None, path) => self.print_path(path, true, 0),
655 ast::ExprKind::Path(Some(qself), path) => self.print_qpath(path, qself, true),
656 ast::ExprKind::Break(opt_label, opt_expr) => {
657 self.word("break");
658 if let Some(label) = opt_label {
659 self.space();
660 self.print_ident(label.ident);
661 }
662 if let Some(expr) = opt_expr {
663 self.space();
664 self.print_expr_cond_paren(
665 expr,
666 expr.precedence() < ExprPrecedence::Jump
669 || (opt_label.is_none() && classify::leading_labeled_expr(expr)),
670 fixup.subsequent_subexpression(),
671 );
672 }
673 }
674 ast::ExprKind::Continue(opt_label) => {
675 self.word("continue");
676 if let Some(label) = opt_label {
677 self.space();
678 self.print_ident(label.ident);
679 }
680 }
681 ast::ExprKind::Ret(result) => {
682 self.word("return");
683 if let Some(expr) = result {
684 self.word(" ");
685 self.print_expr_cond_paren(
686 expr,
687 expr.precedence() < ExprPrecedence::Jump,
688 fixup.subsequent_subexpression(),
689 );
690 }
691 }
692 ast::ExprKind::Yeet(result) => {
693 self.word("do");
694 self.word(" ");
695 self.word("yeet");
696 if let Some(expr) = result {
697 self.word(" ");
698 self.print_expr_cond_paren(
699 expr,
700 expr.precedence() < ExprPrecedence::Jump,
701 fixup.subsequent_subexpression(),
702 );
703 }
704 }
705 ast::ExprKind::Become(result) => {
706 self.word("become");
707 self.word(" ");
708 self.print_expr_cond_paren(
709 result,
710 result.precedence() < ExprPrecedence::Jump,
711 fixup.subsequent_subexpression(),
712 );
713 }
714 ast::ExprKind::InlineAsm(a) => {
715 self.word("asm!");
717 self.print_inline_asm(a);
718 }
719 ast::ExprKind::FormatArgs(fmt) => {
720 self.word("format_args!");
722 self.popen();
723 self.ibox(0);
724 self.word(reconstruct_format_args_template_string(&fmt.template));
725 for arg in fmt.arguments.all_args() {
726 self.word_space(",");
727 self.print_expr(&arg.expr, FixupContext::default());
728 }
729 self.end();
730 self.pclose();
731 }
732 ast::ExprKind::OffsetOf(container, fields) => {
733 self.word("builtin # offset_of");
734 self.popen();
735 self.ibox(0);
736 self.print_type(container);
737 self.word(",");
738 self.space();
739
740 if let Some((&first, rest)) = fields.split_first() {
741 self.print_ident(first);
742
743 for &field in rest {
744 self.word(".");
745 self.print_ident(field);
746 }
747 }
748 self.end();
749 self.pclose();
750 }
751 ast::ExprKind::MacCall(m) => self.print_mac(m),
752 ast::ExprKind::Paren(e) => {
753 self.popen();
754 self.print_expr(e, FixupContext::default());
755 self.pclose();
756 }
757 ast::ExprKind::Yield(e) => {
758 self.word("yield");
759
760 if let Some(expr) = e {
761 self.space();
762 self.print_expr_cond_paren(
763 expr,
764 expr.precedence() < ExprPrecedence::Jump,
765 fixup.subsequent_subexpression(),
766 );
767 }
768 }
769 ast::ExprKind::Try(e) => {
770 self.print_expr_cond_paren(
771 e,
772 e.precedence() < ExprPrecedence::Unambiguous,
773 fixup.leftmost_subexpression_with_dot(),
774 );
775 self.word("?")
776 }
777 ast::ExprKind::TryBlock(blk) => {
778 self.cbox(0);
779 self.ibox(0);
780 self.word_nbsp("try");
781 self.print_block_with_attrs(blk, attrs)
782 }
783 ast::ExprKind::UnsafeBinderCast(kind, expr, ty) => {
784 self.word("builtin # ");
785 match kind {
786 ast::UnsafeBinderCastKind::Wrap => self.word("wrap_binder"),
787 ast::UnsafeBinderCastKind::Unwrap => self.word("unwrap_binder"),
788 }
789 self.popen();
790 self.ibox(0);
791 self.print_expr(expr, FixupContext::default());
792
793 if let Some(ty) = ty {
794 self.word(",");
795 self.space();
796 self.print_type(ty);
797 }
798
799 self.end();
800 self.pclose();
801 }
802 ast::ExprKind::Err(_) => {
803 self.popen();
804 self.word("/*ERROR*/");
805 self.pclose()
806 }
807 ast::ExprKind::Dummy => {
808 self.popen();
809 self.word("/*DUMMY*/");
810 self.pclose();
811 }
812 }
813
814 self.ann.post(self, AnnNode::Expr(expr));
815
816 if needs_par {
817 self.pclose();
818 }
819
820 self.end();
821 }
822
823 fn print_arm(&mut self, arm: &ast::Arm) {
824 if arm.attrs.is_empty() {
826 self.space();
827 }
828 self.cbox(INDENT_UNIT);
829 self.ibox(0);
830 self.maybe_print_comment(arm.pat.span.lo());
831 self.print_outer_attributes(&arm.attrs);
832 self.print_pat(&arm.pat);
833 self.space();
834 if let Some(e) = &arm.guard {
835 self.word_space("if");
836 self.print_expr(e, FixupContext::default());
837 self.space();
838 }
839
840 if let Some(body) = &arm.body {
841 self.word_space("=>");
842
843 match &body.kind {
844 ast::ExprKind::Block(blk, opt_label) => {
845 if let Some(label) = opt_label {
846 self.print_ident(label.ident);
847 self.word_space(":");
848 }
849
850 self.print_block_unclosed_indent(blk);
852
853 if let BlockCheckMode::Unsafe(ast::UserProvided) = blk.rules {
855 self.word(",");
856 }
857 }
858 _ => {
859 self.end(); self.print_expr(body, FixupContext::new_match_arm());
861 self.word(",");
862 }
863 }
864 } else {
865 self.word(",");
866 }
867 self.end(); }
869
870 fn print_closure_binder(&mut self, binder: &ast::ClosureBinder) {
871 match binder {
872 ast::ClosureBinder::NotPresent => {}
873 ast::ClosureBinder::For { generic_params, .. } => {
874 self.print_formal_generic_params(generic_params)
875 }
876 }
877 }
878
879 fn print_movability(&mut self, movability: ast::Movability) {
880 match movability {
881 ast::Movability::Static => self.word_space("static"),
882 ast::Movability::Movable => {}
883 }
884 }
885
886 fn print_capture_clause(&mut self, capture_clause: ast::CaptureBy) {
887 match capture_clause {
888 ast::CaptureBy::Value { .. } => self.word_space("move"),
889 ast::CaptureBy::Ref => {}
890 }
891 }
892}
893
894fn reconstruct_format_args_template_string(pieces: &[FormatArgsPiece]) -> String {
895 let mut template = "\"".to_string();
896 for piece in pieces {
897 match piece {
898 FormatArgsPiece::Literal(s) => {
899 for c in s.as_str().chars() {
900 template.extend(c.escape_debug());
901 if let '{' | '}' = c {
902 template.push(c);
903 }
904 }
905 }
906 FormatArgsPiece::Placeholder(p) => {
907 template.push('{');
908 let (Ok(n) | Err(n)) = p.argument.index;
909 write!(template, "{n}").unwrap();
910 if p.format_options != Default::default() || p.format_trait != FormatTrait::Display
911 {
912 template.push(':');
913 }
914 if let Some(fill) = p.format_options.fill {
915 template.push(fill);
916 }
917 match p.format_options.alignment {
918 Some(FormatAlignment::Left) => template.push('<'),
919 Some(FormatAlignment::Right) => template.push('>'),
920 Some(FormatAlignment::Center) => template.push('^'),
921 None => {}
922 }
923 match p.format_options.sign {
924 Some(FormatSign::Plus) => template.push('+'),
925 Some(FormatSign::Minus) => template.push('-'),
926 None => {}
927 }
928 if p.format_options.alternate {
929 template.push('#');
930 }
931 if p.format_options.zero_pad {
932 template.push('0');
933 }
934 if let Some(width) = &p.format_options.width {
935 match width {
936 FormatCount::Literal(n) => write!(template, "{n}").unwrap(),
937 FormatCount::Argument(FormatArgPosition {
938 index: Ok(n) | Err(n), ..
939 }) => {
940 write!(template, "{n}$").unwrap();
941 }
942 }
943 }
944 if let Some(precision) = &p.format_options.precision {
945 template.push('.');
946 match precision {
947 FormatCount::Literal(n) => write!(template, "{n}").unwrap(),
948 FormatCount::Argument(FormatArgPosition {
949 index: Ok(n) | Err(n), ..
950 }) => {
951 write!(template, "{n}$").unwrap();
952 }
953 }
954 }
955 match p.format_options.debug_hex {
956 Some(FormatDebugHex::Lower) => template.push('x'),
957 Some(FormatDebugHex::Upper) => template.push('X'),
958 None => {}
959 }
960 template.push_str(match p.format_trait {
961 FormatTrait::Display => "",
962 FormatTrait::Debug => "?",
963 FormatTrait::LowerExp => "e",
964 FormatTrait::UpperExp => "E",
965 FormatTrait::Octal => "o",
966 FormatTrait::Pointer => "p",
967 FormatTrait::Binary => "b",
968 FormatTrait::LowerHex => "x",
969 FormatTrait::UpperHex => "X",
970 });
971 template.push('}');
972 }
973 }
974 }
975 template.push('"');
976 template
977}