]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_ast_pretty/src/pprust/state/expr.rs
New upstream version 1.69.0+dfsg1
[rustc.git] / compiler / rustc_ast_pretty / src / pprust / state / expr.rs
CommitLineData
5099ac24
FG
1use crate::pp::Breaks::Inconsistent;
2use crate::pprust::state::{AnnNode, IterDelimited, PrintState, State, INDENT_UNIT};
3
4use rustc_ast::ptr::P;
9c376795
FG
5use rustc_ast::token;
6use rustc_ast::util::literal::escape_byte_str_symbol;
5099ac24
FG
7use rustc_ast::util::parser::{self, AssocOp, Fixity};
8use rustc_ast::{self as ast, BlockCheckMode};
9ffffee4
FG
9use rustc_ast::{
10 FormatAlignment, FormatArgPosition, FormatArgsPiece, FormatCount, FormatDebugHex, FormatSign,
11 FormatTrait,
12};
13use std::fmt::Write;
5099ac24
FG
14
15impl<'a> State<'a> {
16 fn print_else(&mut self, els: Option<&ast::Expr>) {
17 if let Some(_else) = els {
487cf647 18 match &_else.kind {
5099ac24 19 // Another `else if` block.
487cf647 20 ast::ExprKind::If(i, then, e) => {
5099ac24
FG
21 self.cbox(INDENT_UNIT - 1);
22 self.ibox(0);
23 self.word(" else if ");
24 self.print_expr_as_cond(i);
25 self.space();
26 self.print_block(then);
27 self.print_else(e.as_deref())
28 }
29 // Final `else` block.
487cf647 30 ast::ExprKind::Block(b, _) => {
5099ac24
FG
31 self.cbox(INDENT_UNIT - 1);
32 self.ibox(0);
33 self.word(" else ");
34 self.print_block(b)
35 }
36 // Constraints would be great here!
37 _ => {
38 panic!("print_if saw if with weird alternative");
39 }
40 }
41 }
42 }
43
44 fn print_if(&mut self, test: &ast::Expr, blk: &ast::Block, elseopt: Option<&ast::Expr>) {
45 self.head("if");
46 self.print_expr_as_cond(test);
47 self.space();
48 self.print_block(blk);
49 self.print_else(elseopt)
50 }
51
52 fn print_call_post(&mut self, args: &[P<ast::Expr>]) {
53 self.popen();
54 self.commasep_exprs(Inconsistent, args);
55 self.pclose()
56 }
57
58 fn print_expr_maybe_paren(&mut self, expr: &ast::Expr, prec: i8) {
59 self.print_expr_cond_paren(expr, expr.precedence().order() < prec)
60 }
61
62 /// Prints an expr using syntax that's acceptable in a condition position, such as the `cond` in
63 /// `if cond { ... }`.
64 fn print_expr_as_cond(&mut self, expr: &ast::Expr) {
65 self.print_expr_cond_paren(expr, Self::cond_needs_par(expr))
66 }
67
487cf647
FG
68 /// Does `expr` need parentheses when printed in a condition position?
69 ///
70 /// These cases need parens due to the parse error observed in #26461: `if return {}`
71 /// parses as the erroneous construct `if (return {})`, not `if (return) {}`.
5099ac24
FG
72 pub(super) fn cond_needs_par(expr: &ast::Expr) -> bool {
73 match expr.kind {
04454e1e
FG
74 ast::ExprKind::Break(..)
75 | ast::ExprKind::Closure(..)
76 | ast::ExprKind::Ret(..)
77 | ast::ExprKind::Yeet(..) => true,
5099ac24
FG
78 _ => parser::contains_exterior_struct_lit(expr),
79 }
80 }
81
82 /// Prints `expr` or `(expr)` when `needs_par` holds.
83 pub(super) fn print_expr_cond_paren(&mut self, expr: &ast::Expr, needs_par: bool) {
84 if needs_par {
85 self.popen();
86 }
87 self.print_expr(expr);
88 if needs_par {
89 self.pclose();
90 }
91 }
92
93 fn print_expr_vec(&mut self, exprs: &[P<ast::Expr>]) {
94 self.ibox(INDENT_UNIT);
95 self.word("[");
96 self.commasep_exprs(Inconsistent, exprs);
97 self.word("]");
98 self.end();
99 }
100
04454e1e
FG
101 pub(super) fn print_expr_anon_const(
102 &mut self,
103 expr: &ast::AnonConst,
104 attrs: &[ast::Attribute],
105 ) {
5099ac24
FG
106 self.ibox(INDENT_UNIT);
107 self.word("const");
04454e1e
FG
108 self.nbsp();
109 if let ast::ExprKind::Block(block, None) = &expr.value.kind {
110 self.cbox(0);
111 self.ibox(0);
112 self.print_block_with_attrs(block, attrs);
113 } else {
114 self.print_expr(&expr.value);
115 }
5099ac24
FG
116 self.end();
117 }
118
119 fn print_expr_repeat(&mut self, element: &ast::Expr, count: &ast::AnonConst) {
120 self.ibox(INDENT_UNIT);
121 self.word("[");
122 self.print_expr(element);
123 self.word_space(";");
124 self.print_expr(&count.value);
125 self.word("]");
126 self.end();
127 }
128
129 fn print_expr_struct(
130 &mut self,
487cf647 131 qself: &Option<P<ast::QSelf>>,
5099ac24
FG
132 path: &ast::Path,
133 fields: &[ast::ExprField],
134 rest: &ast::StructRest,
135 ) {
136 if let Some(qself) = qself {
137 self.print_qpath(path, qself, true);
138 } else {
139 self.print_path(path, true, 0);
140 }
141 self.nbsp();
142 self.word("{");
143 let has_rest = match rest {
144 ast::StructRest::Base(_) | ast::StructRest::Rest(_) => true,
145 ast::StructRest::None => false,
146 };
147 if fields.is_empty() && !has_rest {
148 self.word("}");
149 return;
150 }
151 self.cbox(0);
152 for field in fields.iter().delimited() {
153 self.maybe_print_comment(field.span.hi());
154 self.print_outer_attributes(&field.attrs);
155 if field.is_first {
156 self.space_if_not_bol();
157 }
158 if !field.is_shorthand {
159 self.print_ident(field.ident);
160 self.word_nbsp(":");
161 }
162 self.print_expr(&field.expr);
163 if !field.is_last || has_rest {
164 self.word_space(",");
165 } else {
166 self.trailing_comma_or_space();
167 }
168 }
169 if has_rest {
170 if fields.is_empty() {
171 self.space();
172 }
173 self.word("..");
174 if let ast::StructRest::Base(expr) = rest {
175 self.print_expr(expr);
176 }
177 self.space();
178 }
179 self.offset(-INDENT_UNIT);
180 self.end();
181 self.word("}");
182 }
183
184 fn print_expr_tup(&mut self, exprs: &[P<ast::Expr>]) {
185 self.popen();
186 self.commasep_exprs(Inconsistent, exprs);
187 if exprs.len() == 1 {
188 self.word(",");
189 }
190 self.pclose()
191 }
192
193 fn print_expr_call(&mut self, func: &ast::Expr, args: &[P<ast::Expr>]) {
194 let prec = match func.kind {
195 ast::ExprKind::Field(..) => parser::PREC_FORCE_PAREN,
196 _ => parser::PREC_POSTFIX,
197 };
198
199 self.print_expr_maybe_paren(func, prec);
200 self.print_call_post(args)
201 }
202
2b03887a
FG
203 fn print_expr_method_call(
204 &mut self,
205 segment: &ast::PathSegment,
206 receiver: &ast::Expr,
207 base_args: &[P<ast::Expr>],
208 ) {
209 self.print_expr_maybe_paren(receiver, parser::PREC_POSTFIX);
5099ac24
FG
210 self.word(".");
211 self.print_ident(segment.ident);
487cf647 212 if let Some(args) = &segment.args {
5099ac24
FG
213 self.print_generic_args(args, true);
214 }
215 self.print_call_post(base_args)
216 }
217
218 fn print_expr_binary(&mut self, op: ast::BinOp, lhs: &ast::Expr, rhs: &ast::Expr) {
219 let assoc_op = AssocOp::from_ast_binop(op.node);
220 let prec = assoc_op.precedence() as i8;
221 let fixity = assoc_op.fixity();
222
223 let (left_prec, right_prec) = match fixity {
224 Fixity::Left => (prec, prec + 1),
225 Fixity::Right => (prec + 1, prec),
226 Fixity::None => (prec + 1, prec + 1),
227 };
228
229 let left_prec = match (&lhs.kind, op.node) {
230 // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
231 // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
232 // of `(x as i32) < ...`. We need to convince it _not_ to do that.
233 (&ast::ExprKind::Cast { .. }, ast::BinOpKind::Lt | ast::BinOpKind::Shl) => {
234 parser::PREC_FORCE_PAREN
235 }
236 // We are given `(let _ = a) OP b`.
237 //
238 // - When `OP <= LAnd` we should print `let _ = a OP b` to avoid redundant parens
239 // as the parser will interpret this as `(let _ = a) OP b`.
240 //
241 // - Otherwise, e.g. when we have `(let a = b) < c` in AST,
242 // parens are required since the parser would interpret `let a = b < c` as
243 // `let a = (b < c)`. To achieve this, we force parens.
244 (&ast::ExprKind::Let { .. }, _) if !parser::needs_par_as_let_scrutinee(prec) => {
245 parser::PREC_FORCE_PAREN
246 }
247 _ => left_prec,
248 };
249
250 self.print_expr_maybe_paren(lhs, left_prec);
251 self.space();
252 self.word_space(op.node.to_string());
253 self.print_expr_maybe_paren(rhs, right_prec)
254 }
255
256 fn print_expr_unary(&mut self, op: ast::UnOp, expr: &ast::Expr) {
257 self.word(ast::UnOp::to_string(op));
258 self.print_expr_maybe_paren(expr, parser::PREC_PREFIX)
259 }
260
261 fn print_expr_addr_of(
262 &mut self,
263 kind: ast::BorrowKind,
264 mutability: ast::Mutability,
265 expr: &ast::Expr,
266 ) {
267 self.word("&");
268 match kind {
269 ast::BorrowKind::Ref => self.print_mutability(mutability, false),
270 ast::BorrowKind::Raw => {
271 self.word_nbsp("raw");
272 self.print_mutability(mutability, true);
273 }
274 }
275 self.print_expr_maybe_paren(expr, parser::PREC_PREFIX)
276 }
277
278 pub fn print_expr(&mut self, expr: &ast::Expr) {
279 self.print_expr_outer_attr_style(expr, true)
280 }
281
282 pub(super) fn print_expr_outer_attr_style(&mut self, expr: &ast::Expr, is_inline: bool) {
283 self.maybe_print_comment(expr.span.lo());
284
285 let attrs = &expr.attrs;
286 if is_inline {
287 self.print_outer_attributes_inline(attrs);
288 } else {
289 self.print_outer_attributes(attrs);
290 }
291
292 self.ibox(INDENT_UNIT);
293 self.ann.pre(self, AnnNode::Expr(expr));
487cf647
FG
294 match &expr.kind {
295 ast::ExprKind::Box(expr) => {
5099ac24
FG
296 self.word_space("box");
297 self.print_expr_maybe_paren(expr, parser::PREC_PREFIX);
298 }
487cf647 299 ast::ExprKind::Array(exprs) => {
5099ac24
FG
300 self.print_expr_vec(exprs);
301 }
487cf647 302 ast::ExprKind::ConstBlock(anon_const) => {
04454e1e 303 self.print_expr_anon_const(anon_const, attrs);
5099ac24 304 }
487cf647 305 ast::ExprKind::Repeat(element, count) => {
5099ac24
FG
306 self.print_expr_repeat(element, count);
307 }
487cf647 308 ast::ExprKind::Struct(se) => {
5099ac24
FG
309 self.print_expr_struct(&se.qself, &se.path, &se.fields, &se.rest);
310 }
487cf647 311 ast::ExprKind::Tup(exprs) => {
5099ac24
FG
312 self.print_expr_tup(exprs);
313 }
487cf647
FG
314 ast::ExprKind::Call(func, args) => {
315 self.print_expr_call(func, args);
316 }
317 ast::ExprKind::MethodCall(box ast::MethodCall { seg, receiver, args, .. }) => {
318 self.print_expr_method_call(seg, receiver, args);
5099ac24 319 }
487cf647
FG
320 ast::ExprKind::Binary(op, lhs, rhs) => {
321 self.print_expr_binary(*op, lhs, rhs);
5099ac24 322 }
487cf647
FG
323 ast::ExprKind::Unary(op, expr) => {
324 self.print_expr_unary(*op, expr);
5099ac24 325 }
487cf647
FG
326 ast::ExprKind::AddrOf(k, m, expr) => {
327 self.print_expr_addr_of(*k, *m, expr);
5099ac24 328 }
487cf647
FG
329 ast::ExprKind::Lit(token_lit) => {
330 self.print_token_literal(*token_lit, expr.span);
5099ac24 331 }
487cf647 332 ast::ExprKind::IncludedBytes(bytes) => {
9c376795 333 let lit = token::Lit::new(token::ByteStr, escape_byte_str_symbol(bytes), None);
487cf647 334 self.print_token_literal(lit, expr.span)
5099ac24 335 }
487cf647 336 ast::ExprKind::Cast(expr, ty) => {
5099ac24
FG
337 let prec = AssocOp::As.precedence() as i8;
338 self.print_expr_maybe_paren(expr, prec);
339 self.space();
340 self.word_space("as");
341 self.print_type(ty);
342 }
487cf647 343 ast::ExprKind::Type(expr, ty) => {
5099ac24
FG
344 let prec = AssocOp::Colon.precedence() as i8;
345 self.print_expr_maybe_paren(expr, prec);
346 self.word_space(":");
347 self.print_type(ty);
348 }
487cf647 349 ast::ExprKind::Let(pat, scrutinee, _) => {
5099ac24
FG
350 self.print_let(pat, scrutinee);
351 }
487cf647
FG
352 ast::ExprKind::If(test, blk, elseopt) => self.print_if(test, blk, elseopt.as_deref()),
353 ast::ExprKind::While(test, blk, opt_label) => {
5099ac24
FG
354 if let Some(label) = opt_label {
355 self.print_ident(label.ident);
356 self.word_space(":");
357 }
358 self.cbox(0);
359 self.ibox(0);
360 self.word_nbsp("while");
361 self.print_expr_as_cond(test);
362 self.space();
363 self.print_block_with_attrs(blk, attrs);
364 }
487cf647 365 ast::ExprKind::ForLoop(pat, iter, blk, opt_label) => {
5099ac24
FG
366 if let Some(label) = opt_label {
367 self.print_ident(label.ident);
368 self.word_space(":");
369 }
370 self.cbox(0);
371 self.ibox(0);
372 self.word_nbsp("for");
373 self.print_pat(pat);
374 self.space();
375 self.word_space("in");
376 self.print_expr_as_cond(iter);
377 self.space();
378 self.print_block_with_attrs(blk, attrs);
379 }
487cf647 380 ast::ExprKind::Loop(blk, opt_label, _) => {
5099ac24
FG
381 if let Some(label) = opt_label {
382 self.print_ident(label.ident);
383 self.word_space(":");
384 }
385 self.cbox(0);
386 self.ibox(0);
387 self.word_nbsp("loop");
388 self.print_block_with_attrs(blk, attrs);
389 }
487cf647 390 ast::ExprKind::Match(expr, arms) => {
5099ac24
FG
391 self.cbox(0);
392 self.ibox(0);
393 self.word_nbsp("match");
394 self.print_expr_as_cond(expr);
395 self.space();
396 self.bopen();
397 self.print_inner_attributes_no_trailing_hardbreak(attrs);
398 for arm in arms {
399 self.print_arm(arm);
400 }
401 let empty = attrs.is_empty() && arms.is_empty();
402 self.bclose(expr.span, empty);
403 }
487cf647
FG
404 ast::ExprKind::Closure(box ast::Closure {
405 binder,
5099ac24 406 capture_clause,
9c376795 407 constness,
5099ac24
FG
408 asyncness,
409 movability,
487cf647
FG
410 fn_decl,
411 body,
412 fn_decl_span: _,
413 fn_arg_span: _,
414 }) => {
064997fb 415 self.print_closure_binder(binder);
9c376795 416 self.print_constness(*constness);
487cf647
FG
417 self.print_movability(*movability);
418 self.print_asyncness(*asyncness);
419 self.print_capture_clause(*capture_clause);
5099ac24 420
487cf647 421 self.print_fn_params_and_ret(fn_decl, true);
5099ac24
FG
422 self.space();
423 self.print_expr(body);
424 self.end(); // need to close a box
425
426 // a box will be closed by print_expr, but we didn't want an overall
427 // wrapper so we closed the corresponding opening. so create an
428 // empty box to satisfy the close.
429 self.ibox(0);
430 }
487cf647 431 ast::ExprKind::Block(blk, opt_label) => {
5099ac24
FG
432 if let Some(label) = opt_label {
433 self.print_ident(label.ident);
434 self.word_space(":");
435 }
436 // containing cbox, will be closed by print-block at }
437 self.cbox(0);
438 // head-box, will be closed by print-block after {
439 self.ibox(0);
440 self.print_block_with_attrs(blk, attrs);
441 }
487cf647 442 ast::ExprKind::Async(capture_clause, _, blk) => {
5099ac24 443 self.word_nbsp("async");
487cf647 444 self.print_capture_clause(*capture_clause);
5099ac24
FG
445 // cbox/ibox in analogy to the `ExprKind::Block` arm above
446 self.cbox(0);
447 self.ibox(0);
448 self.print_block_with_attrs(blk, attrs);
449 }
487cf647 450 ast::ExprKind::Await(expr) => {
5099ac24
FG
451 self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX);
452 self.word(".await");
453 }
487cf647 454 ast::ExprKind::Assign(lhs, rhs, _) => {
5099ac24
FG
455 let prec = AssocOp::Assign.precedence() as i8;
456 self.print_expr_maybe_paren(lhs, prec + 1);
457 self.space();
458 self.word_space("=");
459 self.print_expr_maybe_paren(rhs, prec);
460 }
487cf647 461 ast::ExprKind::AssignOp(op, lhs, rhs) => {
5099ac24
FG
462 let prec = AssocOp::Assign.precedence() as i8;
463 self.print_expr_maybe_paren(lhs, prec + 1);
464 self.space();
465 self.word(op.node.to_string());
466 self.word_space("=");
467 self.print_expr_maybe_paren(rhs, prec);
468 }
487cf647 469 ast::ExprKind::Field(expr, ident) => {
5099ac24
FG
470 self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX);
471 self.word(".");
487cf647 472 self.print_ident(*ident);
5099ac24 473 }
487cf647 474 ast::ExprKind::Index(expr, index) => {
5099ac24
FG
475 self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX);
476 self.word("[");
477 self.print_expr(index);
478 self.word("]");
479 }
487cf647 480 ast::ExprKind::Range(start, end, limits) => {
9c376795 481 // Special case for `Range`. `AssocOp` claims that `Range` has higher precedence
5099ac24
FG
482 // than `Assign`, but `x .. x = x` gives a parse error instead of `x .. (x = x)`.
483 // Here we use a fake precedence value so that any child with lower precedence than
9c376795 484 // a "normal" binop gets parenthesized. (`LOr` is the lowest-precedence binop.)
5099ac24 485 let fake_prec = AssocOp::LOr.precedence() as i8;
487cf647 486 if let Some(e) = start {
5099ac24
FG
487 self.print_expr_maybe_paren(e, fake_prec);
488 }
487cf647
FG
489 match limits {
490 ast::RangeLimits::HalfOpen => self.word(".."),
491 ast::RangeLimits::Closed => self.word("..="),
5099ac24 492 }
487cf647 493 if let Some(e) = end {
5099ac24
FG
494 self.print_expr_maybe_paren(e, fake_prec);
495 }
496 }
497 ast::ExprKind::Underscore => self.word("_"),
487cf647
FG
498 ast::ExprKind::Path(None, path) => self.print_path(path, true, 0),
499 ast::ExprKind::Path(Some(qself), path) => self.print_qpath(path, qself, true),
500 ast::ExprKind::Break(opt_label, opt_expr) => {
5099ac24
FG
501 self.word("break");
502 if let Some(label) = opt_label {
503 self.space();
504 self.print_ident(label.ident);
505 }
487cf647 506 if let Some(expr) = opt_expr {
5099ac24
FG
507 self.space();
508 self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
509 }
510 }
511 ast::ExprKind::Continue(opt_label) => {
512 self.word("continue");
513 if let Some(label) = opt_label {
514 self.space();
515 self.print_ident(label.ident);
516 }
517 }
487cf647 518 ast::ExprKind::Ret(result) => {
5099ac24 519 self.word("return");
487cf647 520 if let Some(expr) = result {
5099ac24
FG
521 self.word(" ");
522 self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
523 }
524 }
487cf647 525 ast::ExprKind::Yeet(result) => {
04454e1e
FG
526 self.word("do");
527 self.word(" ");
528 self.word("yeet");
487cf647 529 if let Some(expr) = result {
04454e1e
FG
530 self.word(" ");
531 self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
532 }
533 }
487cf647 534 ast::ExprKind::InlineAsm(a) => {
9ffffee4 535 // FIXME: This should have its own syntax, distinct from a macro invocation.
5099ac24
FG
536 self.word("asm!");
537 self.print_inline_asm(a);
538 }
9ffffee4
FG
539 ast::ExprKind::FormatArgs(fmt) => {
540 // FIXME: This should have its own syntax, distinct from a macro invocation.
541 self.word("format_args!");
542 self.popen();
543 self.rbox(0, Inconsistent);
544 self.word(reconstruct_format_args_template_string(&fmt.template));
545 for arg in fmt.arguments.all_args() {
546 self.word_space(",");
547 self.print_expr(&arg.expr);
548 }
549 self.end();
550 self.pclose();
551 }
487cf647
FG
552 ast::ExprKind::MacCall(m) => self.print_mac(m),
553 ast::ExprKind::Paren(e) => {
5099ac24
FG
554 self.popen();
555 self.print_expr(e);
556 self.pclose();
557 }
487cf647 558 ast::ExprKind::Yield(e) => {
5099ac24
FG
559 self.word("yield");
560
487cf647 561 if let Some(expr) = e {
5099ac24
FG
562 self.space();
563 self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
564 }
565 }
487cf647 566 ast::ExprKind::Try(e) => {
5099ac24
FG
567 self.print_expr_maybe_paren(e, parser::PREC_POSTFIX);
568 self.word("?")
569 }
487cf647 570 ast::ExprKind::TryBlock(blk) => {
5099ac24
FG
571 self.cbox(0);
572 self.ibox(0);
573 self.word_nbsp("try");
574 self.print_block_with_attrs(blk, attrs)
575 }
576 ast::ExprKind::Err => {
577 self.popen();
578 self.word("/*ERROR*/");
579 self.pclose()
580 }
581 }
582 self.ann.post(self, AnnNode::Expr(expr));
583 self.end();
584 }
585
586 fn print_arm(&mut self, arm: &ast::Arm) {
587 // Note, I have no idea why this check is necessary, but here it is.
588 if arm.attrs.is_empty() {
589 self.space();
590 }
591 self.cbox(INDENT_UNIT);
592 self.ibox(0);
593 self.maybe_print_comment(arm.pat.span.lo());
594 self.print_outer_attributes(&arm.attrs);
595 self.print_pat(&arm.pat);
596 self.space();
487cf647 597 if let Some(e) = &arm.guard {
5099ac24
FG
598 self.word_space("if");
599 self.print_expr(e);
600 self.space();
601 }
602 self.word_space("=>");
603
487cf647
FG
604 match &arm.body.kind {
605 ast::ExprKind::Block(blk, opt_label) => {
5099ac24
FG
606 if let Some(label) = opt_label {
607 self.print_ident(label.ident);
608 self.word_space(":");
609 }
610
611 // The block will close the pattern's ibox.
612 self.print_block_unclosed_indent(blk);
613
614 // If it is a user-provided unsafe block, print a comma after it.
615 if let BlockCheckMode::Unsafe(ast::UserProvided) = blk.rules {
616 self.word(",");
617 }
618 }
619 _ => {
620 self.end(); // Close the ibox for the pattern.
621 self.print_expr(&arm.body);
622 self.word(",");
623 }
624 }
625 self.end(); // Close enclosing cbox.
626 }
627
064997fb
FG
628 fn print_closure_binder(&mut self, binder: &ast::ClosureBinder) {
629 match binder {
630 ast::ClosureBinder::NotPresent => {}
631 ast::ClosureBinder::For { generic_params, .. } => {
487cf647 632 self.print_formal_generic_params(generic_params)
064997fb
FG
633 }
634 }
635 }
636
5099ac24
FG
637 fn print_movability(&mut self, movability: ast::Movability) {
638 match movability {
639 ast::Movability::Static => self.word_space("static"),
640 ast::Movability::Movable => {}
641 }
642 }
643
644 fn print_capture_clause(&mut self, capture_clause: ast::CaptureBy) {
645 match capture_clause {
646 ast::CaptureBy::Value => self.word_space("move"),
647 ast::CaptureBy::Ref => {}
648 }
649 }
650}
9ffffee4
FG
651
652pub fn reconstruct_format_args_template_string(pieces: &[FormatArgsPiece]) -> String {
653 let mut template = "\"".to_string();
654 for piece in pieces {
655 match piece {
656 FormatArgsPiece::Literal(s) => {
657 for c in s.as_str().escape_debug() {
658 template.push(c);
659 if let '{' | '}' = c {
660 template.push(c);
661 }
662 }
663 }
664 FormatArgsPiece::Placeholder(p) => {
665 template.push('{');
666 let (Ok(n) | Err(n)) = p.argument.index;
667 write!(template, "{n}").unwrap();
668 if p.format_options != Default::default() || p.format_trait != FormatTrait::Display
669 {
670 template.push_str(":");
671 }
672 if let Some(fill) = p.format_options.fill {
673 template.push(fill);
674 }
675 match p.format_options.alignment {
676 Some(FormatAlignment::Left) => template.push_str("<"),
677 Some(FormatAlignment::Right) => template.push_str(">"),
678 Some(FormatAlignment::Center) => template.push_str("^"),
679 None => {}
680 }
681 match p.format_options.sign {
682 Some(FormatSign::Plus) => template.push('+'),
683 Some(FormatSign::Minus) => template.push('-'),
684 None => {}
685 }
686 if p.format_options.alternate {
687 template.push('#');
688 }
689 if p.format_options.zero_pad {
690 template.push('0');
691 }
692 if let Some(width) = &p.format_options.width {
693 match width {
694 FormatCount::Literal(n) => write!(template, "{n}").unwrap(),
695 FormatCount::Argument(FormatArgPosition {
696 index: Ok(n) | Err(n), ..
697 }) => {
698 write!(template, "{n}$").unwrap();
699 }
700 }
701 }
702 if let Some(precision) = &p.format_options.precision {
703 template.push('.');
704 match precision {
705 FormatCount::Literal(n) => write!(template, "{n}").unwrap(),
706 FormatCount::Argument(FormatArgPosition {
707 index: Ok(n) | Err(n), ..
708 }) => {
709 write!(template, "{n}$").unwrap();
710 }
711 }
712 }
713 match p.format_options.debug_hex {
714 Some(FormatDebugHex::Lower) => template.push('x'),
715 Some(FormatDebugHex::Upper) => template.push('X'),
716 None => {}
717 }
718 template.push_str(match p.format_trait {
719 FormatTrait::Display => "",
720 FormatTrait::Debug => "?",
721 FormatTrait::LowerExp => "e",
722 FormatTrait::UpperExp => "E",
723 FormatTrait::Octal => "o",
724 FormatTrait::Pointer => "p",
725 FormatTrait::Binary => "b",
726 FormatTrait::LowerHex => "x",
727 FormatTrait::UpperHex => "X",
728 });
729 template.push('}');
730 }
731 }
732 }
733 template.push('"');
734 template
735}