1#![recursion_limit = "256"]
6use std::cell::Cell;
9use std::vec;
10
11use rustc_abi::ExternAbi;
12use rustc_ast::util::parser::{self, ExprPrecedence, Fixity};
13use rustc_ast::{AttrStyle, DUMMY_NODE_ID, DelimArgs};
14use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent};
15use rustc_ast_pretty::pp::{self, Breaks};
16use rustc_ast_pretty::pprust::state::MacHeader;
17use rustc_ast_pretty::pprust::{Comments, PrintState};
18use rustc_attr_data_structures::{AttributeKind, PrintAttribute};
19use rustc_hir::{
20 BindingMode, ByRef, ConstArgKind, GenericArg, GenericBound, GenericParam, GenericParamKind,
21 HirId, ImplicitSelfKind, LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term,
22 TyPatKind,
23};
24use rustc_span::source_map::SourceMap;
25use rustc_span::{FileName, Ident, Span, Symbol, kw};
26use {rustc_ast as ast, rustc_hir as hir};
27
28pub fn id_to_string(cx: &dyn rustc_hir::intravisit::HirTyCtxt<'_>, hir_id: HirId) -> String {
29 to_string(&cx, |s| s.print_node(cx.hir_node(hir_id)))
30}
31
32pub enum AnnNode<'a> {
33 Name(&'a Symbol),
34 Block(&'a hir::Block<'a>),
35 Item(&'a hir::Item<'a>),
36 SubItem(HirId),
37 Expr(&'a hir::Expr<'a>),
38 Pat(&'a hir::Pat<'a>),
39 TyPat(&'a hir::TyPat<'a>),
40 Arm(&'a hir::Arm<'a>),
41}
42
43pub enum Nested {
44 Item(hir::ItemId),
45 TraitItem(hir::TraitItemId),
46 ImplItem(hir::ImplItemId),
47 ForeignItem(hir::ForeignItemId),
48 Body(hir::BodyId),
49 BodyParamPat(hir::BodyId, usize),
50}
51
52pub trait PpAnn {
53 fn nested(&self, _state: &mut State<'_>, _nested: Nested) {}
54 fn pre(&self, _state: &mut State<'_>, _node: AnnNode<'_>) {}
55 fn post(&self, _state: &mut State<'_>, _node: AnnNode<'_>) {}
56}
57
58impl PpAnn for &dyn rustc_hir::intravisit::HirTyCtxt<'_> {
59 fn nested(&self, state: &mut State<'_>, nested: Nested) {
60 match nested {
61 Nested::Item(id) => state.print_item(self.hir_item(id)),
62 Nested::TraitItem(id) => state.print_trait_item(self.hir_trait_item(id)),
63 Nested::ImplItem(id) => state.print_impl_item(self.hir_impl_item(id)),
64 Nested::ForeignItem(id) => state.print_foreign_item(self.hir_foreign_item(id)),
65 Nested::Body(id) => state.print_expr(self.hir_body(id).value),
66 Nested::BodyParamPat(id, i) => state.print_pat(self.hir_body(id).params[i].pat),
67 }
68 }
69}
70
71pub struct State<'a> {
72 pub s: pp::Printer,
73 comments: Option<Comments<'a>>,
74 attrs: &'a dyn Fn(HirId) -> &'a [hir::Attribute],
75 ann: &'a (dyn PpAnn + 'a),
76}
77
78impl<'a> State<'a> {
79 fn attrs(&self, id: HirId) -> &'a [hir::Attribute] {
80 (self.attrs)(id)
81 }
82
83 fn print_attrs_as_inner(&mut self, attrs: &[hir::Attribute]) {
84 self.print_either_attributes(attrs, ast::AttrStyle::Inner)
85 }
86
87 fn print_attrs_as_outer(&mut self, attrs: &[hir::Attribute]) {
88 self.print_either_attributes(attrs, ast::AttrStyle::Outer)
89 }
90
91 fn print_either_attributes(&mut self, attrs: &[hir::Attribute], style: ast::AttrStyle) {
92 if attrs.is_empty() {
93 return;
94 }
95
96 for attr in attrs {
97 self.print_attribute_inline(attr, style);
98 }
99 self.hardbreak_if_not_bol();
100 }
101
102 fn print_attribute_inline(&mut self, attr: &hir::Attribute, style: AttrStyle) {
103 match &attr {
104 hir::Attribute::Unparsed(unparsed) => {
105 self.maybe_print_comment(unparsed.span.lo());
106 match style {
107 ast::AttrStyle::Inner => self.word("#!["),
108 ast::AttrStyle::Outer => self.word("#["),
109 }
110 self.print_attr_item(&unparsed, unparsed.span);
111 self.word("]");
112 }
113 hir::Attribute::Parsed(AttributeKind::DocComment { style, kind, comment, .. }) => {
114 self.word(rustc_ast_pretty::pprust::state::doc_comment_to_string(
115 *kind, *style, *comment,
116 ));
117 self.hardbreak()
118 }
119 hir::Attribute::Parsed(pa) => {
120 self.word("#[attr = ");
121 pa.print_attribute(self);
122 self.word("]");
123 self.hardbreak()
124 }
125 }
126 }
127
128 fn print_attr_item(&mut self, item: &hir::AttrItem, span: Span) {
129 self.ibox(0);
130 let path = ast::Path {
131 span,
132 segments: item
133 .path
134 .segments
135 .iter()
136 .map(|i| ast::PathSegment { ident: *i, args: None, id: DUMMY_NODE_ID })
137 .collect(),
138 tokens: None,
139 };
140
141 match &item.args {
142 hir::AttrArgs::Delimited(DelimArgs { dspan: _, delim, tokens }) => self
143 .print_mac_common(
144 Some(MacHeader::Path(&path)),
145 false,
146 None,
147 *delim,
148 &tokens,
149 true,
150 span,
151 ),
152 hir::AttrArgs::Empty => {
153 PrintState::print_path(self, &path, false, 0);
154 }
155 hir::AttrArgs::Eq { eq_span: _, expr } => {
156 PrintState::print_path(self, &path, false, 0);
157 self.space();
158 self.word_space("=");
159 let token_str = self.meta_item_lit_to_string(expr);
160 self.word(token_str);
161 }
162 }
163 self.end();
164 }
165
166 fn print_node(&mut self, node: Node<'_>) {
167 match node {
168 Node::Param(a) => self.print_param(a),
169 Node::Item(a) => self.print_item(a),
170 Node::ForeignItem(a) => self.print_foreign_item(a),
171 Node::TraitItem(a) => self.print_trait_item(a),
172 Node::ImplItem(a) => self.print_impl_item(a),
173 Node::Variant(a) => self.print_variant(a),
174 Node::AnonConst(a) => self.print_anon_const(a),
175 Node::ConstBlock(a) => self.print_inline_const(a),
176 Node::ConstArg(a) => self.print_const_arg(a),
177 Node::Expr(a) => self.print_expr(a),
178 Node::ExprField(a) => self.print_expr_field(a),
179 Node::Stmt(a) => self.print_stmt(a),
180 Node::PathSegment(a) => self.print_path_segment(a),
181 Node::Ty(a) => self.print_type(a),
182 Node::AssocItemConstraint(a) => self.print_assoc_item_constraint(a),
183 Node::TraitRef(a) => self.print_trait_ref(a),
184 Node::OpaqueTy(o) => self.print_opaque_ty(o),
185 Node::Pat(a) => self.print_pat(a),
186 Node::TyPat(a) => self.print_ty_pat(a),
187 Node::PatField(a) => self.print_patfield(a),
188 Node::PatExpr(a) => self.print_pat_expr(a),
189 Node::Arm(a) => self.print_arm(a),
190 Node::Infer(_) => self.word("_"),
191 Node::PreciseCapturingNonLifetimeArg(param) => self.print_ident(param.ident),
192 Node::Block(a) => {
193 self.cbox(INDENT_UNIT);
195 self.ibox(0);
197 self.print_block(a);
198 }
199 Node::Lifetime(a) => self.print_lifetime(a),
200 Node::GenericParam(_) => panic!("cannot print Node::GenericParam"),
201 Node::Field(_) => panic!("cannot print Node::Field"),
202 Node::Ctor(..) => panic!("cannot print isolated Ctor"),
206 Node::LetStmt(a) => self.print_local_decl(a),
207 Node::Crate(..) => panic!("cannot print Crate"),
208 Node::WherePredicate(pred) => self.print_where_predicate(pred),
209 Node::Synthetic => unreachable!(),
210 Node::Err(_) => self.word("/*ERROR*/"),
211 }
212 }
213
214 fn print_generic_arg(&mut self, generic_arg: &GenericArg<'_>, elide_lifetimes: bool) {
215 match generic_arg {
216 GenericArg::Lifetime(lt) if !elide_lifetimes => self.print_lifetime(lt),
217 GenericArg::Lifetime(_) => {}
218 GenericArg::Type(ty) => self.print_type(ty.as_unambig_ty()),
219 GenericArg::Const(ct) => self.print_const_arg(ct.as_unambig_ct()),
220 GenericArg::Infer(_inf) => self.word("_"),
221 }
222 }
223}
224
225impl std::ops::Deref for State<'_> {
226 type Target = pp::Printer;
227 fn deref(&self) -> &Self::Target {
228 &self.s
229 }
230}
231
232impl std::ops::DerefMut for State<'_> {
233 fn deref_mut(&mut self) -> &mut Self::Target {
234 &mut self.s
235 }
236}
237
238impl<'a> PrintState<'a> for State<'a> {
239 fn comments(&self) -> Option<&Comments<'a>> {
240 self.comments.as_ref()
241 }
242
243 fn comments_mut(&mut self) -> Option<&mut Comments<'a>> {
244 self.comments.as_mut()
245 }
246
247 fn ann_post(&mut self, ident: Ident) {
248 self.ann.post(self, AnnNode::Name(&ident.name));
249 }
250
251 fn print_generic_args(&mut self, _: &ast::GenericArgs, _colons_before_params: bool) {
252 panic!("AST generic args printed by HIR pretty-printer");
253 }
254}
255
256const INDENT_UNIT: isize = 4;
257
258pub fn print_crate<'a>(
261 sm: &'a SourceMap,
262 krate: &hir::Mod<'_>,
263 filename: FileName,
264 input: String,
265 attrs: &'a dyn Fn(HirId) -> &'a [hir::Attribute],
266 ann: &'a dyn PpAnn,
267) -> String {
268 let mut s = State {
269 s: pp::Printer::new(),
270 comments: Some(Comments::new(sm, filename, input)),
271 attrs,
272 ann,
273 };
274
275 s.print_mod(krate, (*attrs)(hir::CRATE_HIR_ID));
279 s.print_remaining_comments();
280 s.s.eof()
281}
282
283fn to_string<F>(ann: &dyn PpAnn, f: F) -> String
284where
285 F: FnOnce(&mut State<'_>),
286{
287 let mut printer = State { s: pp::Printer::new(), comments: None, attrs: &|_| &[], ann };
288 f(&mut printer);
289 printer.s.eof()
290}
291
292pub fn attribute_to_string(ann: &dyn PpAnn, attr: &hir::Attribute) -> String {
293 to_string(ann, |s| s.print_attribute_inline(attr, AttrStyle::Outer))
294}
295
296pub fn ty_to_string(ann: &dyn PpAnn, ty: &hir::Ty<'_>) -> String {
297 to_string(ann, |s| s.print_type(ty))
298}
299
300pub fn qpath_to_string(ann: &dyn PpAnn, segment: &hir::QPath<'_>) -> String {
301 to_string(ann, |s| s.print_qpath(segment, false))
302}
303
304pub fn pat_to_string(ann: &dyn PpAnn, pat: &hir::Pat<'_>) -> String {
305 to_string(ann, |s| s.print_pat(pat))
306}
307
308pub fn expr_to_string(ann: &dyn PpAnn, pat: &hir::Expr<'_>) -> String {
309 to_string(ann, |s| s.print_expr(pat))
310}
311
312pub fn item_to_string(ann: &dyn PpAnn, pat: &hir::Item<'_>) -> String {
313 to_string(ann, |s| s.print_item(pat))
314}
315
316impl<'a> State<'a> {
317 fn bclose_maybe_open(&mut self, span: rustc_span::Span, close_box: bool) {
318 self.maybe_print_comment(span.hi());
319 self.break_offset_if_not_bol(1, -INDENT_UNIT);
320 self.word("}");
321 if close_box {
322 self.end(); }
324 }
325
326 fn bclose(&mut self, span: rustc_span::Span) {
327 self.bclose_maybe_open(span, true)
328 }
329
330 fn commasep_cmnt<T, F, G>(&mut self, b: Breaks, elts: &[T], mut op: F, mut get_span: G)
331 where
332 F: FnMut(&mut State<'_>, &T),
333 G: FnMut(&T) -> rustc_span::Span,
334 {
335 self.rbox(0, b);
336 let len = elts.len();
337 let mut i = 0;
338 for elt in elts {
339 self.maybe_print_comment(get_span(elt).hi());
340 op(self, elt);
341 i += 1;
342 if i < len {
343 self.word(",");
344 self.maybe_print_trailing_comment(get_span(elt), Some(get_span(&elts[i]).hi()));
345 self.space_if_not_bol();
346 }
347 }
348 self.end();
349 }
350
351 fn commasep_exprs(&mut self, b: Breaks, exprs: &[hir::Expr<'_>]) {
352 self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span);
353 }
354
355 fn print_mod(&mut self, _mod: &hir::Mod<'_>, attrs: &[hir::Attribute]) {
356 self.print_attrs_as_inner(attrs);
357 for &item_id in _mod.item_ids {
358 self.ann.nested(self, Nested::Item(item_id));
359 }
360 }
361
362 fn print_opt_lifetime(&mut self, lifetime: &hir::Lifetime) {
363 if !lifetime.is_elided() {
364 self.print_lifetime(lifetime);
365 self.nbsp();
366 }
367 }
368
369 fn print_type(&mut self, ty: &hir::Ty<'_>) {
370 self.maybe_print_comment(ty.span.lo());
371 self.ibox(0);
372 match ty.kind {
373 hir::TyKind::Slice(ty) => {
374 self.word("[");
375 self.print_type(ty);
376 self.word("]");
377 }
378 hir::TyKind::Ptr(ref mt) => {
379 self.word("*");
380 self.print_mt(mt, true);
381 }
382 hir::TyKind::Ref(lifetime, ref mt) => {
383 self.word("&");
384 self.print_opt_lifetime(lifetime);
385 self.print_mt(mt, false);
386 }
387 hir::TyKind::Never => {
388 self.word("!");
389 }
390 hir::TyKind::Tup(elts) => {
391 self.popen();
392 self.commasep(Inconsistent, elts, |s, ty| s.print_type(ty));
393 if elts.len() == 1 {
394 self.word(",");
395 }
396 self.pclose();
397 }
398 hir::TyKind::BareFn(f) => {
399 self.print_ty_fn(f.abi, f.safety, f.decl, None, f.generic_params, f.param_names);
400 }
401 hir::TyKind::UnsafeBinder(unsafe_binder) => {
402 self.print_unsafe_binder(unsafe_binder);
403 }
404 hir::TyKind::OpaqueDef(..) => self.word("/*impl Trait*/"),
405 hir::TyKind::TraitAscription(bounds) => {
406 self.print_bounds("impl", bounds);
407 }
408 hir::TyKind::Path(ref qpath) => self.print_qpath(qpath, false),
409 hir::TyKind::TraitObject(bounds, lifetime) => {
410 let syntax = lifetime.tag();
411 match syntax {
412 ast::TraitObjectSyntax::Dyn => self.word_nbsp("dyn"),
413 ast::TraitObjectSyntax::DynStar => self.word_nbsp("dyn*"),
414 ast::TraitObjectSyntax::None => {}
415 }
416 let mut first = true;
417 for bound in bounds {
418 if first {
419 first = false;
420 } else {
421 self.nbsp();
422 self.word_space("+");
423 }
424 self.print_poly_trait_ref(bound);
425 }
426 if !lifetime.is_elided() {
427 self.nbsp();
428 self.word_space("+");
429 self.print_lifetime(lifetime.pointer());
430 }
431 }
432 hir::TyKind::Array(ty, ref length) => {
433 self.word("[");
434 self.print_type(ty);
435 self.word("; ");
436 self.print_const_arg(length);
437 self.word("]");
438 }
439 hir::TyKind::Typeof(ref e) => {
440 self.word("typeof(");
441 self.print_anon_const(e);
442 self.word(")");
443 }
444 hir::TyKind::Err(_) => {
445 self.popen();
446 self.word("/*ERROR*/");
447 self.pclose();
448 }
449 hir::TyKind::Infer(()) | hir::TyKind::InferDelegation(..) => {
450 self.word("_");
451 }
452 hir::TyKind::Pat(ty, pat) => {
453 self.print_type(ty);
454 self.word(" is ");
455 self.print_ty_pat(pat);
456 }
457 }
458 self.end()
459 }
460
461 fn print_unsafe_binder(&mut self, unsafe_binder: &hir::UnsafeBinderTy<'_>) {
462 self.ibox(INDENT_UNIT);
463 self.word("unsafe");
464 self.print_generic_params(unsafe_binder.generic_params);
465 self.nbsp();
466 self.print_type(unsafe_binder.inner_ty);
467 self.end();
468 }
469
470 fn print_foreign_item(&mut self, item: &hir::ForeignItem<'_>) {
471 self.hardbreak_if_not_bol();
472 self.maybe_print_comment(item.span.lo());
473 self.print_attrs_as_outer(self.attrs(item.hir_id()));
474 match item.kind {
475 hir::ForeignItemKind::Fn(sig, arg_names, generics) => {
476 self.head("");
477 self.print_fn(
478 sig.decl,
479 sig.header,
480 Some(item.ident.name),
481 generics,
482 arg_names,
483 None,
484 );
485 self.end(); self.word(";");
487 self.end() }
489 hir::ForeignItemKind::Static(t, m, safety) => {
490 self.print_safety(safety);
491 self.head("static");
492 if m.is_mut() {
493 self.word_space("mut");
494 }
495 self.print_ident(item.ident);
496 self.word_space(":");
497 self.print_type(t);
498 self.word(";");
499 self.end(); self.end() }
502 hir::ForeignItemKind::Type => {
503 self.head("type");
504 self.print_ident(item.ident);
505 self.word(";");
506 self.end(); self.end() }
509 }
510 }
511
512 fn print_associated_const(
513 &mut self,
514 ident: Ident,
515 generics: &hir::Generics<'_>,
516 ty: &hir::Ty<'_>,
517 default: Option<hir::BodyId>,
518 ) {
519 self.word_space("const");
520 self.print_ident(ident);
521 self.print_generic_params(generics.params);
522 self.word_space(":");
523 self.print_type(ty);
524 if let Some(expr) = default {
525 self.space();
526 self.word_space("=");
527 self.ann.nested(self, Nested::Body(expr));
528 }
529 self.print_where_clause(generics);
530 self.word(";")
531 }
532
533 fn print_associated_type(
534 &mut self,
535 ident: Ident,
536 generics: &hir::Generics<'_>,
537 bounds: Option<hir::GenericBounds<'_>>,
538 ty: Option<&hir::Ty<'_>>,
539 ) {
540 self.word_space("type");
541 self.print_ident(ident);
542 self.print_generic_params(generics.params);
543 if let Some(bounds) = bounds {
544 self.print_bounds(":", bounds);
545 }
546 self.print_where_clause(generics);
547 if let Some(ty) = ty {
548 self.space();
549 self.word_space("=");
550 self.print_type(ty);
551 }
552 self.word(";")
553 }
554
555 fn print_item(&mut self, item: &hir::Item<'_>) {
556 self.hardbreak_if_not_bol();
557 self.maybe_print_comment(item.span.lo());
558 let attrs = self.attrs(item.hir_id());
559 self.print_attrs_as_outer(attrs);
560 self.ann.pre(self, AnnNode::Item(item));
561 match item.kind {
562 hir::ItemKind::ExternCrate(orig_name) => {
563 self.head("extern crate");
564 if let Some(orig_name) = orig_name {
565 self.print_name(orig_name);
566 self.space();
567 self.word("as");
568 self.space();
569 }
570 self.print_ident(item.ident);
571 self.word(";");
572 self.end(); self.end(); }
575 hir::ItemKind::Use(path, kind) => {
576 self.head("use");
577 self.print_path(path, false);
578
579 match kind {
580 hir::UseKind::Single => {
581 if path.segments.last().unwrap().ident != item.ident {
582 self.space();
583 self.word_space("as");
584 self.print_ident(item.ident);
585 }
586 self.word(";");
587 }
588 hir::UseKind::Glob => self.word("::*;"),
589 hir::UseKind::ListStem => self.word("::{};"),
590 }
591 self.end(); self.end(); }
594 hir::ItemKind::Static(ty, m, expr) => {
595 self.head("static");
596 if m.is_mut() {
597 self.word_space("mut");
598 }
599 self.print_ident(item.ident);
600 self.word_space(":");
601 self.print_type(ty);
602 self.space();
603 self.end(); self.word_space("=");
606 self.ann.nested(self, Nested::Body(expr));
607 self.word(";");
608 self.end(); }
610 hir::ItemKind::Const(ty, generics, expr) => {
611 self.head("const");
612 self.print_ident(item.ident);
613 self.print_generic_params(generics.params);
614 self.word_space(":");
615 self.print_type(ty);
616 self.space();
617 self.end(); self.word_space("=");
620 self.ann.nested(self, Nested::Body(expr));
621 self.print_where_clause(generics);
622 self.word(";");
623 self.end(); }
625 hir::ItemKind::Fn { sig, generics, body, .. } => {
626 self.head("");
627 self.print_fn(
628 sig.decl,
629 sig.header,
630 Some(item.ident.name),
631 generics,
632 &[],
633 Some(body),
634 );
635 self.word(" ");
636 self.end(); self.end(); self.ann.nested(self, Nested::Body(body));
639 }
640 hir::ItemKind::Macro(macro_def, _) => {
641 self.print_mac_def(macro_def, &item.ident, item.span, |_| {});
642 }
643 hir::ItemKind::Mod(_mod) => {
644 self.head("mod");
645 self.print_ident(item.ident);
646 self.nbsp();
647 self.bopen();
648 self.print_mod(_mod, attrs);
649 self.bclose(item.span);
650 }
651 hir::ItemKind::ForeignMod { abi, items } => {
652 self.head("extern");
653 self.word_nbsp(abi.to_string());
654 self.bopen();
655 self.print_attrs_as_inner(self.attrs(item.hir_id()));
656 for item in items {
657 self.ann.nested(self, Nested::ForeignItem(item.id));
658 }
659 self.bclose(item.span);
660 }
661 hir::ItemKind::GlobalAsm { asm, .. } => {
662 self.head("global_asm!");
663 self.print_inline_asm(asm);
664 self.end()
665 }
666 hir::ItemKind::TyAlias(ty, generics) => {
667 self.head("type");
668 self.print_ident(item.ident);
669 self.print_generic_params(generics.params);
670 self.end(); self.print_where_clause(generics);
673 self.space();
674 self.word_space("=");
675 self.print_type(ty);
676 self.word(";");
677 self.end(); }
679 hir::ItemKind::Enum(ref enum_definition, params) => {
680 self.print_enum_def(enum_definition, params, item.ident.name, item.span);
681 }
682 hir::ItemKind::Struct(ref struct_def, generics) => {
683 self.head("struct");
684 self.print_struct(struct_def, generics, item.ident.name, item.span, true);
685 }
686 hir::ItemKind::Union(ref struct_def, generics) => {
687 self.head("union");
688 self.print_struct(struct_def, generics, item.ident.name, item.span, true);
689 }
690 hir::ItemKind::Impl(&hir::Impl {
691 constness,
692 safety,
693 polarity,
694 defaultness,
695 defaultness_span: _,
696 generics,
697 ref of_trait,
698 self_ty,
699 items,
700 }) => {
701 self.head("");
702 self.print_defaultness(defaultness);
703 self.print_safety(safety);
704 self.word_nbsp("impl");
705
706 if let hir::Constness::Const = constness {
707 self.word_nbsp("const");
708 }
709
710 if !generics.params.is_empty() {
711 self.print_generic_params(generics.params);
712 self.space();
713 }
714
715 if let hir::ImplPolarity::Negative(_) = polarity {
716 self.word("!");
717 }
718
719 if let Some(t) = of_trait {
720 self.print_trait_ref(t);
721 self.space();
722 self.word_space("for");
723 }
724
725 self.print_type(self_ty);
726 self.print_where_clause(generics);
727
728 self.space();
729 self.bopen();
730 self.print_attrs_as_inner(attrs);
731 for impl_item in items {
732 self.ann.nested(self, Nested::ImplItem(impl_item.id));
733 }
734 self.bclose(item.span);
735 }
736 hir::ItemKind::Trait(is_auto, safety, generics, bounds, trait_items) => {
737 self.head("");
738 self.print_is_auto(is_auto);
739 self.print_safety(safety);
740 self.word_nbsp("trait");
741 self.print_ident(item.ident);
742 self.print_generic_params(generics.params);
743 self.print_bounds(":", bounds);
744 self.print_where_clause(generics);
745 self.word(" ");
746 self.bopen();
747 for trait_item in trait_items {
748 self.ann.nested(self, Nested::TraitItem(trait_item.id));
749 }
750 self.bclose(item.span);
751 }
752 hir::ItemKind::TraitAlias(generics, bounds) => {
753 self.head("trait");
754 self.print_ident(item.ident);
755 self.print_generic_params(generics.params);
756 self.nbsp();
757 self.print_bounds("=", bounds);
758 self.print_where_clause(generics);
759 self.word(";");
760 self.end(); self.end(); }
763 }
764 self.ann.post(self, AnnNode::Item(item))
765 }
766
767 fn print_trait_ref(&mut self, t: &hir::TraitRef<'_>) {
768 self.print_path(t.path, false);
769 }
770
771 fn print_opaque_ty(&mut self, o: &hir::OpaqueTy<'_>) {
772 self.head("opaque");
773 self.word("{");
774 self.print_bounds("impl", o.bounds);
775 self.word("}");
776 }
777
778 fn print_formal_generic_params(&mut self, generic_params: &[hir::GenericParam<'_>]) {
779 if !generic_params.is_empty() {
780 self.word("for");
781 self.print_generic_params(generic_params);
782 self.nbsp();
783 }
784 }
785
786 fn print_poly_trait_ref(&mut self, t: &hir::PolyTraitRef<'_>) {
787 let hir::TraitBoundModifiers { constness, polarity } = t.modifiers;
788 match constness {
789 hir::BoundConstness::Never => {}
790 hir::BoundConstness::Always(_) => self.word("const"),
791 hir::BoundConstness::Maybe(_) => self.word("~const"),
792 }
793 match polarity {
794 hir::BoundPolarity::Positive => {}
795 hir::BoundPolarity::Negative(_) => self.word("!"),
796 hir::BoundPolarity::Maybe(_) => self.word("?"),
797 }
798 self.print_formal_generic_params(t.bound_generic_params);
799 self.print_trait_ref(&t.trait_ref);
800 }
801
802 fn print_enum_def(
803 &mut self,
804 enum_definition: &hir::EnumDef<'_>,
805 generics: &hir::Generics<'_>,
806 name: Symbol,
807 span: rustc_span::Span,
808 ) {
809 self.head("enum");
810 self.print_name(name);
811 self.print_generic_params(generics.params);
812 self.print_where_clause(generics);
813 self.space();
814 self.print_variants(enum_definition.variants, span);
815 }
816
817 fn print_variants(&mut self, variants: &[hir::Variant<'_>], span: rustc_span::Span) {
818 self.bopen();
819 for v in variants {
820 self.space_if_not_bol();
821 self.maybe_print_comment(v.span.lo());
822 self.print_attrs_as_outer(self.attrs(v.hir_id));
823 self.ibox(INDENT_UNIT);
824 self.print_variant(v);
825 self.word(",");
826 self.end();
827 self.maybe_print_trailing_comment(v.span, None);
828 }
829 self.bclose(span)
830 }
831
832 fn print_defaultness(&mut self, defaultness: hir::Defaultness) {
833 match defaultness {
834 hir::Defaultness::Default { .. } => self.word_nbsp("default"),
835 hir::Defaultness::Final => (),
836 }
837 }
838
839 fn print_struct(
840 &mut self,
841 struct_def: &hir::VariantData<'_>,
842 generics: &hir::Generics<'_>,
843 name: Symbol,
844 span: rustc_span::Span,
845 print_finalizer: bool,
846 ) {
847 self.print_name(name);
848 self.print_generic_params(generics.params);
849 match struct_def {
850 hir::VariantData::Tuple(..) | hir::VariantData::Unit(..) => {
851 if let hir::VariantData::Tuple(..) = struct_def {
852 self.popen();
853 self.commasep(Inconsistent, struct_def.fields(), |s, field| {
854 s.maybe_print_comment(field.span.lo());
855 s.print_attrs_as_outer(s.attrs(field.hir_id));
856 s.print_type(field.ty);
857 });
858 self.pclose();
859 }
860 self.print_where_clause(generics);
861 if print_finalizer {
862 self.word(";");
863 }
864 self.end();
865 self.end() }
867 hir::VariantData::Struct { .. } => {
868 self.print_where_clause(generics);
869 self.print_variant_struct(span, struct_def.fields())
870 }
871 }
872 }
873
874 fn print_variant_struct(&mut self, span: rustc_span::Span, fields: &[hir::FieldDef<'_>]) {
875 self.nbsp();
876 self.bopen();
877 self.hardbreak_if_not_bol();
878
879 for field in fields {
880 self.hardbreak_if_not_bol();
881 self.maybe_print_comment(field.span.lo());
882 self.print_attrs_as_outer(self.attrs(field.hir_id));
883 self.print_ident(field.ident);
884 self.word_nbsp(":");
885 self.print_type(field.ty);
886 self.word(",");
887 }
888
889 self.bclose(span)
890 }
891
892 pub fn print_variant(&mut self, v: &hir::Variant<'_>) {
893 self.head("");
894 let generics = hir::Generics::empty();
895 self.print_struct(&v.data, generics, v.ident.name, v.span, false);
896 if let Some(ref d) = v.disr_expr {
897 self.space();
898 self.word_space("=");
899 self.print_anon_const(d);
900 }
901 }
902
903 fn print_method_sig(
904 &mut self,
905 ident: Ident,
906 m: &hir::FnSig<'_>,
907 generics: &hir::Generics<'_>,
908 arg_names: &[Ident],
909 body_id: Option<hir::BodyId>,
910 ) {
911 self.print_fn(m.decl, m.header, Some(ident.name), generics, arg_names, body_id);
912 }
913
914 fn print_trait_item(&mut self, ti: &hir::TraitItem<'_>) {
915 self.ann.pre(self, AnnNode::SubItem(ti.hir_id()));
916 self.hardbreak_if_not_bol();
917 self.maybe_print_comment(ti.span.lo());
918 self.print_attrs_as_outer(self.attrs(ti.hir_id()));
919 match ti.kind {
920 hir::TraitItemKind::Const(ty, default) => {
921 self.print_associated_const(ti.ident, ti.generics, ty, default);
922 }
923 hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(arg_names)) => {
924 self.print_method_sig(ti.ident, sig, ti.generics, arg_names, None);
925 self.word(";");
926 }
927 hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
928 self.head("");
929 self.print_method_sig(ti.ident, sig, ti.generics, &[], Some(body));
930 self.nbsp();
931 self.end(); self.end(); self.ann.nested(self, Nested::Body(body));
934 }
935 hir::TraitItemKind::Type(bounds, default) => {
936 self.print_associated_type(ti.ident, ti.generics, Some(bounds), default);
937 }
938 }
939 self.ann.post(self, AnnNode::SubItem(ti.hir_id()))
940 }
941
942 fn print_impl_item(&mut self, ii: &hir::ImplItem<'_>) {
943 self.ann.pre(self, AnnNode::SubItem(ii.hir_id()));
944 self.hardbreak_if_not_bol();
945 self.maybe_print_comment(ii.span.lo());
946 self.print_attrs_as_outer(self.attrs(ii.hir_id()));
947
948 match ii.kind {
949 hir::ImplItemKind::Const(ty, expr) => {
950 self.print_associated_const(ii.ident, ii.generics, ty, Some(expr));
951 }
952 hir::ImplItemKind::Fn(ref sig, body) => {
953 self.head("");
954 self.print_method_sig(ii.ident, sig, ii.generics, &[], Some(body));
955 self.nbsp();
956 self.end(); self.end(); self.ann.nested(self, Nested::Body(body));
959 }
960 hir::ImplItemKind::Type(ty) => {
961 self.print_associated_type(ii.ident, ii.generics, None, Some(ty));
962 }
963 }
964 self.ann.post(self, AnnNode::SubItem(ii.hir_id()))
965 }
966
967 fn print_local(
968 &mut self,
969 init: Option<&hir::Expr<'_>>,
970 els: Option<&hir::Block<'_>>,
971 decl: impl Fn(&mut Self),
972 ) {
973 self.space_if_not_bol();
974 self.ibox(INDENT_UNIT);
975 self.word_nbsp("let");
976
977 self.ibox(INDENT_UNIT);
978 decl(self);
979 self.end();
980
981 if let Some(init) = init {
982 self.nbsp();
983 self.word_space("=");
984 self.print_expr(init);
985 }
986
987 if let Some(els) = els {
988 self.nbsp();
989 self.word_space("else");
990 self.cbox(0);
992 self.ibox(0);
994 self.print_block(els);
995 }
996
997 self.end()
998 }
999
1000 fn print_stmt(&mut self, st: &hir::Stmt<'_>) {
1001 self.maybe_print_comment(st.span.lo());
1002 match st.kind {
1003 hir::StmtKind::Let(loc) => {
1004 self.print_local(loc.init, loc.els, |this| this.print_local_decl(loc));
1005 }
1006 hir::StmtKind::Item(item) => self.ann.nested(self, Nested::Item(item)),
1007 hir::StmtKind::Expr(expr) => {
1008 self.space_if_not_bol();
1009 self.print_expr(expr);
1010 }
1011 hir::StmtKind::Semi(expr) => {
1012 self.space_if_not_bol();
1013 self.print_expr(expr);
1014 self.word(";");
1015 }
1016 }
1017 if stmt_ends_with_semi(&st.kind) {
1018 self.word(";");
1019 }
1020 self.maybe_print_trailing_comment(st.span, None)
1021 }
1022
1023 fn print_block(&mut self, blk: &hir::Block<'_>) {
1024 self.print_block_with_attrs(blk, &[])
1025 }
1026
1027 fn print_block_unclosed(&mut self, blk: &hir::Block<'_>) {
1028 self.print_block_maybe_unclosed(blk, &[], false)
1029 }
1030
1031 fn print_block_with_attrs(&mut self, blk: &hir::Block<'_>, attrs: &[hir::Attribute]) {
1032 self.print_block_maybe_unclosed(blk, attrs, true)
1033 }
1034
1035 fn print_block_maybe_unclosed(
1036 &mut self,
1037 blk: &hir::Block<'_>,
1038 attrs: &[hir::Attribute],
1039 close_box: bool,
1040 ) {
1041 match blk.rules {
1042 hir::BlockCheckMode::UnsafeBlock(..) => self.word_space("unsafe"),
1043 hir::BlockCheckMode::DefaultBlock => (),
1044 }
1045 self.maybe_print_comment(blk.span.lo());
1046 self.ann.pre(self, AnnNode::Block(blk));
1047 self.bopen();
1048
1049 self.print_attrs_as_inner(attrs);
1050
1051 for st in blk.stmts {
1052 self.print_stmt(st);
1053 }
1054 if let Some(expr) = blk.expr {
1055 self.space_if_not_bol();
1056 self.print_expr(expr);
1057 self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi()));
1058 }
1059 self.bclose_maybe_open(blk.span, close_box);
1060 self.ann.post(self, AnnNode::Block(blk))
1061 }
1062
1063 fn print_else(&mut self, els: Option<&hir::Expr<'_>>) {
1064 if let Some(els_inner) = els {
1065 match els_inner.kind {
1066 hir::ExprKind::If(i, then, e) => {
1068 self.cbox(INDENT_UNIT - 1);
1069 self.ibox(0);
1070 self.word(" else if ");
1071 self.print_expr_as_cond(i);
1072 self.space();
1073 self.print_expr(then);
1074 self.print_else(e);
1075 }
1076 hir::ExprKind::Block(b, _) => {
1078 self.cbox(INDENT_UNIT - 1);
1079 self.ibox(0);
1080 self.word(" else ");
1081 self.print_block(b);
1082 }
1083 _ => {
1085 panic!("print_if saw if with weird alternative");
1086 }
1087 }
1088 }
1089 }
1090
1091 fn print_if(
1092 &mut self,
1093 test: &hir::Expr<'_>,
1094 blk: &hir::Expr<'_>,
1095 elseopt: Option<&hir::Expr<'_>>,
1096 ) {
1097 self.head("if");
1098 self.print_expr_as_cond(test);
1099 self.space();
1100 self.print_expr(blk);
1101 self.print_else(elseopt)
1102 }
1103
1104 fn print_anon_const(&mut self, constant: &hir::AnonConst) {
1105 self.ann.nested(self, Nested::Body(constant.body))
1106 }
1107
1108 fn print_const_arg(&mut self, const_arg: &hir::ConstArg<'_>) {
1109 match &const_arg.kind {
1110 ConstArgKind::Path(qpath) => self.print_qpath(qpath, true),
1111 ConstArgKind::Anon(anon) => self.print_anon_const(anon),
1112 ConstArgKind::Infer(..) => self.word("_"),
1113 }
1114 }
1115
1116 fn print_call_post(&mut self, args: &[hir::Expr<'_>]) {
1117 self.popen();
1118 self.commasep_exprs(Inconsistent, args);
1119 self.pclose()
1120 }
1121
1122 fn print_expr_as_cond(&mut self, expr: &hir::Expr<'_>) {
1125 self.print_expr_cond_paren(expr, Self::cond_needs_par(expr))
1126 }
1127
1128 fn print_expr_cond_paren(&mut self, expr: &hir::Expr<'_>, needs_par: bool) {
1130 if needs_par {
1131 self.popen();
1132 }
1133 if let hir::ExprKind::DropTemps(actual_expr) = expr.kind {
1134 self.print_expr(actual_expr);
1135 } else {
1136 self.print_expr(expr);
1137 }
1138 if needs_par {
1139 self.pclose();
1140 }
1141 }
1142
1143 fn print_let(&mut self, pat: &hir::Pat<'_>, ty: Option<&hir::Ty<'_>>, init: &hir::Expr<'_>) {
1145 self.word_space("let");
1146 self.print_pat(pat);
1147 if let Some(ty) = ty {
1148 self.word_space(":");
1149 self.print_type(ty);
1150 }
1151 self.space();
1152 self.word_space("=");
1153 let npals = || parser::needs_par_as_let_scrutinee(init.precedence());
1154 self.print_expr_cond_paren(init, Self::cond_needs_par(init) || npals())
1155 }
1156
1157 fn cond_needs_par(expr: &hir::Expr<'_>) -> bool {
1162 match expr.kind {
1163 hir::ExprKind::Break(..) | hir::ExprKind::Closure { .. } | hir::ExprKind::Ret(..) => {
1164 true
1165 }
1166 _ => contains_exterior_struct_lit(expr),
1167 }
1168 }
1169
1170 fn print_expr_vec(&mut self, exprs: &[hir::Expr<'_>]) {
1171 self.ibox(INDENT_UNIT);
1172 self.word("[");
1173 self.commasep_exprs(Inconsistent, exprs);
1174 self.word("]");
1175 self.end()
1176 }
1177
1178 fn print_inline_const(&mut self, constant: &hir::ConstBlock) {
1179 self.ibox(INDENT_UNIT);
1180 self.word_space("const");
1181 self.ann.nested(self, Nested::Body(constant.body));
1182 self.end()
1183 }
1184
1185 fn print_expr_repeat(&mut self, element: &hir::Expr<'_>, count: &hir::ConstArg<'_>) {
1186 self.ibox(INDENT_UNIT);
1187 self.word("[");
1188 self.print_expr(element);
1189 self.word_space(";");
1190 self.print_const_arg(count);
1191 self.word("]");
1192 self.end()
1193 }
1194
1195 fn print_expr_struct(
1196 &mut self,
1197 qpath: &hir::QPath<'_>,
1198 fields: &[hir::ExprField<'_>],
1199 wth: hir::StructTailExpr<'_>,
1200 ) {
1201 self.print_qpath(qpath, true);
1202 self.word("{");
1203 self.commasep_cmnt(Consistent, fields, |s, field| s.print_expr_field(field), |f| f.span);
1204 match wth {
1205 hir::StructTailExpr::Base(expr) => {
1206 self.ibox(INDENT_UNIT);
1207 if !fields.is_empty() {
1208 self.word(",");
1209 self.space();
1210 }
1211 self.word("..");
1212 self.print_expr(expr);
1213 self.end();
1214 }
1215 hir::StructTailExpr::DefaultFields(_) => {
1216 self.ibox(INDENT_UNIT);
1217 if !fields.is_empty() {
1218 self.word(",");
1219 self.space();
1220 }
1221 self.word("..");
1222 self.end();
1223 }
1224 hir::StructTailExpr::None => {
1225 if !fields.is_empty() {
1226 self.word(",");
1227 }
1228 }
1229 }
1230
1231 self.word("}");
1232 }
1233
1234 fn print_expr_field(&mut self, field: &hir::ExprField<'_>) {
1235 if self.attrs(field.hir_id).is_empty() {
1236 self.space();
1237 }
1238 self.cbox(INDENT_UNIT);
1239 self.print_attrs_as_outer(self.attrs(field.hir_id));
1240 if !field.is_shorthand {
1241 self.print_ident(field.ident);
1242 self.word_space(":");
1243 }
1244 self.print_expr(field.expr);
1245 self.end()
1246 }
1247
1248 fn print_expr_tup(&mut self, exprs: &[hir::Expr<'_>]) {
1249 self.popen();
1250 self.commasep_exprs(Inconsistent, exprs);
1251 if exprs.len() == 1 {
1252 self.word(",");
1253 }
1254 self.pclose()
1255 }
1256
1257 fn print_expr_call(&mut self, func: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
1258 let needs_paren = match func.kind {
1259 hir::ExprKind::Field(..) => true,
1260 _ => func.precedence() < ExprPrecedence::Unambiguous,
1261 };
1262
1263 self.print_expr_cond_paren(func, needs_paren);
1264 self.print_call_post(args)
1265 }
1266
1267 fn print_expr_method_call(
1268 &mut self,
1269 segment: &hir::PathSegment<'_>,
1270 receiver: &hir::Expr<'_>,
1271 args: &[hir::Expr<'_>],
1272 ) {
1273 let base_args = args;
1274 self.print_expr_cond_paren(receiver, receiver.precedence() < ExprPrecedence::Unambiguous);
1275 self.word(".");
1276 self.print_ident(segment.ident);
1277
1278 let generic_args = segment.args();
1279 if !generic_args.args.is_empty() || !generic_args.constraints.is_empty() {
1280 self.print_generic_args(generic_args, true);
1281 }
1282
1283 self.print_call_post(base_args)
1284 }
1285
1286 fn print_expr_binary(&mut self, op: hir::BinOp, lhs: &hir::Expr<'_>, rhs: &hir::Expr<'_>) {
1287 let binop_prec = op.node.precedence();
1288 let left_prec = lhs.precedence();
1289 let right_prec = rhs.precedence();
1290
1291 let (mut left_needs_paren, right_needs_paren) = match op.node.fixity() {
1292 Fixity::Left => (left_prec < binop_prec, right_prec <= binop_prec),
1293 Fixity::Right => (left_prec <= binop_prec, right_prec < binop_prec),
1294 Fixity::None => (left_prec <= binop_prec, right_prec <= binop_prec),
1295 };
1296
1297 match (&lhs.kind, op.node) {
1298 (&hir::ExprKind::Cast { .. }, hir::BinOpKind::Lt | hir::BinOpKind::Shl) => {
1302 left_needs_paren = true;
1303 }
1304 (&hir::ExprKind::Let { .. }, _) if !parser::needs_par_as_let_scrutinee(binop_prec) => {
1305 left_needs_paren = true;
1306 }
1307 _ => {}
1308 }
1309
1310 self.print_expr_cond_paren(lhs, left_needs_paren);
1311 self.space();
1312 self.word_space(op.node.as_str());
1313 self.print_expr_cond_paren(rhs, right_needs_paren);
1314 }
1315
1316 fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr<'_>) {
1317 self.word(op.as_str());
1318 self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Prefix);
1319 }
1320
1321 fn print_expr_addr_of(
1322 &mut self,
1323 kind: hir::BorrowKind,
1324 mutability: hir::Mutability,
1325 expr: &hir::Expr<'_>,
1326 ) {
1327 self.word("&");
1328 match kind {
1329 hir::BorrowKind::Ref => self.print_mutability(mutability, false),
1330 hir::BorrowKind::Raw => {
1331 self.word_nbsp("raw");
1332 self.print_mutability(mutability, true);
1333 }
1334 }
1335 self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Prefix);
1336 }
1337
1338 fn print_literal(&mut self, lit: &hir::Lit) {
1339 self.maybe_print_comment(lit.span.lo());
1340 self.word(lit.node.to_string())
1341 }
1342
1343 fn print_inline_asm(&mut self, asm: &hir::InlineAsm<'_>) {
1344 enum AsmArg<'a> {
1345 Template(String),
1346 Operand(&'a hir::InlineAsmOperand<'a>),
1347 Options(ast::InlineAsmOptions),
1348 }
1349
1350 let mut args = vec![AsmArg::Template(ast::InlineAsmTemplatePiece::to_string(asm.template))];
1351 args.extend(asm.operands.iter().map(|(o, _)| AsmArg::Operand(o)));
1352 if !asm.options.is_empty() {
1353 args.push(AsmArg::Options(asm.options));
1354 }
1355
1356 self.popen();
1357 self.commasep(Consistent, &args, |s, arg| match *arg {
1358 AsmArg::Template(ref template) => s.print_string(template, ast::StrStyle::Cooked),
1359 AsmArg::Operand(op) => match *op {
1360 hir::InlineAsmOperand::In { reg, expr } => {
1361 s.word("in");
1362 s.popen();
1363 s.word(format!("{reg}"));
1364 s.pclose();
1365 s.space();
1366 s.print_expr(expr);
1367 }
1368 hir::InlineAsmOperand::Out { reg, late, ref expr } => {
1369 s.word(if late { "lateout" } else { "out" });
1370 s.popen();
1371 s.word(format!("{reg}"));
1372 s.pclose();
1373 s.space();
1374 match expr {
1375 Some(expr) => s.print_expr(expr),
1376 None => s.word("_"),
1377 }
1378 }
1379 hir::InlineAsmOperand::InOut { reg, late, expr } => {
1380 s.word(if late { "inlateout" } else { "inout" });
1381 s.popen();
1382 s.word(format!("{reg}"));
1383 s.pclose();
1384 s.space();
1385 s.print_expr(expr);
1386 }
1387 hir::InlineAsmOperand::SplitInOut { reg, late, in_expr, ref out_expr } => {
1388 s.word(if late { "inlateout" } else { "inout" });
1389 s.popen();
1390 s.word(format!("{reg}"));
1391 s.pclose();
1392 s.space();
1393 s.print_expr(in_expr);
1394 s.space();
1395 s.word_space("=>");
1396 match out_expr {
1397 Some(out_expr) => s.print_expr(out_expr),
1398 None => s.word("_"),
1399 }
1400 }
1401 hir::InlineAsmOperand::Const { ref anon_const } => {
1402 s.word("const");
1403 s.space();
1404 s.ann.nested(s, Nested::Body(anon_const.body))
1406 }
1407 hir::InlineAsmOperand::SymFn { ref expr } => {
1408 s.word("sym_fn");
1409 s.space();
1410 s.print_expr(expr);
1411 }
1412 hir::InlineAsmOperand::SymStatic { ref path, def_id: _ } => {
1413 s.word("sym_static");
1414 s.space();
1415 s.print_qpath(path, true);
1416 }
1417 hir::InlineAsmOperand::Label { block } => {
1418 s.head("label");
1419 s.print_block(block);
1420 }
1421 },
1422 AsmArg::Options(opts) => {
1423 s.word("options");
1424 s.popen();
1425 s.commasep(Inconsistent, &opts.human_readable_names(), |s, &opt| {
1426 s.word(opt);
1427 });
1428 s.pclose();
1429 }
1430 });
1431 self.pclose();
1432 }
1433
1434 fn print_expr(&mut self, expr: &hir::Expr<'_>) {
1435 self.maybe_print_comment(expr.span.lo());
1436 self.print_attrs_as_outer(self.attrs(expr.hir_id));
1437 self.ibox(INDENT_UNIT);
1438 self.ann.pre(self, AnnNode::Expr(expr));
1439 match expr.kind {
1440 hir::ExprKind::Array(exprs) => {
1441 self.print_expr_vec(exprs);
1442 }
1443 hir::ExprKind::ConstBlock(ref anon_const) => {
1444 self.print_inline_const(anon_const);
1445 }
1446 hir::ExprKind::Repeat(element, ref count) => {
1447 self.print_expr_repeat(element, count);
1448 }
1449 hir::ExprKind::Struct(qpath, fields, wth) => {
1450 self.print_expr_struct(qpath, fields, wth);
1451 }
1452 hir::ExprKind::Tup(exprs) => {
1453 self.print_expr_tup(exprs);
1454 }
1455 hir::ExprKind::Call(func, args) => {
1456 self.print_expr_call(func, args);
1457 }
1458 hir::ExprKind::MethodCall(segment, receiver, args, _) => {
1459 self.print_expr_method_call(segment, receiver, args);
1460 }
1461 hir::ExprKind::Use(expr, _) => {
1462 self.print_expr(expr);
1463 self.word(".use");
1464 }
1465 hir::ExprKind::Binary(op, lhs, rhs) => {
1466 self.print_expr_binary(op, lhs, rhs);
1467 }
1468 hir::ExprKind::Unary(op, expr) => {
1469 self.print_expr_unary(op, expr);
1470 }
1471 hir::ExprKind::AddrOf(k, m, expr) => {
1472 self.print_expr_addr_of(k, m, expr);
1473 }
1474 hir::ExprKind::Lit(lit) => {
1475 self.print_literal(lit);
1476 }
1477 hir::ExprKind::Cast(expr, ty) => {
1478 self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Cast);
1479 self.space();
1480 self.word_space("as");
1481 self.print_type(ty);
1482 }
1483 hir::ExprKind::Type(expr, ty) => {
1484 self.word("type_ascribe!(");
1485 self.ibox(0);
1486 self.print_expr(expr);
1487
1488 self.word(",");
1489 self.space_if_not_bol();
1490 self.print_type(ty);
1491
1492 self.end();
1493 self.word(")");
1494 }
1495 hir::ExprKind::DropTemps(init) => {
1496 self.cbox(INDENT_UNIT);
1498 self.ibox(0);
1499 self.bopen();
1500
1501 let temp = Ident::from_str("_t");
1503 self.print_local(Some(init), None, |this| this.print_ident(temp));
1504 self.word(";");
1505
1506 self.space_if_not_bol();
1508 self.print_ident(temp);
1509
1510 self.bclose_maybe_open(expr.span, true);
1512 }
1513 hir::ExprKind::Let(&hir::LetExpr { pat, ty, init, .. }) => {
1514 self.print_let(pat, ty, init);
1515 }
1516 hir::ExprKind::If(test, blk, elseopt) => {
1517 self.print_if(test, blk, elseopt);
1518 }
1519 hir::ExprKind::Loop(blk, opt_label, _, _) => {
1520 if let Some(label) = opt_label {
1521 self.print_ident(label.ident);
1522 self.word_space(":");
1523 }
1524 self.head("loop");
1525 self.print_block(blk);
1526 }
1527 hir::ExprKind::Match(expr, arms, _) => {
1528 self.cbox(INDENT_UNIT);
1529 self.ibox(INDENT_UNIT);
1530 self.word_nbsp("match");
1531 self.print_expr_as_cond(expr);
1532 self.space();
1533 self.bopen();
1534 for arm in arms {
1535 self.print_arm(arm);
1536 }
1537 self.bclose(expr.span);
1538 }
1539 hir::ExprKind::Closure(&hir::Closure {
1540 binder,
1541 constness,
1542 capture_clause,
1543 bound_generic_params,
1544 fn_decl,
1545 body,
1546 fn_decl_span: _,
1547 fn_arg_span: _,
1548 kind: _,
1549 def_id: _,
1550 }) => {
1551 self.print_closure_binder(binder, bound_generic_params);
1552 self.print_constness(constness);
1553 self.print_capture_clause(capture_clause);
1554
1555 self.print_closure_params(fn_decl, body);
1556 self.space();
1557
1558 self.ann.nested(self, Nested::Body(body));
1560 self.end(); self.ibox(0);
1566 }
1567 hir::ExprKind::Block(blk, opt_label) => {
1568 if let Some(label) = opt_label {
1569 self.print_ident(label.ident);
1570 self.word_space(":");
1571 }
1572 self.cbox(0);
1574 self.ibox(0);
1576 self.print_block(blk);
1577 }
1578 hir::ExprKind::Assign(lhs, rhs, _) => {
1579 self.print_expr_cond_paren(lhs, lhs.precedence() <= ExprPrecedence::Assign);
1580 self.space();
1581 self.word_space("=");
1582 self.print_expr_cond_paren(rhs, rhs.precedence() < ExprPrecedence::Assign);
1583 }
1584 hir::ExprKind::AssignOp(op, lhs, rhs) => {
1585 self.print_expr_cond_paren(lhs, lhs.precedence() <= ExprPrecedence::Assign);
1586 self.space();
1587 self.word(op.node.as_str());
1588 self.word_space("=");
1589 self.print_expr_cond_paren(rhs, rhs.precedence() < ExprPrecedence::Assign);
1590 }
1591 hir::ExprKind::Field(expr, ident) => {
1592 self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Unambiguous);
1593 self.word(".");
1594 self.print_ident(ident);
1595 }
1596 hir::ExprKind::Index(expr, index, _) => {
1597 self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Unambiguous);
1598 self.word("[");
1599 self.print_expr(index);
1600 self.word("]");
1601 }
1602 hir::ExprKind::Path(ref qpath) => self.print_qpath(qpath, true),
1603 hir::ExprKind::Break(destination, opt_expr) => {
1604 self.word("break");
1605 if let Some(label) = destination.label {
1606 self.space();
1607 self.print_ident(label.ident);
1608 }
1609 if let Some(expr) = opt_expr {
1610 self.space();
1611 self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump);
1612 }
1613 }
1614 hir::ExprKind::Continue(destination) => {
1615 self.word("continue");
1616 if let Some(label) = destination.label {
1617 self.space();
1618 self.print_ident(label.ident);
1619 }
1620 }
1621 hir::ExprKind::Ret(result) => {
1622 self.word("return");
1623 if let Some(expr) = result {
1624 self.word(" ");
1625 self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump);
1626 }
1627 }
1628 hir::ExprKind::Become(result) => {
1629 self.word("become");
1630 self.word(" ");
1631 self.print_expr_cond_paren(result, result.precedence() < ExprPrecedence::Jump);
1632 }
1633 hir::ExprKind::InlineAsm(asm) => {
1634 self.word("asm!");
1635 self.print_inline_asm(asm);
1636 }
1637 hir::ExprKind::OffsetOf(container, fields) => {
1638 self.word("offset_of!(");
1639 self.print_type(container);
1640 self.word(",");
1641 self.space();
1642
1643 if let Some((&first, rest)) = fields.split_first() {
1644 self.print_ident(first);
1645
1646 for &field in rest {
1647 self.word(".");
1648 self.print_ident(field);
1649 }
1650 }
1651
1652 self.word(")");
1653 }
1654 hir::ExprKind::UnsafeBinderCast(kind, expr, ty) => {
1655 match kind {
1656 ast::UnsafeBinderCastKind::Wrap => self.word("wrap_binder!("),
1657 ast::UnsafeBinderCastKind::Unwrap => self.word("unwrap_binder!("),
1658 }
1659 self.print_expr(expr);
1660 if let Some(ty) = ty {
1661 self.word(",");
1662 self.space();
1663 self.print_type(ty);
1664 }
1665 self.word(")");
1666 }
1667 hir::ExprKind::Yield(expr, _) => {
1668 self.word_space("yield");
1669 self.print_expr_cond_paren(expr, expr.precedence() < ExprPrecedence::Jump);
1670 }
1671 hir::ExprKind::Err(_) => {
1672 self.popen();
1673 self.word("/*ERROR*/");
1674 self.pclose();
1675 }
1676 }
1677 self.ann.post(self, AnnNode::Expr(expr));
1678 self.end()
1679 }
1680
1681 fn print_local_decl(&mut self, loc: &hir::LetStmt<'_>) {
1682 self.print_pat(loc.pat);
1683 if let Some(ty) = loc.ty {
1684 self.word_space(":");
1685 self.print_type(ty);
1686 }
1687 }
1688
1689 fn print_name(&mut self, name: Symbol) {
1690 self.print_ident(Ident::with_dummy_span(name))
1691 }
1692
1693 fn print_path<R>(&mut self, path: &hir::Path<'_, R>, colons_before_params: bool) {
1694 self.maybe_print_comment(path.span.lo());
1695
1696 for (i, segment) in path.segments.iter().enumerate() {
1697 if i > 0 {
1698 self.word("::")
1699 }
1700 if segment.ident.name != kw::PathRoot {
1701 self.print_ident(segment.ident);
1702 self.print_generic_args(segment.args(), colons_before_params);
1703 }
1704 }
1705 }
1706
1707 fn print_path_segment(&mut self, segment: &hir::PathSegment<'_>) {
1708 if segment.ident.name != kw::PathRoot {
1709 self.print_ident(segment.ident);
1710 self.print_generic_args(segment.args(), false);
1711 }
1712 }
1713
1714 fn print_qpath(&mut self, qpath: &hir::QPath<'_>, colons_before_params: bool) {
1715 match *qpath {
1716 hir::QPath::Resolved(None, path) => self.print_path(path, colons_before_params),
1717 hir::QPath::Resolved(Some(qself), path) => {
1718 self.word("<");
1719 self.print_type(qself);
1720 self.space();
1721 self.word_space("as");
1722
1723 for (i, segment) in path.segments[..path.segments.len() - 1].iter().enumerate() {
1724 if i > 0 {
1725 self.word("::")
1726 }
1727 if segment.ident.name != kw::PathRoot {
1728 self.print_ident(segment.ident);
1729 self.print_generic_args(segment.args(), colons_before_params);
1730 }
1731 }
1732
1733 self.word(">");
1734 self.word("::");
1735 let item_segment = path.segments.last().unwrap();
1736 self.print_ident(item_segment.ident);
1737 self.print_generic_args(item_segment.args(), colons_before_params)
1738 }
1739 hir::QPath::TypeRelative(qself, item_segment) => {
1740 if let hir::TyKind::Path(hir::QPath::Resolved(None, _)) = qself.kind {
1744 self.print_type(qself);
1745 } else {
1746 self.word("<");
1747 self.print_type(qself);
1748 self.word(">");
1749 }
1750
1751 self.word("::");
1752 self.print_ident(item_segment.ident);
1753 self.print_generic_args(item_segment.args(), colons_before_params)
1754 }
1755 hir::QPath::LangItem(lang_item, span) => {
1756 self.word("#[lang = \"");
1757 self.print_ident(Ident::new(lang_item.name(), span));
1758 self.word("\"]");
1759 }
1760 }
1761 }
1762
1763 fn print_generic_args(
1764 &mut self,
1765 generic_args: &hir::GenericArgs<'_>,
1766 colons_before_params: bool,
1767 ) {
1768 match generic_args.parenthesized {
1769 hir::GenericArgsParentheses::No => {
1770 let start = if colons_before_params { "::<" } else { "<" };
1771 let empty = Cell::new(true);
1772 let start_or_comma = |this: &mut Self| {
1773 if empty.get() {
1774 empty.set(false);
1775 this.word(start)
1776 } else {
1777 this.word_space(",")
1778 }
1779 };
1780
1781 let mut nonelided_generic_args: bool = false;
1782 let elide_lifetimes = generic_args.args.iter().all(|arg| match arg {
1783 GenericArg::Lifetime(lt) if lt.is_elided() => true,
1784 GenericArg::Lifetime(_) => {
1785 nonelided_generic_args = true;
1786 false
1787 }
1788 _ => {
1789 nonelided_generic_args = true;
1790 true
1791 }
1792 });
1793
1794 if nonelided_generic_args {
1795 start_or_comma(self);
1796 self.commasep(Inconsistent, generic_args.args, |s, generic_arg| {
1797 s.print_generic_arg(generic_arg, elide_lifetimes)
1798 });
1799 }
1800
1801 for constraint in generic_args.constraints {
1802 start_or_comma(self);
1803 self.print_assoc_item_constraint(constraint);
1804 }
1805
1806 if !empty.get() {
1807 self.word(">")
1808 }
1809 }
1810 hir::GenericArgsParentheses::ParenSugar => {
1811 let (inputs, output) = generic_args.paren_sugar_inputs_output().unwrap();
1812
1813 self.word("(");
1814 self.commasep(Inconsistent, inputs, |s, ty| s.print_type(ty));
1815 self.word(")");
1816
1817 self.space_if_not_bol();
1818 self.word_space("->");
1819 self.print_type(output);
1820 }
1821 hir::GenericArgsParentheses::ReturnTypeNotation => {
1822 self.word("(..)");
1823 }
1824 }
1825 }
1826
1827 fn print_assoc_item_constraint(&mut self, constraint: &hir::AssocItemConstraint<'_>) {
1828 self.print_ident(constraint.ident);
1829 self.print_generic_args(constraint.gen_args, false);
1830 self.space();
1831 match constraint.kind {
1832 hir::AssocItemConstraintKind::Equality { ref term } => {
1833 self.word_space("=");
1834 match term {
1835 Term::Ty(ty) => self.print_type(ty),
1836 Term::Const(c) => self.print_const_arg(c),
1837 }
1838 }
1839 hir::AssocItemConstraintKind::Bound { bounds } => {
1840 self.print_bounds(":", bounds);
1841 }
1842 }
1843 }
1844
1845 fn print_pat_expr(&mut self, expr: &hir::PatExpr<'_>) {
1846 match &expr.kind {
1847 hir::PatExprKind::Lit { lit, negated } => {
1848 if *negated {
1849 self.word("-");
1850 }
1851 self.print_literal(lit);
1852 }
1853 hir::PatExprKind::ConstBlock(c) => self.print_inline_const(c),
1854 hir::PatExprKind::Path(qpath) => self.print_qpath(qpath, true),
1855 }
1856 }
1857
1858 fn print_ty_pat(&mut self, pat: &hir::TyPat<'_>) {
1859 self.maybe_print_comment(pat.span.lo());
1860 self.ann.pre(self, AnnNode::TyPat(pat));
1861 match pat.kind {
1864 TyPatKind::Range(begin, end) => {
1865 self.print_const_arg(begin);
1866 self.word("..=");
1867 self.print_const_arg(end);
1868 }
1869 TyPatKind::Err(_) => {
1870 self.popen();
1871 self.word("/*ERROR*/");
1872 self.pclose();
1873 }
1874 }
1875 self.ann.post(self, AnnNode::TyPat(pat))
1876 }
1877
1878 fn print_pat(&mut self, pat: &hir::Pat<'_>) {
1879 self.maybe_print_comment(pat.span.lo());
1880 self.ann.pre(self, AnnNode::Pat(pat));
1881 match pat.kind {
1884 PatKind::Wild => self.word("_"),
1885 PatKind::Never => self.word("!"),
1886 PatKind::Binding(BindingMode(by_ref, mutbl), _, ident, sub) => {
1887 if mutbl.is_mut() {
1888 self.word_nbsp("mut");
1889 }
1890 if let ByRef::Yes(rmutbl) = by_ref {
1891 self.word_nbsp("ref");
1892 if rmutbl.is_mut() {
1893 self.word_nbsp("mut");
1894 }
1895 }
1896 self.print_ident(ident);
1897 if let Some(p) = sub {
1898 self.word("@");
1899 self.print_pat(p);
1900 }
1901 }
1902 PatKind::TupleStruct(ref qpath, elts, ddpos) => {
1903 self.print_qpath(qpath, true);
1904 self.popen();
1905 if let Some(ddpos) = ddpos.as_opt_usize() {
1906 self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p));
1907 if ddpos != 0 {
1908 self.word_space(",");
1909 }
1910 self.word("..");
1911 if ddpos != elts.len() {
1912 self.word(",");
1913 self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(p));
1914 }
1915 } else {
1916 self.commasep(Inconsistent, elts, |s, p| s.print_pat(p));
1917 }
1918 self.pclose();
1919 }
1920 PatKind::Struct(ref qpath, fields, etc) => {
1921 self.print_qpath(qpath, true);
1922 self.nbsp();
1923 self.word("{");
1924 let empty = fields.is_empty() && !etc;
1925 if !empty {
1926 self.space();
1927 }
1928 self.commasep_cmnt(Consistent, fields, |s, f| s.print_patfield(f), |f| f.pat.span);
1929 if etc {
1930 if !fields.is_empty() {
1931 self.word_space(",");
1932 }
1933 self.word("..");
1934 }
1935 if !empty {
1936 self.space();
1937 }
1938 self.word("}");
1939 }
1940 PatKind::Or(pats) => {
1941 self.strsep("|", true, Inconsistent, pats, |s, p| s.print_pat(p));
1942 }
1943 PatKind::Tuple(elts, ddpos) => {
1944 self.popen();
1945 if let Some(ddpos) = ddpos.as_opt_usize() {
1946 self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p));
1947 if ddpos != 0 {
1948 self.word_space(",");
1949 }
1950 self.word("..");
1951 if ddpos != elts.len() {
1952 self.word(",");
1953 self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(p));
1954 }
1955 } else {
1956 self.commasep(Inconsistent, elts, |s, p| s.print_pat(p));
1957 if elts.len() == 1 {
1958 self.word(",");
1959 }
1960 }
1961 self.pclose();
1962 }
1963 PatKind::Box(inner) => {
1964 let is_range_inner = matches!(inner.kind, PatKind::Range(..));
1965 self.word("box ");
1966 if is_range_inner {
1967 self.popen();
1968 }
1969 self.print_pat(inner);
1970 if is_range_inner {
1971 self.pclose();
1972 }
1973 }
1974 PatKind::Deref(inner) => {
1975 self.word("deref!");
1976 self.popen();
1977 self.print_pat(inner);
1978 self.pclose();
1979 }
1980 PatKind::Ref(inner, mutbl) => {
1981 let is_range_inner = matches!(inner.kind, PatKind::Range(..));
1982 self.word("&");
1983 self.word(mutbl.prefix_str());
1984 if is_range_inner {
1985 self.popen();
1986 }
1987 self.print_pat(inner);
1988 if is_range_inner {
1989 self.pclose();
1990 }
1991 }
1992 PatKind::Expr(e) => self.print_pat_expr(e),
1993 PatKind::Range(begin, end, end_kind) => {
1994 if let Some(expr) = begin {
1995 self.print_pat_expr(expr);
1996 }
1997 match end_kind {
1998 RangeEnd::Included => self.word("..."),
1999 RangeEnd::Excluded => self.word(".."),
2000 }
2001 if let Some(expr) = end {
2002 self.print_pat_expr(expr);
2003 }
2004 }
2005 PatKind::Slice(before, slice, after) => {
2006 self.word("[");
2007 self.commasep(Inconsistent, before, |s, p| s.print_pat(p));
2008 if let Some(p) = slice {
2009 if !before.is_empty() {
2010 self.word_space(",");
2011 }
2012 if let PatKind::Wild = p.kind {
2013 } else {
2015 self.print_pat(p);
2016 }
2017 self.word("..");
2018 if !after.is_empty() {
2019 self.word_space(",");
2020 }
2021 }
2022 self.commasep(Inconsistent, after, |s, p| s.print_pat(p));
2023 self.word("]");
2024 }
2025 PatKind::Guard(inner, cond) => {
2026 self.print_pat(inner);
2027 self.space();
2028 self.word_space("if");
2029 self.print_expr(cond);
2030 }
2031 PatKind::Err(_) => {
2032 self.popen();
2033 self.word("/*ERROR*/");
2034 self.pclose();
2035 }
2036 }
2037 self.ann.post(self, AnnNode::Pat(pat))
2038 }
2039
2040 fn print_patfield(&mut self, field: &hir::PatField<'_>) {
2041 if self.attrs(field.hir_id).is_empty() {
2042 self.space();
2043 }
2044 self.cbox(INDENT_UNIT);
2045 self.print_attrs_as_outer(self.attrs(field.hir_id));
2046 if !field.is_shorthand {
2047 self.print_ident(field.ident);
2048 self.word_nbsp(":");
2049 }
2050 self.print_pat(field.pat);
2051 self.end();
2052 }
2053
2054 fn print_param(&mut self, arg: &hir::Param<'_>) {
2055 self.print_attrs_as_outer(self.attrs(arg.hir_id));
2056 self.print_pat(arg.pat);
2057 }
2058
2059 fn print_implicit_self(&mut self, implicit_self_kind: &hir::ImplicitSelfKind) {
2060 match implicit_self_kind {
2061 ImplicitSelfKind::Imm => {
2062 self.word("self");
2063 }
2064 ImplicitSelfKind::Mut => {
2065 self.print_mutability(hir::Mutability::Mut, false);
2066 self.word("self");
2067 }
2068 ImplicitSelfKind::RefImm => {
2069 self.word("&");
2070 self.word("self");
2071 }
2072 ImplicitSelfKind::RefMut => {
2073 self.word("&");
2074 self.print_mutability(hir::Mutability::Mut, false);
2075 self.word("self");
2076 }
2077 ImplicitSelfKind::None => unreachable!(),
2078 }
2079 }
2080
2081 fn print_arm(&mut self, arm: &hir::Arm<'_>) {
2082 if self.attrs(arm.hir_id).is_empty() {
2085 self.space();
2086 }
2087 self.cbox(INDENT_UNIT);
2088 self.ann.pre(self, AnnNode::Arm(arm));
2089 self.ibox(0);
2090 self.print_attrs_as_outer(self.attrs(arm.hir_id));
2091 self.print_pat(arm.pat);
2092 self.space();
2093 if let Some(ref g) = arm.guard {
2094 self.word_space("if");
2095 self.print_expr(g);
2096 self.space();
2097 }
2098 self.word_space("=>");
2099
2100 match arm.body.kind {
2101 hir::ExprKind::Block(blk, opt_label) => {
2102 if let Some(label) = opt_label {
2103 self.print_ident(label.ident);
2104 self.word_space(":");
2105 }
2106 self.print_block_unclosed(blk);
2108
2109 if let hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::UserProvided) = blk.rules
2111 {
2112 self.word(",");
2113 }
2114 }
2115 _ => {
2116 self.end(); self.print_expr(arm.body);
2118 self.word(",");
2119 }
2120 }
2121 self.ann.post(self, AnnNode::Arm(arm));
2122 self.end() }
2124
2125 fn print_fn(
2126 &mut self,
2127 decl: &hir::FnDecl<'_>,
2128 header: hir::FnHeader,
2129 name: Option<Symbol>,
2130 generics: &hir::Generics<'_>,
2131 arg_names: &[Ident],
2132 body_id: Option<hir::BodyId>,
2133 ) {
2134 self.print_fn_header_info(header);
2135
2136 if let Some(name) = name {
2137 self.nbsp();
2138 self.print_name(name);
2139 }
2140 self.print_generic_params(generics.params);
2141
2142 self.popen();
2143 assert!(arg_names.is_empty() || body_id.is_none());
2145 let mut i = 0;
2146 let mut print_arg = |s: &mut Self, ty: Option<&hir::Ty<'_>>| {
2147 if i == 0 && decl.implicit_self.has_implicit_self() {
2148 s.print_implicit_self(&decl.implicit_self);
2149 } else {
2150 if let Some(arg_name) = arg_names.get(i) {
2151 if arg_name.name != kw::Empty {
2152 s.word(arg_name.to_string());
2153 s.word(":");
2154 s.space();
2155 }
2156 } else if let Some(body_id) = body_id {
2157 s.ann.nested(s, Nested::BodyParamPat(body_id, i));
2158 s.word(":");
2159 s.space();
2160 }
2161 if let Some(ty) = ty {
2162 s.print_type(ty);
2163 }
2164 }
2165 i += 1;
2166 };
2167 self.commasep(Inconsistent, decl.inputs, |s, ty| {
2168 s.ibox(INDENT_UNIT);
2169 print_arg(s, Some(ty));
2170 s.end();
2171 });
2172 if decl.c_variadic {
2173 self.word(", ");
2174 print_arg(self, None);
2175 self.word("...");
2176 }
2177 self.pclose();
2178
2179 self.print_fn_output(decl);
2180 self.print_where_clause(generics)
2181 }
2182
2183 fn print_closure_params(&mut self, decl: &hir::FnDecl<'_>, body_id: hir::BodyId) {
2184 self.word("|");
2185 let mut i = 0;
2186 self.commasep(Inconsistent, decl.inputs, |s, ty| {
2187 s.ibox(INDENT_UNIT);
2188
2189 s.ann.nested(s, Nested::BodyParamPat(body_id, i));
2190 i += 1;
2191
2192 if let hir::TyKind::Infer(()) = ty.kind {
2193 } else {
2195 s.word(":");
2196 s.space();
2197 s.print_type(ty);
2198 }
2199 s.end();
2200 });
2201 self.word("|");
2202
2203 match decl.output {
2204 hir::FnRetTy::Return(ty) => {
2205 self.space_if_not_bol();
2206 self.word_space("->");
2207 self.print_type(ty);
2208 self.maybe_print_comment(ty.span.lo());
2209 }
2210 hir::FnRetTy::DefaultReturn(..) => {}
2211 }
2212 }
2213
2214 fn print_capture_clause(&mut self, capture_clause: hir::CaptureBy) {
2215 match capture_clause {
2216 hir::CaptureBy::Value { .. } => self.word_space("move"),
2217 hir::CaptureBy::Use { .. } => self.word_space("use"),
2218 hir::CaptureBy::Ref => {}
2219 }
2220 }
2221
2222 fn print_closure_binder(
2223 &mut self,
2224 binder: hir::ClosureBinder,
2225 generic_params: &[GenericParam<'_>],
2226 ) {
2227 let generic_params = generic_params
2228 .iter()
2229 .filter(|p| {
2230 matches!(
2231 p,
2232 GenericParam {
2233 kind: GenericParamKind::Lifetime { kind: LifetimeParamKind::Explicit },
2234 ..
2235 }
2236 )
2237 })
2238 .collect::<Vec<_>>();
2239
2240 match binder {
2241 hir::ClosureBinder::Default => {}
2242 hir::ClosureBinder::For { .. } if generic_params.is_empty() => self.word("for<>"),
2245 hir::ClosureBinder::For { .. } => {
2246 self.word("for");
2247 self.word("<");
2248
2249 self.commasep(Inconsistent, &generic_params, |s, param| {
2250 s.print_generic_param(param)
2251 });
2252
2253 self.word(">");
2254 self.nbsp();
2255 }
2256 }
2257 }
2258
2259 fn print_bounds<'b>(
2260 &mut self,
2261 prefix: &'static str,
2262 bounds: impl IntoIterator<Item = &'b hir::GenericBound<'b>>,
2263 ) {
2264 let mut first = true;
2265 for bound in bounds {
2266 if first {
2267 self.word(prefix);
2268 }
2269 if !(first && prefix.is_empty()) {
2270 self.nbsp();
2271 }
2272 if first {
2273 first = false;
2274 } else {
2275 self.word_space("+");
2276 }
2277
2278 match bound {
2279 GenericBound::Trait(tref) => {
2280 self.print_poly_trait_ref(tref);
2281 }
2282 GenericBound::Outlives(lt) => {
2283 self.print_lifetime(lt);
2284 }
2285 GenericBound::Use(args, _) => {
2286 self.word("use <");
2287
2288 self.commasep(Inconsistent, *args, |s, arg| {
2289 s.print_precise_capturing_arg(*arg)
2290 });
2291
2292 self.word(">");
2293 }
2294 }
2295 }
2296 }
2297
2298 fn print_precise_capturing_arg(&mut self, arg: PreciseCapturingArg<'_>) {
2299 match arg {
2300 PreciseCapturingArg::Lifetime(lt) => self.print_lifetime(lt),
2301 PreciseCapturingArg::Param(arg) => self.print_ident(arg.ident),
2302 }
2303 }
2304
2305 fn print_generic_params(&mut self, generic_params: &[GenericParam<'_>]) {
2306 let is_lifetime_elided = |generic_param: &GenericParam<'_>| {
2307 matches!(
2308 generic_param.kind,
2309 GenericParamKind::Lifetime { kind: LifetimeParamKind::Elided(_) }
2310 )
2311 };
2312
2313 if !generic_params.is_empty() && !generic_params.iter().all(is_lifetime_elided) {
2316 self.word("<");
2317
2318 self.commasep(
2319 Inconsistent,
2320 generic_params.iter().filter(|gp| !is_lifetime_elided(gp)),
2321 |s, param| s.print_generic_param(param),
2322 );
2323
2324 self.word(">");
2325 }
2326 }
2327
2328 fn print_generic_param(&mut self, param: &GenericParam<'_>) {
2329 if let GenericParamKind::Const { .. } = param.kind {
2330 self.word_space("const");
2331 }
2332
2333 self.print_ident(param.name.ident());
2334
2335 match param.kind {
2336 GenericParamKind::Lifetime { .. } => {}
2337 GenericParamKind::Type { default, .. } => {
2338 if let Some(default) = default {
2339 self.space();
2340 self.word_space("=");
2341 self.print_type(default);
2342 }
2343 }
2344 GenericParamKind::Const { ty, ref default, synthetic: _ } => {
2345 self.word_space(":");
2346 self.print_type(ty);
2347 if let Some(default) = default {
2348 self.space();
2349 self.word_space("=");
2350 self.print_const_arg(default);
2351 }
2352 }
2353 }
2354 }
2355
2356 fn print_lifetime(&mut self, lifetime: &hir::Lifetime) {
2357 self.print_ident(lifetime.ident)
2358 }
2359
2360 fn print_where_clause(&mut self, generics: &hir::Generics<'_>) {
2361 if generics.predicates.is_empty() {
2362 return;
2363 }
2364
2365 self.space();
2366 self.word_space("where");
2367
2368 for (i, predicate) in generics.predicates.iter().enumerate() {
2369 if i != 0 {
2370 self.word_space(",");
2371 }
2372 self.print_where_predicate(predicate);
2373 }
2374 }
2375
2376 fn print_where_predicate(&mut self, predicate: &hir::WherePredicate<'_>) {
2377 self.print_attrs_as_outer(self.attrs(predicate.hir_id));
2378 match *predicate.kind {
2379 hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate {
2380 bound_generic_params,
2381 bounded_ty,
2382 bounds,
2383 ..
2384 }) => {
2385 self.print_formal_generic_params(bound_generic_params);
2386 self.print_type(bounded_ty);
2387 self.print_bounds(":", bounds);
2388 }
2389 hir::WherePredicateKind::RegionPredicate(hir::WhereRegionPredicate {
2390 lifetime,
2391 bounds,
2392 ..
2393 }) => {
2394 self.print_lifetime(lifetime);
2395 self.word(":");
2396
2397 for (i, bound) in bounds.iter().enumerate() {
2398 match bound {
2399 GenericBound::Outlives(lt) => {
2400 self.print_lifetime(lt);
2401 }
2402 _ => panic!("unexpected bound on lifetime param: {bound:?}"),
2403 }
2404
2405 if i != 0 {
2406 self.word(":");
2407 }
2408 }
2409 }
2410 hir::WherePredicateKind::EqPredicate(hir::WhereEqPredicate {
2411 lhs_ty, rhs_ty, ..
2412 }) => {
2413 self.print_type(lhs_ty);
2414 self.space();
2415 self.word_space("=");
2416 self.print_type(rhs_ty);
2417 }
2418 }
2419 }
2420
2421 fn print_mutability(&mut self, mutbl: hir::Mutability, print_const: bool) {
2422 match mutbl {
2423 hir::Mutability::Mut => self.word_nbsp("mut"),
2424 hir::Mutability::Not => {
2425 if print_const {
2426 self.word_nbsp("const")
2427 }
2428 }
2429 }
2430 }
2431
2432 fn print_mt(&mut self, mt: &hir::MutTy<'_>, print_const: bool) {
2433 self.print_mutability(mt.mutbl, print_const);
2434 self.print_type(mt.ty);
2435 }
2436
2437 fn print_fn_output(&mut self, decl: &hir::FnDecl<'_>) {
2438 match decl.output {
2439 hir::FnRetTy::Return(ty) => {
2440 self.space_if_not_bol();
2441 self.ibox(INDENT_UNIT);
2442 self.word_space("->");
2443 self.print_type(ty);
2444 }
2445 hir::FnRetTy::DefaultReturn(..) => return,
2446 }
2447 self.end();
2448
2449 if let hir::FnRetTy::Return(output) = decl.output {
2450 self.maybe_print_comment(output.span.lo());
2451 }
2452 }
2453
2454 fn print_ty_fn(
2455 &mut self,
2456 abi: ExternAbi,
2457 safety: hir::Safety,
2458 decl: &hir::FnDecl<'_>,
2459 name: Option<Symbol>,
2460 generic_params: &[hir::GenericParam<'_>],
2461 arg_names: &[Ident],
2462 ) {
2463 self.ibox(INDENT_UNIT);
2464 self.print_formal_generic_params(generic_params);
2465 let generics = hir::Generics::empty();
2466 self.print_fn(
2467 decl,
2468 hir::FnHeader {
2469 safety: safety.into(),
2470 abi,
2471 constness: hir::Constness::NotConst,
2472 asyncness: hir::IsAsync::NotAsync,
2473 },
2474 name,
2475 generics,
2476 arg_names,
2477 None,
2478 );
2479 self.end();
2480 }
2481
2482 fn print_fn_header_info(&mut self, header: hir::FnHeader) {
2483 self.print_constness(header.constness);
2484
2485 let safety = match header.safety {
2486 hir::HeaderSafety::SafeTargetFeatures => {
2487 self.word_nbsp("#[target_feature]");
2488 hir::Safety::Safe
2489 }
2490 hir::HeaderSafety::Normal(safety) => safety,
2491 };
2492
2493 match header.asyncness {
2494 hir::IsAsync::NotAsync => {}
2495 hir::IsAsync::Async(_) => self.word_nbsp("async"),
2496 }
2497
2498 self.print_safety(safety);
2499
2500 if header.abi != ExternAbi::Rust {
2501 self.word_nbsp("extern");
2502 self.word_nbsp(header.abi.to_string());
2503 }
2504
2505 self.word("fn")
2506 }
2507
2508 fn print_constness(&mut self, s: hir::Constness) {
2509 match s {
2510 hir::Constness::NotConst => {}
2511 hir::Constness::Const => self.word_nbsp("const"),
2512 }
2513 }
2514
2515 fn print_safety(&mut self, s: hir::Safety) {
2516 match s {
2517 hir::Safety::Safe => {}
2518 hir::Safety::Unsafe => self.word_nbsp("unsafe"),
2519 }
2520 }
2521
2522 fn print_is_auto(&mut self, s: hir::IsAuto) {
2523 match s {
2524 hir::IsAuto::Yes => self.word_nbsp("auto"),
2525 hir::IsAuto::No => {}
2526 }
2527 }
2528}
2529
2530fn expr_requires_semi_to_be_stmt(e: &hir::Expr<'_>) -> bool {
2540 !matches!(
2541 e.kind,
2542 hir::ExprKind::If(..)
2543 | hir::ExprKind::Match(..)
2544 | hir::ExprKind::Block(..)
2545 | hir::ExprKind::Loop(..)
2546 )
2547}
2548
2549fn stmt_ends_with_semi(stmt: &hir::StmtKind<'_>) -> bool {
2553 match *stmt {
2554 hir::StmtKind::Let(_) => true,
2555 hir::StmtKind::Item(_) => false,
2556 hir::StmtKind::Expr(e) => expr_requires_semi_to_be_stmt(e),
2557 hir::StmtKind::Semi(..) => false,
2558 }
2559}
2560
2561fn contains_exterior_struct_lit(value: &hir::Expr<'_>) -> bool {
2565 match value.kind {
2566 hir::ExprKind::Struct(..) => true,
2567
2568 hir::ExprKind::Assign(lhs, rhs, _)
2569 | hir::ExprKind::AssignOp(_, lhs, rhs)
2570 | hir::ExprKind::Binary(_, lhs, rhs) => {
2571 contains_exterior_struct_lit(lhs) || contains_exterior_struct_lit(rhs)
2573 }
2574 hir::ExprKind::Unary(_, x)
2575 | hir::ExprKind::Cast(x, _)
2576 | hir::ExprKind::Type(x, _)
2577 | hir::ExprKind::Field(x, _)
2578 | hir::ExprKind::Index(x, _, _) => {
2579 contains_exterior_struct_lit(x)
2581 }
2582
2583 hir::ExprKind::MethodCall(_, receiver, ..) => {
2584 contains_exterior_struct_lit(receiver)
2586 }
2587
2588 _ => false,
2589 }
2590}