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