]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_ast_pretty/src/pprust/state/item.rs
New upstream version 1.74.1+dfsg1
[rustc.git] / compiler / rustc_ast_pretty / src / pprust / state / item.rs
1 use crate::pp::Breaks::Inconsistent;
2 use crate::pprust::state::delimited::IterDelimited;
3 use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT};
4
5 use ast::StaticItem;
6 use rustc_ast as ast;
7 use rustc_ast::GenericBound;
8 use rustc_ast::ModKind;
9 use rustc_span::symbol::Ident;
10
11 fn visibility_qualified(vis: &ast::Visibility, s: &str) -> String {
12 format!("{}{}", State::to_string(|s| s.print_visibility(vis)), s)
13 }
14
15 impl<'a> State<'a> {
16 fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod, attrs: &[ast::Attribute]) {
17 self.print_inner_attributes(attrs);
18 for item in &nmod.items {
19 self.print_foreign_item(item);
20 }
21 }
22
23 pub(crate) fn print_foreign_item(&mut self, item: &ast::ForeignItem) {
24 let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item;
25 self.ann.pre(self, AnnNode::SubItem(id));
26 self.hardbreak_if_not_bol();
27 self.maybe_print_comment(span.lo());
28 self.print_outer_attributes(attrs);
29 match kind {
30 ast::ForeignItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
31 self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs);
32 }
33 ast::ForeignItemKind::Static(ty, mutbl, body) => self.print_item_const(
34 ident,
35 Some(*mutbl),
36 &ast::Generics::default(),
37 ty,
38 body.as_deref(),
39 vis,
40 ast::Defaultness::Final,
41 ),
42 ast::ForeignItemKind::TyAlias(box ast::TyAlias {
43 defaultness,
44 generics,
45 where_clauses,
46 where_predicates_split,
47 bounds,
48 ty,
49 }) => {
50 self.print_associated_type(
51 ident,
52 generics,
53 *where_clauses,
54 *where_predicates_split,
55 bounds,
56 ty.as_deref(),
57 vis,
58 *defaultness,
59 );
60 }
61 ast::ForeignItemKind::MacCall(m) => {
62 self.print_mac(m);
63 if m.args.need_semicolon() {
64 self.word(";");
65 }
66 }
67 }
68 self.ann.post(self, AnnNode::SubItem(id))
69 }
70
71 fn print_item_const(
72 &mut self,
73 ident: Ident,
74 mutbl: Option<ast::Mutability>,
75 generics: &ast::Generics,
76 ty: &ast::Ty,
77 body: Option<&ast::Expr>,
78 vis: &ast::Visibility,
79 defaultness: ast::Defaultness,
80 ) {
81 self.head("");
82 self.print_visibility(vis);
83 self.print_defaultness(defaultness);
84 let leading = match mutbl {
85 None => "const",
86 Some(ast::Mutability::Not) => "static",
87 Some(ast::Mutability::Mut) => "static mut",
88 };
89 self.word_space(leading);
90 self.print_ident(ident);
91 self.print_generic_params(&generics.params);
92 self.word_space(":");
93 self.print_type(ty);
94 if body.is_some() {
95 self.space();
96 }
97 self.end(); // end the head-ibox
98 if let Some(body) = body {
99 self.word_space("=");
100 self.print_expr(body);
101 }
102 self.print_where_clause(&generics.where_clause);
103 self.word(";");
104 self.end(); // end the outer cbox
105 }
106
107 fn print_associated_type(
108 &mut self,
109 ident: Ident,
110 generics: &ast::Generics,
111 where_clauses: (ast::TyAliasWhereClause, ast::TyAliasWhereClause),
112 where_predicates_split: usize,
113 bounds: &ast::GenericBounds,
114 ty: Option<&ast::Ty>,
115 vis: &ast::Visibility,
116 defaultness: ast::Defaultness,
117 ) {
118 let (before_predicates, after_predicates) =
119 generics.where_clause.predicates.split_at(where_predicates_split);
120 self.head("");
121 self.print_visibility(vis);
122 self.print_defaultness(defaultness);
123 self.word_space("type");
124 self.print_ident(ident);
125 self.print_generic_params(&generics.params);
126 if !bounds.is_empty() {
127 self.word_nbsp(":");
128 self.print_type_bounds(bounds);
129 }
130 self.print_where_clause_parts(where_clauses.0.0, before_predicates);
131 if let Some(ty) = ty {
132 self.space();
133 self.word_space("=");
134 self.print_type(ty);
135 }
136 self.print_where_clause_parts(where_clauses.1.0, after_predicates);
137 self.word(";");
138 self.end(); // end inner head-block
139 self.end(); // end outer head-block
140 }
141
142 /// Pretty-prints an item.
143 pub(crate) fn print_item(&mut self, item: &ast::Item) {
144 self.hardbreak_if_not_bol();
145 self.maybe_print_comment(item.span.lo());
146 self.print_outer_attributes(&item.attrs);
147 self.ann.pre(self, AnnNode::Item(item));
148 match &item.kind {
149 ast::ItemKind::ExternCrate(orig_name) => {
150 self.head(visibility_qualified(&item.vis, "extern crate"));
151 if let &Some(orig_name) = orig_name {
152 self.print_name(orig_name);
153 self.space();
154 self.word("as");
155 self.space();
156 }
157 self.print_ident(item.ident);
158 self.word(";");
159 self.end(); // end inner head-block
160 self.end(); // end outer head-block
161 }
162 ast::ItemKind::Use(tree) => {
163 self.print_visibility(&item.vis);
164 self.word_nbsp("use");
165 self.print_use_tree(tree);
166 self.word(";");
167 }
168 ast::ItemKind::Static(box StaticItem { ty, mutability: mutbl, expr: body }) => {
169 self.print_item_const(
170 item.ident,
171 Some(*mutbl),
172 &ast::Generics::default(),
173 ty,
174 body.as_deref(),
175 &item.vis,
176 ast::Defaultness::Final,
177 );
178 }
179 ast::ItemKind::Const(box ast::ConstItem { defaultness, generics, ty, expr }) => {
180 self.print_item_const(
181 item.ident,
182 None,
183 generics,
184 ty,
185 expr.as_deref(),
186 &item.vis,
187 *defaultness,
188 );
189 }
190 ast::ItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
191 self.print_fn_full(
192 sig,
193 item.ident,
194 generics,
195 &item.vis,
196 *defaultness,
197 body.as_deref(),
198 &item.attrs,
199 );
200 }
201 ast::ItemKind::Mod(unsafety, mod_kind) => {
202 self.head(Self::to_string(|s| {
203 s.print_visibility(&item.vis);
204 s.print_unsafety(*unsafety);
205 s.word("mod");
206 }));
207 self.print_ident(item.ident);
208
209 match mod_kind {
210 ModKind::Loaded(items, ..) => {
211 self.nbsp();
212 self.bopen();
213 self.print_inner_attributes(&item.attrs);
214 for item in items {
215 self.print_item(item);
216 }
217 let empty = item.attrs.is_empty() && items.is_empty();
218 self.bclose(item.span, empty);
219 }
220 ModKind::Unloaded => {
221 self.word(";");
222 self.end(); // end inner head-block
223 self.end(); // end outer head-block
224 }
225 }
226 }
227 ast::ItemKind::ForeignMod(nmod) => {
228 self.head(Self::to_string(|s| {
229 s.print_unsafety(nmod.unsafety);
230 s.word("extern");
231 }));
232 if let Some(abi) = nmod.abi {
233 self.print_token_literal(abi.as_token_lit(), abi.span);
234 self.nbsp();
235 }
236 self.bopen();
237 self.print_foreign_mod(nmod, &item.attrs);
238 let empty = item.attrs.is_empty() && nmod.items.is_empty();
239 self.bclose(item.span, empty);
240 }
241 ast::ItemKind::GlobalAsm(asm) => {
242 self.head(visibility_qualified(&item.vis, "global_asm!"));
243 self.print_inline_asm(asm);
244 self.word(";");
245 self.end();
246 self.end();
247 }
248 ast::ItemKind::TyAlias(box ast::TyAlias {
249 defaultness,
250 generics,
251 where_clauses,
252 where_predicates_split,
253 bounds,
254 ty,
255 }) => {
256 self.print_associated_type(
257 item.ident,
258 generics,
259 *where_clauses,
260 *where_predicates_split,
261 bounds,
262 ty.as_deref(),
263 &item.vis,
264 *defaultness,
265 );
266 }
267 ast::ItemKind::Enum(enum_definition, params) => {
268 self.print_enum_def(enum_definition, params, item.ident, item.span, &item.vis);
269 }
270 ast::ItemKind::Struct(struct_def, generics) => {
271 self.head(visibility_qualified(&item.vis, "struct"));
272 self.print_struct(struct_def, generics, item.ident, item.span, true);
273 }
274 ast::ItemKind::Union(struct_def, generics) => {
275 self.head(visibility_qualified(&item.vis, "union"));
276 self.print_struct(struct_def, generics, item.ident, item.span, true);
277 }
278 ast::ItemKind::Impl(box ast::Impl {
279 unsafety,
280 polarity,
281 defaultness,
282 constness,
283 generics,
284 of_trait,
285 self_ty,
286 items,
287 }) => {
288 self.head("");
289 self.print_visibility(&item.vis);
290 self.print_defaultness(*defaultness);
291 self.print_unsafety(*unsafety);
292 self.word("impl");
293
294 if generics.params.is_empty() {
295 self.nbsp();
296 } else {
297 self.print_generic_params(&generics.params);
298 self.space();
299 }
300
301 self.print_constness(*constness);
302
303 if let ast::ImplPolarity::Negative(_) = polarity {
304 self.word("!");
305 }
306
307 if let Some(t) = of_trait {
308 self.print_trait_ref(t);
309 self.space();
310 self.word_space("for");
311 }
312
313 self.print_type(self_ty);
314 self.print_where_clause(&generics.where_clause);
315
316 self.space();
317 self.bopen();
318 self.print_inner_attributes(&item.attrs);
319 for impl_item in items {
320 self.print_assoc_item(impl_item);
321 }
322 let empty = item.attrs.is_empty() && items.is_empty();
323 self.bclose(item.span, empty);
324 }
325 ast::ItemKind::Trait(box ast::Trait {
326 is_auto,
327 unsafety,
328 generics,
329 bounds,
330 items,
331 ..
332 }) => {
333 self.head("");
334 self.print_visibility(&item.vis);
335 self.print_unsafety(*unsafety);
336 self.print_is_auto(*is_auto);
337 self.word_nbsp("trait");
338 self.print_ident(item.ident);
339 self.print_generic_params(&generics.params);
340 let mut real_bounds = Vec::with_capacity(bounds.len());
341 for b in bounds.iter() {
342 if let GenericBound::Trait(ptr, ast::TraitBoundModifier::Maybe) = b {
343 self.space();
344 self.word_space("for ?");
345 self.print_trait_ref(&ptr.trait_ref);
346 } else {
347 real_bounds.push(b.clone());
348 }
349 }
350 if !real_bounds.is_empty() {
351 self.word_nbsp(":");
352 self.print_type_bounds(&real_bounds);
353 }
354 self.print_where_clause(&generics.where_clause);
355 self.word(" ");
356 self.bopen();
357 self.print_inner_attributes(&item.attrs);
358 for trait_item in items {
359 self.print_assoc_item(trait_item);
360 }
361 let empty = item.attrs.is_empty() && items.is_empty();
362 self.bclose(item.span, empty);
363 }
364 ast::ItemKind::TraitAlias(generics, bounds) => {
365 self.head(visibility_qualified(&item.vis, "trait"));
366 self.print_ident(item.ident);
367 self.print_generic_params(&generics.params);
368 self.nbsp();
369 if !bounds.is_empty() {
370 self.word_nbsp("=");
371 self.print_type_bounds(&bounds);
372 }
373 self.print_where_clause(&generics.where_clause);
374 self.word(";");
375 self.end(); // end inner head-block
376 self.end(); // end outer head-block
377 }
378 ast::ItemKind::MacCall(mac) => {
379 self.print_mac(mac);
380 if mac.args.need_semicolon() {
381 self.word(";");
382 }
383 }
384 ast::ItemKind::MacroDef(macro_def) => {
385 self.print_mac_def(macro_def, &item.ident, item.span, |state| {
386 state.print_visibility(&item.vis)
387 });
388 }
389 }
390 self.ann.post(self, AnnNode::Item(item))
391 }
392
393 fn print_enum_def(
394 &mut self,
395 enum_definition: &ast::EnumDef,
396 generics: &ast::Generics,
397 ident: Ident,
398 span: rustc_span::Span,
399 visibility: &ast::Visibility,
400 ) {
401 self.head(visibility_qualified(visibility, "enum"));
402 self.print_ident(ident);
403 self.print_generic_params(&generics.params);
404 self.print_where_clause(&generics.where_clause);
405 self.space();
406 self.print_variants(&enum_definition.variants, span)
407 }
408
409 fn print_variants(&mut self, variants: &[ast::Variant], span: rustc_span::Span) {
410 self.bopen();
411 for v in variants {
412 self.space_if_not_bol();
413 self.maybe_print_comment(v.span.lo());
414 self.print_outer_attributes(&v.attrs);
415 self.ibox(0);
416 self.print_variant(v);
417 self.word(",");
418 self.end();
419 self.maybe_print_trailing_comment(v.span, None);
420 }
421 let empty = variants.is_empty();
422 self.bclose(span, empty)
423 }
424
425 pub(crate) fn print_visibility(&mut self, vis: &ast::Visibility) {
426 match &vis.kind {
427 ast::VisibilityKind::Public => self.word_nbsp("pub"),
428 ast::VisibilityKind::Restricted { path, shorthand, .. } => {
429 let path = Self::to_string(|s| s.print_path(path, false, 0));
430 if *shorthand && (path == "crate" || path == "self" || path == "super") {
431 self.word_nbsp(format!("pub({path})"))
432 } else {
433 self.word_nbsp(format!("pub(in {path})"))
434 }
435 }
436 ast::VisibilityKind::Inherited => {}
437 }
438 }
439
440 fn print_defaultness(&mut self, defaultness: ast::Defaultness) {
441 if let ast::Defaultness::Default(_) = defaultness {
442 self.word_nbsp("default");
443 }
444 }
445
446 pub(crate) fn print_record_struct_body(
447 &mut self,
448 fields: &[ast::FieldDef],
449 span: rustc_span::Span,
450 ) {
451 self.nbsp();
452 self.bopen();
453
454 let empty = fields.is_empty();
455 if !empty {
456 self.hardbreak_if_not_bol();
457
458 for field in fields {
459 self.hardbreak_if_not_bol();
460 self.maybe_print_comment(field.span.lo());
461 self.print_outer_attributes(&field.attrs);
462 self.print_visibility(&field.vis);
463 self.print_ident(field.ident.unwrap());
464 self.word_nbsp(":");
465 self.print_type(&field.ty);
466 self.word(",");
467 }
468 }
469
470 self.bclose(span, empty);
471 }
472
473 fn print_struct(
474 &mut self,
475 struct_def: &ast::VariantData,
476 generics: &ast::Generics,
477 ident: Ident,
478 span: rustc_span::Span,
479 print_finalizer: bool,
480 ) {
481 self.print_ident(ident);
482 self.print_generic_params(&generics.params);
483 match &struct_def {
484 ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
485 if let ast::VariantData::Tuple(..) = struct_def {
486 self.popen();
487 self.commasep(Inconsistent, struct_def.fields(), |s, field| {
488 s.maybe_print_comment(field.span.lo());
489 s.print_outer_attributes(&field.attrs);
490 s.print_visibility(&field.vis);
491 s.print_type(&field.ty)
492 });
493 self.pclose();
494 }
495 self.print_where_clause(&generics.where_clause);
496 if print_finalizer {
497 self.word(";");
498 }
499 self.end();
500 self.end(); // Close the outer-box.
501 }
502 ast::VariantData::Struct(fields, ..) => {
503 self.print_where_clause(&generics.where_clause);
504 self.print_record_struct_body(fields, span);
505 }
506 }
507 }
508
509 pub(crate) fn print_variant(&mut self, v: &ast::Variant) {
510 self.head("");
511 self.print_visibility(&v.vis);
512 let generics = ast::Generics::default();
513 self.print_struct(&v.data, &generics, v.ident, v.span, false);
514 if let Some(d) = &v.disr_expr {
515 self.space();
516 self.word_space("=");
517 self.print_expr(&d.value)
518 }
519 }
520
521 pub(crate) fn print_assoc_item(&mut self, item: &ast::AssocItem) {
522 let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item;
523 self.ann.pre(self, AnnNode::SubItem(id));
524 self.hardbreak_if_not_bol();
525 self.maybe_print_comment(span.lo());
526 self.print_outer_attributes(attrs);
527 match kind {
528 ast::AssocItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
529 self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs);
530 }
531 ast::AssocItemKind::Const(box ast::ConstItem { defaultness, generics, ty, expr }) => {
532 self.print_item_const(
533 ident,
534 None,
535 generics,
536 ty,
537 expr.as_deref(),
538 vis,
539 *defaultness,
540 );
541 }
542 ast::AssocItemKind::Type(box ast::TyAlias {
543 defaultness,
544 generics,
545 where_clauses,
546 where_predicates_split,
547 bounds,
548 ty,
549 }) => {
550 self.print_associated_type(
551 ident,
552 generics,
553 *where_clauses,
554 *where_predicates_split,
555 bounds,
556 ty.as_deref(),
557 vis,
558 *defaultness,
559 );
560 }
561 ast::AssocItemKind::MacCall(m) => {
562 self.print_mac(m);
563 if m.args.need_semicolon() {
564 self.word(";");
565 }
566 }
567 }
568 self.ann.post(self, AnnNode::SubItem(id))
569 }
570
571 fn print_fn_full(
572 &mut self,
573 sig: &ast::FnSig,
574 name: Ident,
575 generics: &ast::Generics,
576 vis: &ast::Visibility,
577 defaultness: ast::Defaultness,
578 body: Option<&ast::Block>,
579 attrs: &[ast::Attribute],
580 ) {
581 if body.is_some() {
582 self.head("");
583 }
584 self.print_visibility(vis);
585 self.print_defaultness(defaultness);
586 self.print_fn(&sig.decl, sig.header, Some(name), generics);
587 if let Some(body) = body {
588 self.nbsp();
589 self.print_block_with_attrs(body, attrs);
590 } else {
591 self.word(";");
592 }
593 }
594
595 pub(crate) fn print_fn(
596 &mut self,
597 decl: &ast::FnDecl,
598 header: ast::FnHeader,
599 name: Option<Ident>,
600 generics: &ast::Generics,
601 ) {
602 self.print_fn_header_info(header);
603 if let Some(name) = name {
604 self.nbsp();
605 self.print_ident(name);
606 }
607 self.print_generic_params(&generics.params);
608 self.print_fn_params_and_ret(decl, false);
609 self.print_where_clause(&generics.where_clause)
610 }
611
612 pub(crate) fn print_fn_params_and_ret(&mut self, decl: &ast::FnDecl, is_closure: bool) {
613 let (open, close) = if is_closure { ("|", "|") } else { ("(", ")") };
614 self.word(open);
615 self.commasep(Inconsistent, &decl.inputs, |s, param| s.print_param(param, is_closure));
616 self.word(close);
617 self.print_fn_ret_ty(&decl.output)
618 }
619
620 fn print_where_clause(&mut self, where_clause: &ast::WhereClause) {
621 self.print_where_clause_parts(where_clause.has_where_token, &where_clause.predicates);
622 }
623
624 pub(crate) fn print_where_clause_parts(
625 &mut self,
626 has_where_token: bool,
627 predicates: &[ast::WherePredicate],
628 ) {
629 if predicates.is_empty() && !has_where_token {
630 return;
631 }
632
633 self.space();
634 self.word_space("where");
635
636 for (i, predicate) in predicates.iter().enumerate() {
637 if i != 0 {
638 self.word_space(",");
639 }
640
641 self.print_where_predicate(predicate);
642 }
643 }
644
645 pub fn print_where_predicate(&mut self, predicate: &ast::WherePredicate) {
646 match predicate {
647 ast::WherePredicate::BoundPredicate(where_bound_predicate) => {
648 self.print_where_bound_predicate(where_bound_predicate);
649 }
650 ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
651 lifetime,
652 bounds,
653 ..
654 }) => {
655 self.print_lifetime(*lifetime);
656 self.word(":");
657 if !bounds.is_empty() {
658 self.nbsp();
659 self.print_lifetime_bounds(bounds);
660 }
661 }
662 ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { lhs_ty, rhs_ty, .. }) => {
663 self.print_type(lhs_ty);
664 self.space();
665 self.word_space("=");
666 self.print_type(rhs_ty);
667 }
668 }
669 }
670
671 pub fn print_where_bound_predicate(
672 &mut self,
673 where_bound_predicate: &ast::WhereBoundPredicate,
674 ) {
675 self.print_formal_generic_params(&where_bound_predicate.bound_generic_params);
676 self.print_type(&where_bound_predicate.bounded_ty);
677 self.word(":");
678 if !where_bound_predicate.bounds.is_empty() {
679 self.nbsp();
680 self.print_type_bounds(&where_bound_predicate.bounds);
681 }
682 }
683
684 fn print_use_tree(&mut self, tree: &ast::UseTree) {
685 match &tree.kind {
686 ast::UseTreeKind::Simple(rename) => {
687 self.print_path(&tree.prefix, false, 0);
688 if let &Some(rename) = rename {
689 self.nbsp();
690 self.word_nbsp("as");
691 self.print_ident(rename);
692 }
693 }
694 ast::UseTreeKind::Glob => {
695 if !tree.prefix.segments.is_empty() {
696 self.print_path(&tree.prefix, false, 0);
697 self.word("::");
698 }
699 self.word("*");
700 }
701 ast::UseTreeKind::Nested(items) => {
702 if !tree.prefix.segments.is_empty() {
703 self.print_path(&tree.prefix, false, 0);
704 self.word("::");
705 }
706 if items.is_empty() {
707 self.word("{}");
708 } else if items.len() == 1 {
709 self.print_use_tree(&items[0].0);
710 } else {
711 self.cbox(INDENT_UNIT);
712 self.word("{");
713 self.zerobreak();
714 self.ibox(0);
715 for use_tree in items.iter().delimited() {
716 self.print_use_tree(&use_tree.0);
717 if !use_tree.is_last {
718 self.word(",");
719 if let ast::UseTreeKind::Nested(_) = use_tree.0.kind {
720 self.hardbreak();
721 } else {
722 self.space();
723 }
724 }
725 }
726 self.end();
727 self.trailing_comma();
728 self.offset(-INDENT_UNIT);
729 self.word("}");
730 self.end();
731 }
732 }
733 }
734 }
735 }