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