1use ast::StaticItem;
2use itertools::Itertools;
3use rustc_ast::{self as ast, EiiImpl, ModKind, Safety, TraitAlias};
4use rustc_span::Ident;
5
6use crate::pp::BoxMarker;
7use crate::pp::Breaks::Inconsistent;
8use crate::pprust::state::fixup::FixupContext;
9use crate::pprust::state::{AnnNode, INDENT_UNIT, PrintState, State};
10
11enum DelegationKind<'a> {
12 Single,
13 List(&'a [(Ident, Option<Ident>)]),
14 Glob,
15}
16
17fn visibility_qualified(vis: &ast::Visibility, s: &str) -> String {
18 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}",
State::to_string(|s| s.print_visibility(vis)), s))
})format!("{}{}", State::to_string(|s| s.print_visibility(vis)), s)
19}
20
21impl<'a> State<'a> {
22 fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod, attrs: &[ast::Attribute]) {
23 self.print_inner_attributes(attrs);
24 for item in &nmod.items {
25 self.print_foreign_item(item);
26 }
27 }
28
29 pub(crate) fn print_foreign_item(&mut self, item: &ast::ForeignItem) {
30 let ast::Item { id, span, ref attrs, ref kind, ref vis, tokens: _ } = *item;
31 self.ann.pre(self, AnnNode::SubItem(id));
32 self.hardbreak_if_not_bol();
33 self.maybe_print_comment(span.lo());
34 self.print_outer_attributes(attrs);
35 match kind {
36 ast::ForeignItemKind::Fn(func) => {
37 self.print_fn_full(vis, attrs, &*func);
38 }
39 ast::ForeignItemKind::Static(ast::StaticItem {
40 ident,
41 ty,
42 mutability,
43 expr,
44 safety,
45 define_opaque,
46 eii_impls,
47 }) => self.print_item_const(
48 *ident,
49 Some(*mutability),
50 &ast::Generics::default(),
51 ty,
52 expr.as_deref(),
53 vis,
54 *safety,
55 ast::Defaultness::Implicit,
56 define_opaque.as_deref(),
57 eii_impls,
58 ),
59 ast::ForeignItemKind::TyAlias(ast::TyAlias {
60 defaultness,
61 ident,
62 generics,
63 after_where_clause,
64 bounds,
65 ty,
66 }) => {
67 self.print_associated_type(
68 *ident,
69 generics,
70 after_where_clause,
71 bounds,
72 ty.as_deref(),
73 vis,
74 *defaultness,
75 );
76 }
77 ast::ForeignItemKind::MacCall(m) => {
78 self.print_mac(m);
79 if m.args.need_semicolon() {
80 self.word(";");
81 }
82 }
83 }
84 self.ann.post(self, AnnNode::SubItem(id))
85 }
86
87 fn print_item_const(
88 &mut self,
89 ident: Ident,
90 mutbl: Option<ast::Mutability>,
91 generics: &ast::Generics,
92 ty: &ast::Ty,
93 body: Option<&ast::Expr>,
94 vis: &ast::Visibility,
95 safety: ast::Safety,
96 defaultness: ast::Defaultness,
97 define_opaque: Option<&[(ast::NodeId, ast::Path)]>,
98 eii_impls: &[EiiImpl],
99 ) {
100 self.print_define_opaques(define_opaque);
101 for eii_impl in eii_impls {
102 self.print_eii_impl(eii_impl);
103 }
104 let (cb, ib) = self.head("");
105 self.print_visibility(vis);
106 self.print_safety(safety);
107 self.print_defaultness(defaultness);
108 let leading = match mutbl {
109 None => "const",
110 Some(ast::Mutability::Not) => "static",
111 Some(ast::Mutability::Mut) => "static mut",
112 };
113 self.word_space(leading);
114 self.print_ident(ident);
115 self.print_generic_params(&generics.params);
116 self.word_space(":");
117 self.print_type(ty);
118 if body.is_some() {
119 self.space();
120 }
121 self.end(ib);
122 if let Some(body) = body {
123 self.word_space("=");
124 self.print_expr(body, FixupContext::default());
125 }
126 self.print_where_clause(&generics.where_clause);
127 self.word(";");
128 self.end(cb);
129 }
130
131 fn print_associated_type(
132 &mut self,
133 ident: Ident,
134 generics: &ast::Generics,
135 after_where_clause: &ast::WhereClause,
136 bounds: &ast::GenericBounds,
137 ty: Option<&ast::Ty>,
138 vis: &ast::Visibility,
139 defaultness: ast::Defaultness,
140 ) {
141 let (cb, ib) = self.head("");
142 self.print_visibility(vis);
143 self.print_defaultness(defaultness);
144 self.word_space("type");
145 self.print_ident(ident);
146 self.print_generic_params(&generics.params);
147 if !bounds.is_empty() {
148 self.word_nbsp(":");
149 self.print_type_bounds(bounds);
150 }
151 self.print_where_clause(&generics.where_clause);
152 if let Some(ty) = ty {
153 self.space();
154 self.word_space("=");
155 self.print_type(ty);
156 }
157 self.print_where_clause(&after_where_clause);
158 self.word(";");
159 self.end(ib);
160 self.end(cb);
161 }
162
163 pub(crate) fn print_item(&mut self, item: &ast::Item) {
165 if self.is_sdylib_interface && item.span.is_dummy() {
166 return;
168 }
169 self.hardbreak_if_not_bol();
170 self.maybe_print_comment(item.span.lo());
171 self.print_outer_attributes(&item.attrs);
172 self.ann.pre(self, AnnNode::Item(item));
173 match &item.kind {
174 ast::ItemKind::ExternCrate(orig_name, ident) => {
175 let (cb, ib) = self.head(visibility_qualified(&item.vis, "extern crate"));
176 if let &Some(orig_name) = orig_name {
177 self.print_name(orig_name);
178 self.space();
179 self.word("as");
180 self.space();
181 }
182 self.print_ident(*ident);
183 self.word(";");
184 self.end(ib);
185 self.end(cb);
186 }
187 ast::ItemKind::Use(tree) => {
188 self.print_visibility(&item.vis);
189 self.word_nbsp("use");
190 self.print_use_tree(tree);
191 self.word(";");
192 }
193 ast::ItemKind::Static(StaticItem {
194 ident,
195 ty,
196 safety,
197 mutability: mutbl,
198 expr: body,
199 define_opaque,
200 eii_impls,
201 }) => {
202 self.print_safety(*safety);
203 self.print_item_const(
204 *ident,
205 Some(*mutbl),
206 &ast::Generics::default(),
207 ty,
208 body.as_deref(),
209 &item.vis,
210 ast::Safety::Default,
211 ast::Defaultness::Implicit,
212 define_opaque.as_deref(),
213 eii_impls,
214 );
215 }
216 ast::ItemKind::ConstBlock(ast::ConstBlockItem { id: _, span: _, block }) => {
217 let ib = self.ibox(INDENT_UNIT);
218 self.word("const");
219 self.nbsp();
220 {
221 let cb = self.cbox(0);
222 let ib = self.ibox(0);
223 self.print_block_with_attrs(block, &[], cb, ib);
224 }
225 self.end(ib);
226 }
227 ast::ItemKind::Const(ast::ConstItem {
228 defaultness,
229 ident,
230 generics,
231 ty,
232 body,
233 kind: _,
234 define_opaque,
235 }) => {
236 self.print_item_const(
237 *ident,
238 None,
239 generics,
240 ty,
241 body.as_deref(),
242 &item.vis,
243 ast::Safety::Default,
244 *defaultness,
245 define_opaque.as_deref(),
246 &[],
247 );
248 }
249 ast::ItemKind::Fn(func) => {
250 self.print_fn_full(&item.vis, &item.attrs, &*func);
251 }
252 ast::ItemKind::Mod(safety, ident, mod_kind) => {
253 let (cb, ib) = self.head(Self::to_string(|s| {
254 s.print_visibility(&item.vis);
255 s.print_safety(*safety);
256 s.word("mod");
257 }));
258 self.print_ident(*ident);
259
260 match mod_kind {
261 ModKind::Loaded(items, ..) => {
262 self.nbsp();
263 self.bopen(ib);
264 self.print_inner_attributes(&item.attrs);
265 for item in items {
266 self.print_item(item);
267 }
268 let empty = item.attrs.is_empty() && items.is_empty();
269 self.bclose(item.span, empty, cb);
270 }
271 ModKind::Unloaded => {
272 self.word(";");
273 self.end(ib);
274 self.end(cb);
275 }
276 }
277 }
278 ast::ItemKind::ForeignMod(nmod) => {
279 let (cb, ib) = self.head(Self::to_string(|s| {
280 s.print_safety(nmod.safety);
281 s.word("extern");
282 }));
283 if let Some(abi) = nmod.abi {
284 self.print_token_literal(abi.as_token_lit(), abi.span);
285 self.nbsp();
286 }
287 self.bopen(ib);
288 self.print_foreign_mod(nmod, &item.attrs);
289 let empty = item.attrs.is_empty() && nmod.items.is_empty();
290 self.bclose(item.span, empty, cb);
291 }
292 ast::ItemKind::GlobalAsm(asm) => {
293 let (cb, ib) = self.head(visibility_qualified(&item.vis, "global_asm!"));
295 self.print_inline_asm(asm);
296 self.word(";");
297 self.end(ib);
298 self.end(cb);
299 }
300 ast::ItemKind::TyAlias(ast::TyAlias {
301 defaultness,
302 ident,
303 generics,
304 after_where_clause,
305 bounds,
306 ty,
307 }) => {
308 self.print_associated_type(
309 *ident,
310 generics,
311 after_where_clause,
312 bounds,
313 ty.as_deref(),
314 &item.vis,
315 *defaultness,
316 );
317 }
318 ast::ItemKind::Enum(ident, generics, enum_definition) => {
319 self.print_enum_def(enum_definition, generics, *ident, item.span, &item.vis);
320 }
321 ast::ItemKind::Struct(ident, generics, struct_def) => {
322 let (cb, ib) = self.head(visibility_qualified(&item.vis, "struct"));
323 self.print_struct(struct_def, generics, *ident, item.span, true, cb, ib);
324 }
325 ast::ItemKind::Union(ident, generics, struct_def) => {
326 let (cb, ib) = self.head(visibility_qualified(&item.vis, "union"));
327 self.print_struct(struct_def, generics, *ident, item.span, true, cb, ib);
328 }
329 ast::ItemKind::Impl(ast::Impl { generics, of_trait, self_ty, items, constness }) => {
330 let (cb, ib) = self.head("");
331 self.print_visibility(&item.vis);
332
333 let impl_generics = |this: &mut Self| {
334 this.word("impl");
335
336 if generics.params.is_empty() {
337 this.nbsp();
338 } else {
339 this.print_generic_params(&generics.params);
340 this.space();
341 }
342 };
343
344 if let Some(of_trait) = of_trait {
345 let ast::TraitImplHeader { defaultness, safety, polarity, ref trait_ref } =
346 *of_trait;
347 self.print_defaultness(defaultness);
348 self.print_constness(*constness);
349 self.print_safety(safety);
350 impl_generics(self);
351 if let ast::ImplPolarity::Negative(_) = polarity {
352 self.word("!");
353 }
354 self.print_trait_ref(trait_ref);
355 self.space();
356 self.word_space("for");
357 } else {
358 self.print_constness(*constness);
359 impl_generics(self);
360 }
361
362 self.print_type(self_ty);
363 self.print_where_clause(&generics.where_clause);
364
365 self.space();
366 self.bopen(ib);
367 self.print_inner_attributes(&item.attrs);
368 for impl_item in items {
369 self.print_assoc_item(impl_item);
370 }
371 let empty = item.attrs.is_empty() && items.is_empty();
372 self.bclose(item.span, empty, cb);
373 }
374 ast::ItemKind::Trait(ast::Trait {
375 impl_restriction,
376 constness,
377 safety,
378 is_auto,
379 ident,
380 generics,
381 bounds,
382 items,
383 }) => {
384 let (cb, ib) = self.head("");
385 self.print_visibility(&item.vis);
386 self.print_impl_restriction(impl_restriction);
387 self.print_constness(*constness);
388 self.print_safety(*safety);
389 self.print_is_auto(*is_auto);
390 self.word_nbsp("trait");
391 self.print_ident(*ident);
392 self.print_generic_params(&generics.params);
393 if !bounds.is_empty() {
394 self.word_nbsp(":");
395 self.print_type_bounds(bounds);
396 }
397 self.print_where_clause(&generics.where_clause);
398 self.word(" ");
399 self.bopen(ib);
400 self.print_inner_attributes(&item.attrs);
401 for trait_item in items {
402 self.print_assoc_item(trait_item);
403 }
404 let empty = item.attrs.is_empty() && items.is_empty();
405 self.bclose(item.span, empty, cb);
406 }
407 ast::ItemKind::TraitAlias(TraitAlias { constness, ident, generics, bounds }) => {
408 let (cb, ib) = self.head("");
409 self.print_visibility(&item.vis);
410 self.print_constness(*constness);
411 self.word_nbsp("trait");
412 self.print_ident(*ident);
413 self.print_generic_params(&generics.params);
414 self.nbsp();
415 if !bounds.is_empty() {
416 self.word_nbsp("=");
417 self.print_type_bounds(bounds);
418 }
419 self.print_where_clause(&generics.where_clause);
420 self.word(";");
421 self.end(ib);
422 self.end(cb);
423 }
424 ast::ItemKind::MacCall(mac) => {
425 self.print_mac(mac);
426 if mac.args.need_semicolon() {
427 self.word(";");
428 }
429 }
430 ast::ItemKind::MacroDef(ident, macro_def) => {
431 self.print_mac_def(macro_def, &ident, item.span, |state| {
432 state.print_visibility(&item.vis)
433 });
434 }
435 ast::ItemKind::Delegation(deleg) => self.print_delegation(
436 &item.attrs,
437 &item.vis,
438 &deleg.qself,
439 &deleg.path,
440 DelegationKind::Single,
441 &deleg.body,
442 ),
443 ast::ItemKind::DelegationMac(deleg) => self.print_delegation(
444 &item.attrs,
445 &item.vis,
446 &deleg.qself,
447 &deleg.prefix,
448 match &deleg.suffixes {
449 ast::DelegationSuffixes::List(s) => DelegationKind::List(s),
450 ast::DelegationSuffixes::Glob(_) => DelegationKind::Glob,
451 },
452 &deleg.body,
453 ),
454 }
455 self.ann.post(self, AnnNode::Item(item))
456 }
457
458 fn print_enum_def(
459 &mut self,
460 enum_definition: &ast::EnumDef,
461 generics: &ast::Generics,
462 ident: Ident,
463 span: rustc_span::Span,
464 visibility: &ast::Visibility,
465 ) {
466 let (cb, ib) = self.head(visibility_qualified(visibility, "enum"));
467 self.print_ident(ident);
468 self.print_generic_params(&generics.params);
469 self.print_where_clause(&generics.where_clause);
470 self.space();
471 self.bopen(ib);
472 for v in enum_definition.variants.iter() {
473 self.space_if_not_bol();
474 self.maybe_print_comment(v.span.lo());
475 self.print_outer_attributes(&v.attrs);
476 let ib = self.ibox(0);
477 self.print_variant(v);
478 self.word(",");
479 self.end(ib);
480 self.maybe_print_trailing_comment(v.span, None);
481 }
482 let empty = enum_definition.variants.is_empty();
483 self.bclose(span, empty, cb)
484 }
485
486 pub(crate) fn print_visibility(&mut self, vis: &ast::Visibility) {
487 match &vis.kind {
488 ast::VisibilityKind::Public => self.word_nbsp("pub"),
489 ast::VisibilityKind::Restricted { path, shorthand, .. } => {
490 let path = Self::to_string(|s| s.print_path(path, false, 0));
491 if *shorthand && (path == "crate" || path == "self" || path == "super") {
492 self.word_nbsp(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("pub({0})", path))
})format!("pub({path})"))
493 } else {
494 self.word_nbsp(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("pub(in {0})", path))
})format!("pub(in {path})"))
495 }
496 }
497 ast::VisibilityKind::Inherited => {}
498 }
499 }
500
501 pub(crate) fn print_impl_restriction(&mut self, impl_restriction: &ast::ImplRestriction) {
502 match &impl_restriction.kind {
503 ast::RestrictionKind::Restricted { path, shorthand, .. } => {
504 let path = Self::to_string(|s| s.print_path(path, false, 0));
505 if *shorthand {
506 self.word_nbsp(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("impl({0})", path))
})format!("impl({path})"))
507 } else {
508 self.word_nbsp(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("impl(in {0})", path))
})format!("impl(in {path})"))
509 }
510 }
511 ast::RestrictionKind::Unrestricted => {}
512 }
513 }
514
515 pub(crate) fn print_mut_restriction(&mut self, mut_restriction: &ast::MutRestriction) {
516 match &mut_restriction.kind {
517 ast::RestrictionKind::Restricted { path, shorthand, .. } => {
518 let path = Self::to_string(|s| s.print_path(path, false, 0));
519 if *shorthand {
520 self.word_nbsp(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("mut({0})", path))
})format!("mut({path})"))
521 } else {
522 self.word_nbsp(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("mut(in {0})", path))
})format!("mut(in {path})"))
523 }
524 }
525 ast::RestrictionKind::Unrestricted => {}
526 }
527 }
528
529 fn print_defaultness(&mut self, defaultness: ast::Defaultness) {
530 if let ast::Defaultness::Default(_) = defaultness {
531 self.word_nbsp("default");
532 }
533 }
534
535 fn print_struct(
536 &mut self,
537 struct_def: &ast::VariantData,
538 generics: &ast::Generics,
539 ident: Ident,
540 span: rustc_span::Span,
541 print_finalizer: bool,
542 cb: BoxMarker,
543 ib: BoxMarker,
544 ) {
545 self.print_ident(ident);
546 self.print_generic_params(&generics.params);
547 match &struct_def {
548 ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
549 if let ast::VariantData::Tuple(..) = struct_def {
550 self.popen();
551 self.commasep(Inconsistent, struct_def.fields(), |s, field| {
552 s.maybe_print_comment(field.span.lo());
553 s.print_outer_attributes(&field.attrs);
554 s.print_visibility(&field.vis);
555 s.print_mut_restriction(field.mut_restriction());
556 s.print_type(&field.ty)
557 });
558 self.pclose();
559 }
560 self.print_where_clause(&generics.where_clause);
561 if print_finalizer {
562 self.word(";");
563 }
564 self.end(ib);
565 self.end(cb);
566 }
567 ast::VariantData::Struct { fields, .. } => {
568 self.print_where_clause(&generics.where_clause);
569 self.nbsp();
570 self.bopen(ib);
571
572 let empty = fields.is_empty();
573 if !empty {
574 self.hardbreak_if_not_bol();
575
576 for field in fields {
577 self.hardbreak_if_not_bol();
578 self.maybe_print_comment(field.span.lo());
579 self.print_outer_attributes(&field.attrs);
580 self.print_visibility(&field.vis);
581 self.print_mut_restriction(field.mut_restriction());
582 self.print_ident(field.ident.unwrap());
583 self.word_nbsp(":");
584 self.print_type(&field.ty);
585 self.word(",");
586 }
587 }
588
589 self.bclose(span, empty, cb);
590 }
591 }
592 }
593
594 pub(crate) fn print_variant(&mut self, v: &ast::Variant) {
595 let (cb, ib) = self.head("");
596 self.print_visibility(&v.vis);
597 let generics = ast::Generics::default();
598 self.print_struct(&v.data, &generics, v.ident, v.span, false, cb, ib);
599 if let Some(d) = &v.disr_expr {
600 self.space();
601 self.word_space("=");
602 self.print_expr(&d.value, FixupContext::default())
603 }
604 }
605
606 pub(crate) fn print_assoc_item(&mut self, item: &ast::AssocItem) {
607 let ast::Item { id, span, ref attrs, ref kind, ref vis, tokens: _ } = *item;
608 self.ann.pre(self, AnnNode::SubItem(id));
609 self.hardbreak_if_not_bol();
610 self.maybe_print_comment(span.lo());
611 self.print_outer_attributes(attrs);
612 match kind {
613 ast::AssocItemKind::Fn(func) => {
614 self.print_fn_full(vis, attrs, &*func);
615 }
616 ast::AssocItemKind::Const(ast::ConstItem {
617 defaultness,
618 ident,
619 generics,
620 ty,
621 body,
622 kind: _,
623 define_opaque,
624 }) => {
625 self.print_item_const(
626 *ident,
627 None,
628 generics,
629 ty,
630 body.as_deref(),
631 vis,
632 ast::Safety::Default,
633 *defaultness,
634 define_opaque.as_deref(),
635 &[],
636 );
637 }
638 ast::AssocItemKind::Type(ast::TyAlias {
639 defaultness,
640 ident,
641 generics,
642 after_where_clause,
643 bounds,
644 ty,
645 }) => {
646 self.print_associated_type(
647 *ident,
648 generics,
649 after_where_clause,
650 bounds,
651 ty.as_deref(),
652 vis,
653 *defaultness,
654 );
655 }
656 ast::AssocItemKind::MacCall(m) => {
657 self.print_mac(m);
658 if m.args.need_semicolon() {
659 self.word(";");
660 }
661 }
662 ast::AssocItemKind::Delegation(deleg) => self.print_delegation(
663 &item.attrs,
664 vis,
665 &deleg.qself,
666 &deleg.path,
667 DelegationKind::Single,
668 &deleg.body,
669 ),
670 ast::AssocItemKind::DelegationMac(deleg) => self.print_delegation(
671 &item.attrs,
672 vis,
673 &deleg.qself,
674 &deleg.prefix,
675 match &deleg.suffixes {
676 ast::DelegationSuffixes::List(s) => DelegationKind::List(s),
677 ast::DelegationSuffixes::Glob(_) => DelegationKind::Glob,
678 },
679 &deleg.body,
680 ),
681 }
682 self.ann.post(self, AnnNode::SubItem(id))
683 }
684
685 fn print_delegation(
686 &mut self,
687 attrs: &[ast::Attribute],
688 vis: &ast::Visibility,
689 qself: &Option<Box<ast::QSelf>>,
690 path: &ast::Path,
691 kind: DelegationKind<'_>,
692 body: &Option<Box<ast::Block>>,
693 ) {
694 let body_cb_ib = body.as_ref().map(|body| (body, self.head("")));
695 self.print_visibility(vis);
696 self.word_nbsp("reuse");
697
698 if let Some(qself) = qself {
699 self.print_qpath(path, qself, false);
700 } else {
701 self.print_path(path, false, 0);
702 }
703 match kind {
704 DelegationKind::Single => {}
705 DelegationKind::List(suffixes) => {
706 self.word("::");
707 self.word("{");
708 for (i, (ident, rename)) in suffixes.iter().enumerate() {
709 self.print_ident(*ident);
710 if let Some(rename) = rename {
711 self.nbsp();
712 self.word_nbsp("as");
713 self.print_ident(*rename);
714 }
715 if i != suffixes.len() - 1 {
716 self.word_space(",");
717 }
718 }
719 self.word("}");
720 }
721 DelegationKind::Glob => {
722 self.word("::");
723 self.word("*");
724 }
725 }
726 if let Some((body, (cb, ib))) = body_cb_ib {
727 self.nbsp();
728 self.print_block_with_attrs(body, attrs, cb, ib);
729 } else {
730 self.word(";");
731 }
732 }
733
734 fn print_fn_full(&mut self, vis: &ast::Visibility, attrs: &[ast::Attribute], func: &ast::Fn) {
735 let ast::Fn { defaultness, ident, generics, sig, contract, body, define_opaque, eii_impls } =
736 func;
737
738 self.print_define_opaques(define_opaque.as_deref());
739
740 for eii_impl in eii_impls {
741 self.print_eii_impl(eii_impl);
742 }
743
744 let body_cb_ib = body.as_ref().map(|body| (body, self.head("")));
745
746 self.print_visibility(vis);
747 self.print_defaultness(*defaultness);
748 self.print_fn(&sig.decl, sig.header, Some(*ident), generics);
749 if let Some(contract) = &contract {
750 self.nbsp();
751 self.print_contract(contract);
752 }
753 if let Some((body, (cb, ib))) = body_cb_ib {
754 if self.is_sdylib_interface {
755 self.word(";");
756 self.end(ib); self.end(cb); return;
759 }
760
761 self.nbsp();
762 self.print_block_with_attrs(body, attrs, cb, ib);
763 } else {
764 self.word(";");
765 }
766 }
767
768 fn print_eii_impl(&mut self, eii: &ast::EiiImpl) {
769 self.word("#[");
770 if let Safety::Unsafe(..) = eii.impl_safety {
771 self.word("unsafe");
772 self.popen();
773 }
774 self.print_path(&eii.eii_macro_path, false, 0);
775 if let Safety::Unsafe(..) = eii.impl_safety {
776 self.pclose();
777 }
778 self.word("]");
779 self.hardbreak();
780 }
781
782 fn print_define_opaques(&mut self, define_opaque: Option<&[(ast::NodeId, ast::Path)]>) {
783 if let Some(define_opaque) = define_opaque {
784 self.word("#[define_opaque(");
785 for (i, (_, path)) in define_opaque.iter().enumerate() {
786 if i != 0 {
787 self.word_space(",");
788 }
789
790 self.print_path(path, false, 0);
791 }
792 self.word(")]");
793 }
794 self.hardbreak_if_not_bol();
795 }
796
797 fn print_contract(&mut self, contract: &ast::FnContract) {
798 if let Some(pred) = &contract.requires {
799 self.word("rustc_requires");
800 self.popen();
801 self.print_expr(pred, FixupContext::default());
802 self.pclose();
803 }
804 if let Some(pred) = &contract.ensures {
805 self.word("rustc_ensures");
806 self.popen();
807 self.print_expr(pred, FixupContext::default());
808 self.pclose();
809 }
810 }
811
812 pub(crate) fn print_fn(
813 &mut self,
814 decl: &ast::FnDecl,
815 header: ast::FnHeader,
816 ident: Option<Ident>,
817 generics: &ast::Generics,
818 ) {
819 self.print_fn_header_info(header);
820 if let Some(ident) = ident {
821 self.nbsp();
822 self.print_ident(ident);
823 }
824 self.print_generic_params(&generics.params);
825 self.print_fn_params_and_ret(decl, false);
826 self.print_where_clause(&generics.where_clause);
827 }
828
829 pub(crate) fn print_fn_params_and_ret(&mut self, decl: &ast::FnDecl, is_closure: bool) {
830 let (open, close) = if is_closure { ("|", "|") } else { ("(", ")") };
831 self.word(open);
832 self.commasep(Inconsistent, &decl.inputs, |s, param| s.print_param(param, is_closure));
833 self.word(close);
834 self.print_fn_ret_ty(&decl.output)
835 }
836
837 fn print_where_clause(&mut self, where_clause: &ast::WhereClause) {
838 let ast::WhereClause { has_where_token, ref predicates, span: _ } = *where_clause;
839 if predicates.is_empty() && !has_where_token {
840 return;
841 }
842
843 self.space();
844 self.word_space("where");
845
846 for (i, predicate) in predicates.iter().enumerate() {
847 if i != 0 {
848 self.word_space(",");
849 }
850
851 self.print_where_predicate(predicate);
852 }
853 }
854
855 pub fn print_where_predicate(&mut self, predicate: &ast::WherePredicate) {
856 let ast::WherePredicate { attrs, kind, id: _, span: _, is_placeholder: _ } = predicate;
857 self.print_outer_attributes(attrs);
858 match kind {
859 ast::WherePredicateKind::BoundPredicate(where_bound_predicate) => {
860 self.print_where_bound_predicate(where_bound_predicate);
861 }
862 ast::WherePredicateKind::RegionPredicate(ast::WhereRegionPredicate {
863 lifetime,
864 bounds,
865 ..
866 }) => {
867 self.print_lifetime(*lifetime);
868 self.word(":");
869 if !bounds.is_empty() {
870 self.nbsp();
871 self.print_lifetime_bounds(bounds);
872 }
873 }
874 }
875 }
876
877 pub(crate) fn print_where_bound_predicate(
878 &mut self,
879 where_bound_predicate: &ast::WhereBoundPredicate,
880 ) {
881 self.print_formal_generic_params(&where_bound_predicate.bound_generic_params);
882 self.print_type(&where_bound_predicate.bounded_ty);
883 self.word(":");
884 if !where_bound_predicate.bounds.is_empty() {
885 self.nbsp();
886 self.print_type_bounds(&where_bound_predicate.bounds);
887 }
888 }
889
890 fn print_use_tree(&mut self, tree: &ast::UseTree) {
891 match &tree.kind {
892 ast::UseTreeKind::Simple(rename) => {
893 self.print_path(&tree.prefix, false, 0);
894 if let &Some(rename) = rename {
895 self.nbsp();
896 self.word_nbsp("as");
897 self.print_ident(rename);
898 }
899 }
900 ast::UseTreeKind::Glob(_) => {
901 if !tree.prefix.segments.is_empty() {
902 self.print_path(&tree.prefix, false, 0);
903 self.word("::");
904 }
905 self.word("*");
906 }
907 ast::UseTreeKind::Nested { items, .. } => {
908 if !tree.prefix.segments.is_empty() {
909 self.print_path(&tree.prefix, false, 0);
910 self.word("::");
911 }
912 if items.is_empty() {
913 self.word("{}");
914 } else if let [(item, _)] = items.as_slice()
915 && !item
916 .prefix
917 .segments
918 .first()
919 .is_some_and(|seg| seg.ident.name == rustc_span::symbol::kw::SelfLower)
920 {
921 self.print_use_tree(item);
922 } else {
923 let cb = self.cbox(INDENT_UNIT);
924 self.word("{");
925 self.zerobreak();
926 let ib = self.ibox(0);
927 for (pos, use_tree) in items.iter().with_position() {
928 let is_last = pos.is_last();
929 self.print_use_tree(&use_tree.0);
930 if !is_last {
931 self.word(",");
932 if let ast::UseTreeKind::Nested { .. } = use_tree.0.kind {
933 self.hardbreak();
934 } else {
935 self.space();
936 }
937 }
938 }
939 self.end(ib);
940 self.trailing_comma();
941 self.offset(-INDENT_UNIT);
942 self.word("}");
943 self.end(cb);
944 }
945 }
946 }
947 }
948}