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