rustc_ast_pretty/pprust/state/
item.rs

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