1 //! HIR pretty-printing is layered on top of AST pretty-printing. A number of
2 //! the definitions in this file have equivalents in `rustc_ast_pretty`.
4 #![recursion_limit = "256"]
5 #![deny(rustc::untranslatable_diagnostic)]
6 #![deny(rustc::diagnostic_outside_of_impl)]
9 use rustc_ast
::util
::parser
::{self, AssocOp, Fixity}
;
10 use rustc_ast_pretty
::pp
::Breaks
::{Consistent, Inconsistent}
;
11 use rustc_ast_pretty
::pp
::{self, Breaks}
;
12 use rustc_ast_pretty
::pprust
::{Comments, PrintState}
;
14 use rustc_hir
::LifetimeParamKind
;
15 use rustc_hir
::{BindingAnnotation, ByRef, GenericArg, GenericParam, GenericParamKind, Node, Term}
;
16 use rustc_hir
::{GenericBound, PatKind, RangeEnd, TraitBoundModifier}
;
17 use rustc_span
::source_map
::SourceMap
;
18 use rustc_span
::symbol
::{kw, Ident, Symbol}
;
19 use rustc_span
::FileName
;
20 use rustc_target
::spec
::abi
::Abi
;
25 pub fn id_to_string(map
: &dyn rustc_hir
::intravisit
::Map
<'_
>, hir_id
: hir
::HirId
) -> String
{
26 to_string(&map
, |s
| s
.print_node(map
.find(hir_id
).unwrap()))
29 pub enum AnnNode
<'a
> {
31 Block(&'a hir
::Block
<'a
>),
32 Item(&'a hir
::Item
<'a
>),
34 Expr(&'a hir
::Expr
<'a
>),
35 Pat(&'a hir
::Pat
<'a
>),
36 Arm(&'a hir
::Arm
<'a
>),
41 TraitItem(hir
::TraitItemId
),
42 ImplItem(hir
::ImplItemId
),
43 ForeignItem(hir
::ForeignItemId
),
45 BodyParamPat(hir
::BodyId
, usize),
49 fn nested(&self, _state
: &mut State
<'_
>, _nested
: Nested
) {}
50 fn pre(&self, _state
: &mut State
<'_
>, _node
: AnnNode
<'_
>) {}
51 fn post(&self, _state
: &mut State
<'_
>, _node
: AnnNode
<'_
>) {}
56 impl PpAnn
for NoAnn {}
58 impl PpAnn
for &dyn rustc_hir
::intravisit
::Map
<'_
> {
59 fn nested(&self, state
: &mut State
<'_
>, nested
: Nested
) {
61 Nested
::Item(id
) => state
.print_item(self.item(id
)),
62 Nested
::TraitItem(id
) => state
.print_trait_item(self.trait_item(id
)),
63 Nested
::ImplItem(id
) => state
.print_impl_item(self.impl_item(id
)),
64 Nested
::ForeignItem(id
) => state
.print_foreign_item(self.foreign_item(id
)),
65 Nested
::Body(id
) => state
.print_expr(self.body(id
).value
),
66 Nested
::BodyParamPat(id
, i
) => state
.print_pat(self.body(id
).params
[i
].pat
),
71 pub struct State
<'a
> {
73 comments
: Option
<Comments
<'a
>>,
74 attrs
: &'a
dyn Fn(hir
::HirId
) -> &'a
[ast
::Attribute
],
75 ann
: &'
a (dyn PpAnn
+ 'a
),
79 fn attrs(&self, id
: hir
::HirId
) -> &'a
[ast
::Attribute
] {
83 fn print_node(&mut self, node
: Node
<'_
>) {
85 Node
::Param(a
) => self.print_param(a
),
86 Node
::Item(a
) => self.print_item(a
),
87 Node
::ForeignItem(a
) => self.print_foreign_item(a
),
88 Node
::TraitItem(a
) => self.print_trait_item(a
),
89 Node
::ImplItem(a
) => self.print_impl_item(a
),
90 Node
::Variant(a
) => self.print_variant(a
),
91 Node
::AnonConst(a
) => self.print_anon_const(a
),
92 Node
::ConstBlock(a
) => self.print_inline_const(a
),
93 Node
::Expr(a
) => self.print_expr(a
),
94 Node
::ExprField(a
) => self.print_expr_field(a
),
95 Node
::Stmt(a
) => self.print_stmt(a
),
96 Node
::PathSegment(a
) => self.print_path_segment(a
),
97 Node
::Ty(a
) => self.print_type(a
),
98 Node
::TypeBinding(a
) => self.print_type_binding(a
),
99 Node
::TraitRef(a
) => self.print_trait_ref(a
),
100 Node
::Pat(a
) => self.print_pat(a
),
101 Node
::PatField(a
) => self.print_patfield(a
),
102 Node
::Arm(a
) => self.print_arm(a
),
103 Node
::Infer(_
) => self.word("_"),
105 // Containing cbox, will be closed by print-block at `}`.
106 self.cbox(INDENT_UNIT
);
107 // Head-ibox, will be closed by print-block after `{`.
111 Node
::Lifetime(a
) => self.print_lifetime(a
),
112 Node
::GenericParam(_
) => panic
!("cannot print Node::GenericParam"),
113 Node
::Field(_
) => panic
!("cannot print Node::Field"),
114 // These cases do not carry enough information in the
115 // `hir_map` to reconstruct their full structure for pretty
117 Node
::Ctor(..) => panic
!("cannot print isolated Ctor"),
118 Node
::Local(a
) => self.print_local_decl(a
),
119 Node
::Crate(..) => panic
!("cannot print Crate"),
124 impl std
::ops
::Deref
for State
<'_
> {
125 type Target
= pp
::Printer
;
126 fn deref(&self) -> &Self::Target
{
131 impl std
::ops
::DerefMut
for State
<'_
> {
132 fn deref_mut(&mut self) -> &mut Self::Target
{
137 impl<'a
> PrintState
<'a
> for State
<'a
> {
138 fn comments(&mut self) -> &mut Option
<Comments
<'a
>> {
142 fn ann_post(&mut self, ident
: Ident
) {
143 self.ann
.post(self, AnnNode
::Name(&ident
.name
));
146 fn print_generic_args(&mut self, _
: &ast
::GenericArgs
, _colons_before_params
: bool
) {
147 panic
!("AST generic args printed by HIR pretty-printer");
151 const INDENT_UNIT
: isize = 4;
153 /// Requires you to pass an input filename and reader so that
154 /// it can scan the input text for comments to copy forward.
155 pub fn print_crate
<'a
>(
157 krate
: &hir
::Mod
<'_
>,
160 attrs
: &'a
dyn Fn(hir
::HirId
) -> &'a
[ast
::Attribute
],
164 s
: pp
::Printer
::new(),
165 comments
: Some(Comments
::new(sm
, filename
, input
)),
170 // When printing the AST, we sometimes need to inject `#[no_std]` here.
171 // Since you can't compile the HIR, it's not necessary.
173 s
.print_mod(krate
, (*attrs
)(hir
::CRATE_HIR_ID
));
174 s
.print_remaining_comments();
178 fn to_string
<F
>(ann
: &dyn PpAnn
, f
: F
) -> String
180 F
: FnOnce(&mut State
<'_
>),
182 let mut printer
= State { s: pp::Printer::new(), comments: None, attrs: &|_| &[], ann }
;
187 pub fn ty_to_string(ty
: &hir
::Ty
<'_
>) -> String
{
188 to_string(&NoAnn
, |s
| s
.print_type(ty
))
191 pub fn qpath_to_string(segment
: &hir
::QPath
<'_
>) -> String
{
192 to_string(&NoAnn
, |s
| s
.print_qpath(segment
, false))
195 pub fn pat_to_string(pat
: &hir
::Pat
<'_
>) -> String
{
196 to_string(&NoAnn
, |s
| s
.print_pat(pat
))
200 fn bclose_maybe_open(&mut self, span
: rustc_span
::Span
, close_box
: bool
) {
201 self.maybe_print_comment(span
.hi());
202 self.break_offset_if_not_bol(1, -INDENT_UNIT
);
205 self.end(); // close the outer-box
209 fn bclose(&mut self, span
: rustc_span
::Span
) {
210 self.bclose_maybe_open(span
, true)
213 fn commasep_cmnt
<T
, F
, G
>(&mut self, b
: Breaks
, elts
: &[T
], mut op
: F
, mut get_span
: G
)
215 F
: FnMut(&mut State
<'_
>, &T
),
216 G
: FnMut(&T
) -> rustc_span
::Span
,
219 let len
= elts
.len();
222 self.maybe_print_comment(get_span(elt
).hi());
227 self.maybe_print_trailing_comment(get_span(elt
), Some(get_span(&elts
[i
]).hi()));
228 self.space_if_not_bol();
234 fn commasep_exprs(&mut self, b
: Breaks
, exprs
: &[hir
::Expr
<'_
>]) {
235 self.commasep_cmnt(b
, exprs
, |s
, e
| s
.print_expr(e
), |e
| e
.span
);
238 fn print_mod(&mut self, _mod
: &hir
::Mod
<'_
>, attrs
: &[ast
::Attribute
]) {
239 self.print_inner_attributes(attrs
);
240 for &item_id
in _mod
.item_ids
{
241 self.ann
.nested(self, Nested
::Item(item_id
));
245 fn print_opt_lifetime(&mut self, lifetime
: &hir
::Lifetime
) {
246 if !lifetime
.is_elided() {
247 self.print_lifetime(lifetime
);
252 fn print_type(&mut self, ty
: &hir
::Ty
<'_
>) {
253 self.maybe_print_comment(ty
.span
.lo());
256 hir
::TyKind
::Slice(ty
) => {
261 hir
::TyKind
::Ptr(ref mt
) => {
263 self.print_mt(mt
, true);
265 hir
::TyKind
::Ref(lifetime
, ref mt
) => {
267 self.print_opt_lifetime(lifetime
);
268 self.print_mt(mt
, false);
270 hir
::TyKind
::Never
=> {
273 hir
::TyKind
::Tup(elts
) => {
275 self.commasep(Inconsistent
, elts
, |s
, ty
| s
.print_type(ty
));
281 hir
::TyKind
::BareFn(f
) => {
282 self.print_ty_fn(f
.abi
, f
.unsafety
, f
.decl
, None
, f
.generic_params
, f
.param_names
);
284 hir
::TyKind
::OpaqueDef(..) => self.word("/*impl Trait*/"),
285 hir
::TyKind
::Path(ref qpath
) => self.print_qpath(qpath
, false),
286 hir
::TyKind
::TraitObject(bounds
, lifetime
, syntax
) => {
287 if syntax
== ast
::TraitObjectSyntax
::Dyn
{
288 self.word_space("dyn");
290 let mut first
= true;
291 for bound
in bounds
{
296 self.word_space("+");
298 self.print_poly_trait_ref(bound
);
300 if !lifetime
.is_elided() {
302 self.word_space("+");
303 self.print_lifetime(lifetime
);
306 hir
::TyKind
::Array(ty
, ref length
) => {
310 self.print_array_length(length
);
313 hir
::TyKind
::Typeof(ref e
) => {
314 self.word("typeof(");
315 self.print_anon_const(e
);
318 hir
::TyKind
::Err(_
) => {
320 self.word("/*ERROR*/");
323 hir
::TyKind
::Infer
=> {
330 fn print_foreign_item(&mut self, item
: &hir
::ForeignItem
<'_
>) {
331 self.hardbreak_if_not_bol();
332 self.maybe_print_comment(item
.span
.lo());
333 self.print_outer_attributes(self.attrs(item
.hir_id()));
335 hir
::ForeignItemKind
::Fn(decl
, arg_names
, generics
) => {
340 unsafety
: hir
::Unsafety
::Normal
,
341 constness
: hir
::Constness
::NotConst
,
343 asyncness
: hir
::IsAsync
::NotAsync
,
345 Some(item
.ident
.name
),
350 self.end(); // end head-ibox
352 self.end() // end the outer fn box
354 hir
::ForeignItemKind
::Static(t
, m
) => {
357 self.word_space("mut");
359 self.print_ident(item
.ident
);
360 self.word_space(":");
363 self.end(); // end the head-ibox
364 self.end() // end the outer cbox
366 hir
::ForeignItemKind
::Type
=> {
368 self.print_ident(item
.ident
);
370 self.end(); // end the head-ibox
371 self.end() // end the outer cbox
376 fn print_associated_const(
379 generics
: &hir
::Generics
<'_
>,
381 default: Option
<hir
::BodyId
>,
383 self.word_space("const");
384 self.print_ident(ident
);
385 self.print_generic_params(generics
.params
);
386 self.word_space(":");
388 if let Some(expr
) = default {
390 self.word_space("=");
391 self.ann
.nested(self, Nested
::Body(expr
));
393 self.print_where_clause(generics
);
397 fn print_associated_type(
400 generics
: &hir
::Generics
<'_
>,
401 bounds
: Option
<hir
::GenericBounds
<'_
>>,
402 ty
: Option
<&hir
::Ty
<'_
>>,
404 self.word_space("type");
405 self.print_ident(ident
);
406 self.print_generic_params(generics
.params
);
407 if let Some(bounds
) = bounds
{
408 self.print_bounds(":", bounds
);
410 self.print_where_clause(generics
);
411 if let Some(ty
) = ty
{
413 self.word_space("=");
421 item
: &hir
::Item
<'_
>,
422 generics
: &hir
::Generics
<'_
>,
423 inner
: impl Fn(&mut Self),
426 self.print_ident(item
.ident
);
427 self.print_generic_params(generics
.params
);
428 self.end(); // end the inner ibox
430 self.print_where_clause(generics
);
434 self.end(); // end the outer ibox
437 fn print_item(&mut self, item
: &hir
::Item
<'_
>) {
438 self.hardbreak_if_not_bol();
439 self.maybe_print_comment(item
.span
.lo());
440 let attrs
= self.attrs(item
.hir_id());
441 self.print_outer_attributes(attrs
);
442 self.ann
.pre(self, AnnNode
::Item(item
));
444 hir
::ItemKind
::ExternCrate(orig_name
) => {
445 self.head("extern crate");
446 if let Some(orig_name
) = orig_name
{
447 self.print_name(orig_name
);
452 self.print_ident(item
.ident
);
454 self.end(); // end inner head-block
455 self.end(); // end outer head-block
457 hir
::ItemKind
::Use(path
, kind
) => {
459 self.print_path(path
, false);
462 hir
::UseKind
::Single
=> {
463 if path
.segments
.last().unwrap().ident
!= item
.ident
{
465 self.word_space("as");
466 self.print_ident(item
.ident
);
470 hir
::UseKind
::Glob
=> self.word("::*;"),
471 hir
::UseKind
::ListStem
=> self.word("::{};"),
473 self.end(); // end inner head-block
474 self.end(); // end outer head-block
476 hir
::ItemKind
::Static(ty
, m
, expr
) => {
479 self.word_space("mut");
481 self.print_ident(item
.ident
);
482 self.word_space(":");
485 self.end(); // end the head-ibox
487 self.word_space("=");
488 self.ann
.nested(self, Nested
::Body(expr
));
490 self.end(); // end the outer cbox
492 hir
::ItemKind
::Const(ty
, generics
, expr
) => {
494 self.print_ident(item
.ident
);
495 self.print_generic_params(generics
.params
);
496 self.word_space(":");
499 self.end(); // end the head-ibox
501 self.word_space("=");
502 self.ann
.nested(self, Nested
::Body(expr
));
503 self.print_where_clause(generics
);
505 self.end(); // end the outer cbox
507 hir
::ItemKind
::Fn(ref sig
, generics
, body
) => {
512 Some(item
.ident
.name
),
518 self.end(); // need to close a box
519 self.end(); // need to close a box
520 self.ann
.nested(self, Nested
::Body(body
));
522 hir
::ItemKind
::Macro(macro_def
, _
) => {
523 self.print_mac_def(macro_def
, &item
.ident
, item
.span
, |_
| {}
);
525 hir
::ItemKind
::Mod(_mod
) => {
527 self.print_ident(item
.ident
);
530 self.print_mod(_mod
, attrs
);
531 self.bclose(item
.span
);
533 hir
::ItemKind
::ForeignMod { abi, items }
=> {
535 self.word_nbsp(abi
.to_string());
537 self.print_inner_attributes(self.attrs(item
.hir_id()));
539 self.ann
.nested(self, Nested
::ForeignItem(item
.id
));
541 self.bclose(item
.span
);
543 hir
::ItemKind
::GlobalAsm(asm
) => {
544 self.head("global_asm!");
545 self.print_inline_asm(asm
);
548 hir
::ItemKind
::TyAlias(ty
, generics
) => {
549 self.print_item_type(item
, generics
, |state
| {
550 state
.word_space("=");
551 state
.print_type(ty
);
554 hir
::ItemKind
::OpaqueTy(opaque_ty
) => {
555 self.print_item_type(item
, opaque_ty
.generics
, |state
| {
556 let mut real_bounds
= Vec
::with_capacity(opaque_ty
.bounds
.len());
557 for b
in opaque_ty
.bounds
{
558 if let GenericBound
::Trait(ptr
, hir
::TraitBoundModifier
::Maybe
) = b
{
560 state
.word_space("for ?");
561 state
.print_trait_ref(&ptr
.trait_ref
);
566 state
.print_bounds("= impl", real_bounds
);
569 hir
::ItemKind
::Enum(ref enum_definition
, params
) => {
570 self.print_enum_def(enum_definition
, params
, item
.ident
.name
, item
.span
);
572 hir
::ItemKind
::Struct(ref struct_def
, generics
) => {
574 self.print_struct(struct_def
, generics
, item
.ident
.name
, item
.span
, true);
576 hir
::ItemKind
::Union(ref struct_def
, generics
) => {
578 self.print_struct(struct_def
, generics
, item
.ident
.name
, item
.span
, true);
580 hir
::ItemKind
::Impl(&hir
::Impl
{
591 self.print_defaultness(defaultness
);
592 self.print_unsafety(unsafety
);
593 self.word_nbsp("impl");
595 if !generics
.params
.is_empty() {
596 self.print_generic_params(generics
.params
);
600 if let hir
::ImplPolarity
::Negative(_
) = polarity
{
604 if let Some(t
) = of_trait
{
605 self.print_trait_ref(t
);
607 self.word_space("for");
610 self.print_type(self_ty
);
611 self.print_where_clause(generics
);
615 self.print_inner_attributes(attrs
);
616 for impl_item
in items
{
617 self.ann
.nested(self, Nested
::ImplItem(impl_item
.id
));
619 self.bclose(item
.span
);
621 hir
::ItemKind
::Trait(is_auto
, unsafety
, generics
, bounds
, trait_items
) => {
623 self.print_is_auto(is_auto
);
624 self.print_unsafety(unsafety
);
625 self.word_nbsp("trait");
626 self.print_ident(item
.ident
);
627 self.print_generic_params(generics
.params
);
628 let mut real_bounds
= Vec
::with_capacity(bounds
.len());
630 if let GenericBound
::Trait(ptr
, hir
::TraitBoundModifier
::Maybe
) = b
{
632 self.word_space("for ?");
633 self.print_trait_ref(&ptr
.trait_ref
);
638 self.print_bounds(":", real_bounds
);
639 self.print_where_clause(generics
);
642 for trait_item
in trait_items
{
643 self.ann
.nested(self, Nested
::TraitItem(trait_item
.id
));
645 self.bclose(item
.span
);
647 hir
::ItemKind
::TraitAlias(generics
, bounds
) => {
649 self.print_ident(item
.ident
);
650 self.print_generic_params(generics
.params
);
652 self.print_bounds("=", bounds
);
653 self.print_where_clause(generics
);
655 self.end(); // end inner head-block
656 self.end(); // end outer head-block
659 self.ann
.post(self, AnnNode
::Item(item
))
662 fn print_trait_ref(&mut self, t
: &hir
::TraitRef
<'_
>) {
663 self.print_path(t
.path
, false);
666 fn print_formal_generic_params(&mut self, generic_params
: &[hir
::GenericParam
<'_
>]) {
667 if !generic_params
.is_empty() {
669 self.print_generic_params(generic_params
);
674 fn print_poly_trait_ref(&mut self, t
: &hir
::PolyTraitRef
<'_
>) {
675 self.print_formal_generic_params(t
.bound_generic_params
);
676 self.print_trait_ref(&t
.trait_ref
);
681 enum_definition
: &hir
::EnumDef
<'_
>,
682 generics
: &hir
::Generics
<'_
>,
684 span
: rustc_span
::Span
,
687 self.print_name(name
);
688 self.print_generic_params(generics
.params
);
689 self.print_where_clause(generics
);
691 self.print_variants(enum_definition
.variants
, span
);
694 fn print_variants(&mut self, variants
: &[hir
::Variant
<'_
>], span
: rustc_span
::Span
) {
697 self.space_if_not_bol();
698 self.maybe_print_comment(v
.span
.lo());
699 self.print_outer_attributes(self.attrs(v
.hir_id
));
700 self.ibox(INDENT_UNIT
);
701 self.print_variant(v
);
704 self.maybe_print_trailing_comment(v
.span
, None
);
709 fn print_defaultness(&mut self, defaultness
: hir
::Defaultness
) {
711 hir
::Defaultness
::Default { .. }
=> self.word_nbsp("default"),
712 hir
::Defaultness
::Final
=> (),
718 struct_def
: &hir
::VariantData
<'_
>,
719 generics
: &hir
::Generics
<'_
>,
721 span
: rustc_span
::Span
,
722 print_finalizer
: bool
,
724 self.print_name(name
);
725 self.print_generic_params(generics
.params
);
727 hir
::VariantData
::Tuple(..) | hir
::VariantData
::Unit(..) => {
728 if let hir
::VariantData
::Tuple(..) = struct_def
{
730 self.commasep(Inconsistent
, struct_def
.fields(), |s
, field
| {
731 s
.maybe_print_comment(field
.span
.lo());
732 s
.print_outer_attributes(s
.attrs(field
.hir_id
));
733 s
.print_type(field
.ty
);
737 self.print_where_clause(generics
);
742 self.end() // close the outer-box
744 hir
::VariantData
::Struct { .. }
=> {
745 self.print_where_clause(generics
);
748 self.hardbreak_if_not_bol();
750 for field
in struct_def
.fields() {
751 self.hardbreak_if_not_bol();
752 self.maybe_print_comment(field
.span
.lo());
753 self.print_outer_attributes(self.attrs(field
.hir_id
));
754 self.print_ident(field
.ident
);
756 self.print_type(field
.ty
);
765 fn print_variant(&mut self, v
: &hir
::Variant
<'_
>) {
767 let generics
= hir
::Generics
::empty();
768 self.print_struct(&v
.data
, generics
, v
.ident
.name
, v
.span
, false);
769 if let Some(ref d
) = v
.disr_expr
{
771 self.word_space("=");
772 self.print_anon_const(d
);
780 generics
: &hir
::Generics
<'_
>,
782 body_id
: Option
<hir
::BodyId
>,
784 self.print_fn(m
.decl
, m
.header
, Some(ident
.name
), generics
, arg_names
, body_id
);
787 fn print_trait_item(&mut self, ti
: &hir
::TraitItem
<'_
>) {
788 self.ann
.pre(self, AnnNode
::SubItem(ti
.hir_id()));
789 self.hardbreak_if_not_bol();
790 self.maybe_print_comment(ti
.span
.lo());
791 self.print_outer_attributes(self.attrs(ti
.hir_id()));
793 hir
::TraitItemKind
::Const(ty
, default) => {
794 self.print_associated_const(ti
.ident
, ti
.generics
, ty
, default);
796 hir
::TraitItemKind
::Fn(ref sig
, hir
::TraitFn
::Required(arg_names
)) => {
797 self.print_method_sig(ti
.ident
, sig
, ti
.generics
, arg_names
, None
);
800 hir
::TraitItemKind
::Fn(ref sig
, hir
::TraitFn
::Provided(body
)) => {
802 self.print_method_sig(ti
.ident
, sig
, ti
.generics
, &[], Some(body
));
804 self.end(); // need to close a box
805 self.end(); // need to close a box
806 self.ann
.nested(self, Nested
::Body(body
));
808 hir
::TraitItemKind
::Type(bounds
, default) => {
809 self.print_associated_type(ti
.ident
, ti
.generics
, Some(bounds
), default);
812 self.ann
.post(self, AnnNode
::SubItem(ti
.hir_id()))
815 fn print_impl_item(&mut self, ii
: &hir
::ImplItem
<'_
>) {
816 self.ann
.pre(self, AnnNode
::SubItem(ii
.hir_id()));
817 self.hardbreak_if_not_bol();
818 self.maybe_print_comment(ii
.span
.lo());
819 self.print_outer_attributes(self.attrs(ii
.hir_id()));
822 hir
::ImplItemKind
::Const(ty
, expr
) => {
823 self.print_associated_const(ii
.ident
, ii
.generics
, ty
, Some(expr
));
825 hir
::ImplItemKind
::Fn(ref sig
, body
) => {
827 self.print_method_sig(ii
.ident
, sig
, ii
.generics
, &[], Some(body
));
829 self.end(); // need to close a box
830 self.end(); // need to close a box
831 self.ann
.nested(self, Nested
::Body(body
));
833 hir
::ImplItemKind
::Type(ty
) => {
834 self.print_associated_type(ii
.ident
, ii
.generics
, None
, Some(ty
));
837 self.ann
.post(self, AnnNode
::SubItem(ii
.hir_id()))
842 init
: Option
<&hir
::Expr
<'_
>>,
843 els
: Option
<&hir
::Block
<'_
>>,
844 decl
: impl Fn(&mut Self),
846 self.space_if_not_bol();
847 self.ibox(INDENT_UNIT
);
848 self.word_nbsp("let");
850 self.ibox(INDENT_UNIT
);
854 if let Some(init
) = init
{
856 self.word_space("=");
857 self.print_expr(init
);
860 if let Some(els
) = els
{
862 self.word_space("else");
863 // containing cbox, will be closed by print-block at `}`
865 // head-box, will be closed by print-block after `{`
867 self.print_block(els
);
873 fn print_stmt(&mut self, st
: &hir
::Stmt
<'_
>) {
874 self.maybe_print_comment(st
.span
.lo());
876 hir
::StmtKind
::Local(loc
) => {
877 self.print_local(loc
.init
, loc
.els
, |this
| this
.print_local_decl(loc
));
879 hir
::StmtKind
::Item(item
) => self.ann
.nested(self, Nested
::Item(item
)),
880 hir
::StmtKind
::Expr(expr
) => {
881 self.space_if_not_bol();
882 self.print_expr(expr
);
884 hir
::StmtKind
::Semi(expr
) => {
885 self.space_if_not_bol();
886 self.print_expr(expr
);
890 if stmt_ends_with_semi(&st
.kind
) {
893 self.maybe_print_trailing_comment(st
.span
, None
)
896 fn print_block(&mut self, blk
: &hir
::Block
<'_
>) {
897 self.print_block_with_attrs(blk
, &[])
900 fn print_block_unclosed(&mut self, blk
: &hir
::Block
<'_
>) {
901 self.print_block_maybe_unclosed(blk
, &[], false)
904 fn print_block_with_attrs(&mut self, blk
: &hir
::Block
<'_
>, attrs
: &[ast
::Attribute
]) {
905 self.print_block_maybe_unclosed(blk
, attrs
, true)
908 fn print_block_maybe_unclosed(
910 blk
: &hir
::Block
<'_
>,
911 attrs
: &[ast
::Attribute
],
915 hir
::BlockCheckMode
::UnsafeBlock(..) => self.word_space("unsafe"),
916 hir
::BlockCheckMode
::DefaultBlock
=> (),
918 self.maybe_print_comment(blk
.span
.lo());
919 self.ann
.pre(self, AnnNode
::Block(blk
));
922 self.print_inner_attributes(attrs
);
924 for st
in blk
.stmts
{
927 if let Some(expr
) = blk
.expr
{
928 self.space_if_not_bol();
929 self.print_expr(expr
);
930 self.maybe_print_trailing_comment(expr
.span
, Some(blk
.span
.hi()));
932 self.bclose_maybe_open(blk
.span
, close_box
);
933 self.ann
.post(self, AnnNode
::Block(blk
))
936 fn print_else(&mut self, els
: Option
<&hir
::Expr
<'_
>>) {
937 if let Some(els_inner
) = els
{
938 match els_inner
.kind
{
939 // Another `else if` block.
940 hir
::ExprKind
::If(i
, then
, e
) => {
941 self.cbox(INDENT_UNIT
- 1);
943 self.word(" else if ");
944 self.print_expr_as_cond(i
);
946 self.print_expr(then
);
949 // Final `else` block.
950 hir
::ExprKind
::Block(b
, _
) => {
951 self.cbox(INDENT_UNIT
- 1);
956 // Constraints would be great here!
958 panic
!("print_if saw if with weird alternative");
966 test
: &hir
::Expr
<'_
>,
968 elseopt
: Option
<&hir
::Expr
<'_
>>,
971 self.print_expr_as_cond(test
);
973 self.print_expr(blk
);
974 self.print_else(elseopt
)
977 fn print_array_length(&mut self, len
: &hir
::ArrayLen
) {
979 hir
::ArrayLen
::Infer(_
, _
) => self.word("_"),
980 hir
::ArrayLen
::Body(ct
) => self.print_anon_const(ct
),
984 fn print_anon_const(&mut self, constant
: &hir
::AnonConst
) {
985 self.ann
.nested(self, Nested
::Body(constant
.body
))
988 fn print_call_post(&mut self, args
: &[hir
::Expr
<'_
>]) {
990 self.commasep_exprs(Inconsistent
, args
);
994 fn print_expr_maybe_paren(&mut self, expr
: &hir
::Expr
<'_
>, prec
: i8) {
995 self.print_expr_cond_paren(expr
, expr
.precedence().order() < prec
)
998 /// Prints an expr using syntax that's acceptable in a condition position, such as the `cond` in
999 /// `if cond { ... }`.
1000 fn print_expr_as_cond(&mut self, expr
: &hir
::Expr
<'_
>) {
1001 self.print_expr_cond_paren(expr
, Self::cond_needs_par(expr
))
1004 /// Prints `expr` or `(expr)` when `needs_par` holds.
1005 fn print_expr_cond_paren(&mut self, expr
: &hir
::Expr
<'_
>, needs_par
: bool
) {
1009 if let hir
::ExprKind
::DropTemps(actual_expr
) = expr
.kind
{
1010 self.print_expr(actual_expr
);
1012 self.print_expr(expr
);
1019 /// Print a `let pat = expr` expression.
1020 fn print_let(&mut self, pat
: &hir
::Pat
<'_
>, ty
: Option
<&hir
::Ty
<'_
>>, init
: &hir
::Expr
<'_
>) {
1021 self.word_space("let");
1022 self.print_pat(pat
);
1023 if let Some(ty
) = ty
{
1024 self.word_space(":");
1025 self.print_type(ty
);
1028 self.word_space("=");
1029 let npals
= || parser
::needs_par_as_let_scrutinee(init
.precedence().order());
1030 self.print_expr_cond_paren(init
, Self::cond_needs_par(init
) || npals())
1033 // Does `expr` need parentheses when printed in a condition position?
1035 // These cases need parens due to the parse error observed in #26461: `if return {}`
1036 // parses as the erroneous construct `if (return {})`, not `if (return) {}`.
1037 fn cond_needs_par(expr
: &hir
::Expr
<'_
>) -> bool
{
1039 hir
::ExprKind
::Break(..) | hir
::ExprKind
::Closure { .. }
| hir
::ExprKind
::Ret(..) => {
1042 _
=> contains_exterior_struct_lit(expr
),
1046 fn print_expr_vec(&mut self, exprs
: &[hir
::Expr
<'_
>]) {
1047 self.ibox(INDENT_UNIT
);
1049 self.commasep_exprs(Inconsistent
, exprs
);
1054 fn print_inline_const(&mut self, constant
: &hir
::ConstBlock
) {
1055 self.ibox(INDENT_UNIT
);
1056 self.word_space("const");
1057 self.ann
.nested(self, Nested
::Body(constant
.body
));
1061 fn print_expr_repeat(&mut self, element
: &hir
::Expr
<'_
>, count
: &hir
::ArrayLen
) {
1062 self.ibox(INDENT_UNIT
);
1064 self.print_expr(element
);
1065 self.word_space(";");
1066 self.print_array_length(count
);
1071 fn print_expr_struct(
1073 qpath
: &hir
::QPath
<'_
>,
1074 fields
: &[hir
::ExprField
<'_
>],
1075 wth
: Option
<&hir
::Expr
<'_
>>,
1077 self.print_qpath(qpath
, true);
1079 self.commasep_cmnt(Consistent
, fields
, |s
, field
| s
.print_expr_field(field
), |f
| f
.span
);
1080 if let Some(expr
) = wth
{
1081 self.ibox(INDENT_UNIT
);
1082 if !fields
.is_empty() {
1087 self.print_expr(expr
);
1089 } else if !fields
.is_empty() {
1096 fn print_expr_field(&mut self, field
: &hir
::ExprField
<'_
>) {
1097 if self.attrs(field
.hir_id
).is_empty() {
1100 self.cbox(INDENT_UNIT
);
1101 self.print_outer_attributes(self.attrs(field
.hir_id
));
1102 if !field
.is_shorthand
{
1103 self.print_ident(field
.ident
);
1104 self.word_space(":");
1106 self.print_expr(field
.expr
);
1110 fn print_expr_tup(&mut self, exprs
: &[hir
::Expr
<'_
>]) {
1112 self.commasep_exprs(Inconsistent
, exprs
);
1113 if exprs
.len() == 1 {
1119 fn print_expr_call(&mut self, func
: &hir
::Expr
<'_
>, args
: &[hir
::Expr
<'_
>]) {
1120 let prec
= match func
.kind
{
1121 hir
::ExprKind
::Field(..) => parser
::PREC_FORCE_PAREN
,
1122 _
=> parser
::PREC_POSTFIX
,
1125 self.print_expr_maybe_paren(func
, prec
);
1126 self.print_call_post(args
)
1129 fn print_expr_method_call(
1131 segment
: &hir
::PathSegment
<'_
>,
1132 receiver
: &hir
::Expr
<'_
>,
1133 args
: &[hir
::Expr
<'_
>],
1135 let base_args
= args
;
1136 self.print_expr_maybe_paren(receiver
, parser
::PREC_POSTFIX
);
1138 self.print_ident(segment
.ident
);
1140 let generic_args
= segment
.args();
1141 if !generic_args
.args
.is_empty() || !generic_args
.bindings
.is_empty() {
1142 self.print_generic_args(generic_args
, true);
1145 self.print_call_post(base_args
)
1148 fn print_expr_binary(&mut self, op
: hir
::BinOp
, lhs
: &hir
::Expr
<'_
>, rhs
: &hir
::Expr
<'_
>) {
1149 let assoc_op
= bin_op_to_assoc_op(op
.node
);
1150 let prec
= assoc_op
.precedence() as i8;
1151 let fixity
= assoc_op
.fixity();
1153 let (left_prec
, right_prec
) = match fixity
{
1154 Fixity
::Left
=> (prec
, prec
+ 1),
1155 Fixity
::Right
=> (prec
+ 1, prec
),
1156 Fixity
::None
=> (prec
+ 1, prec
+ 1),
1159 let left_prec
= match (&lhs
.kind
, op
.node
) {
1160 // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
1161 // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
1162 // of `(x as i32) < ...`. We need to convince it _not_ to do that.
1163 (&hir
::ExprKind
::Cast { .. }
, hir
::BinOpKind
::Lt
| hir
::BinOpKind
::Shl
) => {
1164 parser
::PREC_FORCE_PAREN
1166 (&hir
::ExprKind
::Let { .. }
, _
) if !parser
::needs_par_as_let_scrutinee(prec
) => {
1167 parser
::PREC_FORCE_PAREN
1172 self.print_expr_maybe_paren(lhs
, left_prec
);
1174 self.word_space(op
.node
.as_str());
1175 self.print_expr_maybe_paren(rhs
, right_prec
)
1178 fn print_expr_unary(&mut self, op
: hir
::UnOp
, expr
: &hir
::Expr
<'_
>) {
1179 self.word(op
.as_str());
1180 self.print_expr_maybe_paren(expr
, parser
::PREC_PREFIX
)
1183 fn print_expr_addr_of(
1185 kind
: hir
::BorrowKind
,
1186 mutability
: hir
::Mutability
,
1187 expr
: &hir
::Expr
<'_
>,
1191 hir
::BorrowKind
::Ref
=> self.print_mutability(mutability
, false),
1192 hir
::BorrowKind
::Raw
=> {
1193 self.word_nbsp("raw");
1194 self.print_mutability(mutability
, true);
1197 self.print_expr_maybe_paren(expr
, parser
::PREC_PREFIX
)
1200 fn print_literal(&mut self, lit
: &hir
::Lit
) {
1201 self.maybe_print_comment(lit
.span
.lo());
1202 self.word(lit
.node
.to_string())
1205 fn print_inline_asm(&mut self, asm
: &hir
::InlineAsm
<'_
>) {
1208 Operand(&'a hir
::InlineAsmOperand
<'a
>),
1209 Options(ast
::InlineAsmOptions
),
1212 let mut args
= vec
![AsmArg
::Template(ast
::InlineAsmTemplatePiece
::to_string(asm
.template
))];
1213 args
.extend(asm
.operands
.iter().map(|(o
, _
)| AsmArg
::Operand(o
)));
1214 if !asm
.options
.is_empty() {
1215 args
.push(AsmArg
::Options(asm
.options
));
1219 self.commasep(Consistent
, &args
, |s
, arg
| match *arg
{
1220 AsmArg
::Template(ref template
) => s
.print_string(template
, ast
::StrStyle
::Cooked
),
1221 AsmArg
::Operand(op
) => match *op
{
1222 hir
::InlineAsmOperand
::In { reg, expr }
=> {
1225 s
.word(format
!("{reg}"));
1230 hir
::InlineAsmOperand
::Out { reg, late, ref expr }
=> {
1231 s
.word(if late { "lateout" }
else { "out" }
);
1233 s
.word(format
!("{reg}"));
1237 Some(expr
) => s
.print_expr(expr
),
1238 None
=> s
.word("_"),
1241 hir
::InlineAsmOperand
::InOut { reg, late, expr }
=> {
1242 s
.word(if late { "inlateout" }
else { "inout" }
);
1244 s
.word(format
!("{reg}"));
1249 hir
::InlineAsmOperand
::SplitInOut { reg, late, in_expr, ref out_expr }
=> {
1250 s
.word(if late { "inlateout" }
else { "inout" }
);
1252 s
.word(format
!("{reg}"));
1255 s
.print_expr(in_expr
);
1259 Some(out_expr
) => s
.print_expr(out_expr
),
1260 None
=> s
.word("_"),
1263 hir
::InlineAsmOperand
::Const { ref anon_const }
=> {
1266 s
.print_anon_const(anon_const
);
1268 hir
::InlineAsmOperand
::SymFn { ref anon_const }
=> {
1271 s
.print_anon_const(anon_const
);
1273 hir
::InlineAsmOperand
::SymStatic { ref path, def_id: _ }
=> {
1274 s
.word("sym_static");
1276 s
.print_qpath(path
, true);
1279 AsmArg
::Options(opts
) => {
1282 let mut options
= vec
![];
1283 if opts
.contains(ast
::InlineAsmOptions
::PURE
) {
1284 options
.push("pure");
1286 if opts
.contains(ast
::InlineAsmOptions
::NOMEM
) {
1287 options
.push("nomem");
1289 if opts
.contains(ast
::InlineAsmOptions
::READONLY
) {
1290 options
.push("readonly");
1292 if opts
.contains(ast
::InlineAsmOptions
::PRESERVES_FLAGS
) {
1293 options
.push("preserves_flags");
1295 if opts
.contains(ast
::InlineAsmOptions
::NORETURN
) {
1296 options
.push("noreturn");
1298 if opts
.contains(ast
::InlineAsmOptions
::NOSTACK
) {
1299 options
.push("nostack");
1301 if opts
.contains(ast
::InlineAsmOptions
::ATT_SYNTAX
) {
1302 options
.push("att_syntax");
1304 if opts
.contains(ast
::InlineAsmOptions
::RAW
) {
1305 options
.push("raw");
1307 if opts
.contains(ast
::InlineAsmOptions
::MAY_UNWIND
) {
1308 options
.push("may_unwind");
1310 s
.commasep(Inconsistent
, &options
, |s
, &opt
| {
1319 fn print_expr(&mut self, expr
: &hir
::Expr
<'_
>) {
1320 self.maybe_print_comment(expr
.span
.lo());
1321 self.print_outer_attributes(self.attrs(expr
.hir_id
));
1322 self.ibox(INDENT_UNIT
);
1323 self.ann
.pre(self, AnnNode
::Expr(expr
));
1325 hir
::ExprKind
::Array(exprs
) => {
1326 self.print_expr_vec(exprs
);
1328 hir
::ExprKind
::ConstBlock(ref anon_const
) => {
1329 self.print_inline_const(anon_const
);
1331 hir
::ExprKind
::Repeat(element
, ref count
) => {
1332 self.print_expr_repeat(element
, count
);
1334 hir
::ExprKind
::Struct(qpath
, fields
, wth
) => {
1335 self.print_expr_struct(qpath
, fields
, wth
);
1337 hir
::ExprKind
::Tup(exprs
) => {
1338 self.print_expr_tup(exprs
);
1340 hir
::ExprKind
::Call(func
, args
) => {
1341 self.print_expr_call(func
, args
);
1343 hir
::ExprKind
::MethodCall(segment
, receiver
, args
, _
) => {
1344 self.print_expr_method_call(segment
, receiver
, args
);
1346 hir
::ExprKind
::Binary(op
, lhs
, rhs
) => {
1347 self.print_expr_binary(op
, lhs
, rhs
);
1349 hir
::ExprKind
::Unary(op
, expr
) => {
1350 self.print_expr_unary(op
, expr
);
1352 hir
::ExprKind
::AddrOf(k
, m
, expr
) => {
1353 self.print_expr_addr_of(k
, m
, expr
);
1355 hir
::ExprKind
::Lit(lit
) => {
1356 self.print_literal(lit
);
1358 hir
::ExprKind
::Cast(expr
, ty
) => {
1359 let prec
= AssocOp
::As
.precedence() as i8;
1360 self.print_expr_maybe_paren(expr
, prec
);
1362 self.word_space("as");
1363 self.print_type(ty
);
1365 hir
::ExprKind
::Type(expr
, ty
) => {
1366 self.word("type_ascribe!(");
1368 self.print_expr(expr
);
1371 self.space_if_not_bol();
1372 self.print_type(ty
);
1377 hir
::ExprKind
::DropTemps(init
) => {
1379 self.cbox(INDENT_UNIT
);
1383 // Print `let _t = $init;`:
1384 let temp
= Ident
::from_str("_t");
1385 self.print_local(Some(init
), None
, |this
| this
.print_ident(temp
));
1389 self.space_if_not_bol();
1390 self.print_ident(temp
);
1393 self.bclose_maybe_open(expr
.span
, true);
1395 hir
::ExprKind
::Let(&hir
::Let { pat, ty, init, .. }
) => {
1396 self.print_let(pat
, ty
, init
);
1398 hir
::ExprKind
::If(test
, blk
, elseopt
) => {
1399 self.print_if(test
, blk
, elseopt
);
1401 hir
::ExprKind
::Loop(blk
, opt_label
, _
, _
) => {
1402 if let Some(label
) = opt_label
{
1403 self.print_ident(label
.ident
);
1404 self.word_space(":");
1407 self.print_block(blk
);
1409 hir
::ExprKind
::Match(expr
, arms
, _
) => {
1410 self.cbox(INDENT_UNIT
);
1411 self.ibox(INDENT_UNIT
);
1412 self.word_nbsp("match");
1413 self.print_expr_as_cond(expr
);
1417 self.print_arm(arm
);
1419 self.bclose(expr
.span
);
1421 hir
::ExprKind
::Closure(&hir
::Closure
{
1425 bound_generic_params
,
1433 self.print_closure_binder(binder
, bound_generic_params
);
1434 self.print_constness(constness
);
1435 self.print_capture_clause(capture_clause
);
1437 self.print_closure_params(fn_decl
, body
);
1440 // This is a bare expression.
1441 self.ann
.nested(self, Nested
::Body(body
));
1442 self.end(); // need to close a box
1444 // A box will be closed by `print_expr`, but we didn't want an overall
1445 // wrapper so we closed the corresponding opening. so create an
1446 // empty box to satisfy the close.
1449 hir
::ExprKind
::Block(blk
, opt_label
) => {
1450 if let Some(label
) = opt_label
{
1451 self.print_ident(label
.ident
);
1452 self.word_space(":");
1454 // containing cbox, will be closed by print-block at `}`
1455 self.cbox(INDENT_UNIT
);
1456 // head-box, will be closed by print-block after `{`
1458 self.print_block(blk
);
1460 hir
::ExprKind
::Assign(lhs
, rhs
, _
) => {
1461 let prec
= AssocOp
::Assign
.precedence() as i8;
1462 self.print_expr_maybe_paren(lhs
, prec
+ 1);
1464 self.word_space("=");
1465 self.print_expr_maybe_paren(rhs
, prec
);
1467 hir
::ExprKind
::AssignOp(op
, lhs
, rhs
) => {
1468 let prec
= AssocOp
::Assign
.precedence() as i8;
1469 self.print_expr_maybe_paren(lhs
, prec
+ 1);
1471 self.word(op
.node
.as_str());
1472 self.word_space("=");
1473 self.print_expr_maybe_paren(rhs
, prec
);
1475 hir
::ExprKind
::Field(expr
, ident
) => {
1476 self.print_expr_maybe_paren(expr
, parser
::PREC_POSTFIX
);
1478 self.print_ident(ident
);
1480 hir
::ExprKind
::Index(expr
, index
, _
) => {
1481 self.print_expr_maybe_paren(expr
, parser
::PREC_POSTFIX
);
1483 self.print_expr(index
);
1486 hir
::ExprKind
::Path(ref qpath
) => self.print_qpath(qpath
, true),
1487 hir
::ExprKind
::Break(destination
, opt_expr
) => {
1489 if let Some(label
) = destination
.label
{
1491 self.print_ident(label
.ident
);
1493 if let Some(expr
) = opt_expr
{
1495 self.print_expr_maybe_paren(expr
, parser
::PREC_JUMP
);
1498 hir
::ExprKind
::Continue(destination
) => {
1499 self.word("continue");
1500 if let Some(label
) = destination
.label
{
1502 self.print_ident(label
.ident
);
1505 hir
::ExprKind
::Ret(result
) => {
1506 self.word("return");
1507 if let Some(expr
) = result
{
1509 self.print_expr_maybe_paren(expr
, parser
::PREC_JUMP
);
1512 hir
::ExprKind
::Become(result
) => {
1513 self.word("become");
1515 self.print_expr_maybe_paren(result
, parser
::PREC_JUMP
);
1517 hir
::ExprKind
::InlineAsm(asm
) => {
1519 self.print_inline_asm(asm
);
1521 hir
::ExprKind
::OffsetOf(container
, fields
) => {
1522 self.word("offset_of!(");
1523 self.print_type(container
);
1527 if let Some((&first
, rest
)) = fields
.split_first() {
1528 self.print_ident(first
);
1530 for &field
in rest
{
1532 self.print_ident(field
);
1538 hir
::ExprKind
::Yield(expr
, _
) => {
1539 self.word_space("yield");
1540 self.print_expr_maybe_paren(expr
, parser
::PREC_JUMP
);
1542 hir
::ExprKind
::Err(_
) => {
1544 self.word("/*ERROR*/");
1548 self.ann
.post(self, AnnNode
::Expr(expr
));
1552 fn print_local_decl(&mut self, loc
: &hir
::Local
<'_
>) {
1553 self.print_pat(loc
.pat
);
1554 if let Some(ty
) = loc
.ty
{
1555 self.word_space(":");
1556 self.print_type(ty
);
1560 fn print_name(&mut self, name
: Symbol
) {
1561 self.print_ident(Ident
::with_dummy_span(name
))
1564 fn print_path
<R
>(&mut self, path
: &hir
::Path
<'_
, R
>, colons_before_params
: bool
) {
1565 self.maybe_print_comment(path
.span
.lo());
1567 for (i
, segment
) in path
.segments
.iter().enumerate() {
1571 if segment
.ident
.name
!= kw
::PathRoot
{
1572 self.print_ident(segment
.ident
);
1573 self.print_generic_args(segment
.args(), colons_before_params
);
1578 fn print_path_segment(&mut self, segment
: &hir
::PathSegment
<'_
>) {
1579 if segment
.ident
.name
!= kw
::PathRoot
{
1580 self.print_ident(segment
.ident
);
1581 self.print_generic_args(segment
.args(), false);
1585 fn print_qpath(&mut self, qpath
: &hir
::QPath
<'_
>, colons_before_params
: bool
) {
1587 hir
::QPath
::Resolved(None
, path
) => self.print_path(path
, colons_before_params
),
1588 hir
::QPath
::Resolved(Some(qself
), path
) => {
1590 self.print_type(qself
);
1592 self.word_space("as");
1594 for (i
, segment
) in path
.segments
[..path
.segments
.len() - 1].iter().enumerate() {
1598 if segment
.ident
.name
!= kw
::PathRoot
{
1599 self.print_ident(segment
.ident
);
1600 self.print_generic_args(segment
.args(), colons_before_params
);
1606 let item_segment
= path
.segments
.last().unwrap();
1607 self.print_ident(item_segment
.ident
);
1608 self.print_generic_args(item_segment
.args(), colons_before_params
)
1610 hir
::QPath
::TypeRelative(qself
, item_segment
) => {
1611 // If we've got a compound-qualified-path, let's push an additional pair of angle
1612 // brackets, so that we pretty-print `<<A::B>::C>` as `<A::B>::C`, instead of just
1613 // `A::B::C` (since the latter could be ambiguous to the user)
1614 if let hir
::TyKind
::Path(hir
::QPath
::Resolved(None
, _
)) = qself
.kind
{
1615 self.print_type(qself
);
1618 self.print_type(qself
);
1623 self.print_ident(item_segment
.ident
);
1624 self.print_generic_args(item_segment
.args(), colons_before_params
)
1626 hir
::QPath
::LangItem(lang_item
, span
) => {
1627 self.word("#[lang = \"");
1628 self.print_ident(Ident
::new(lang_item
.name(), span
));
1634 fn print_generic_args(
1636 generic_args
: &hir
::GenericArgs
<'_
>,
1637 colons_before_params
: bool
,
1639 match generic_args
.parenthesized
{
1640 hir
::GenericArgsParentheses
::No
=> {
1641 let start
= if colons_before_params { "::<" }
else { "<" }
;
1642 let empty
= Cell
::new(true);
1643 let start_or_comma
= |this
: &mut Self| {
1648 this
.word_space(",")
1652 let mut nonelided_generic_args
: bool
= false;
1653 let elide_lifetimes
= generic_args
.args
.iter().all(|arg
| match arg
{
1654 GenericArg
::Lifetime(lt
) if lt
.is_elided() => true,
1655 GenericArg
::Lifetime(_
) => {
1656 nonelided_generic_args
= true;
1660 nonelided_generic_args
= true;
1665 if nonelided_generic_args
{
1666 start_or_comma(self);
1667 self.commasep(Inconsistent
, generic_args
.args
, |s
, generic_arg
| {
1669 GenericArg
::Lifetime(lt
) if !elide_lifetimes
=> s
.print_lifetime(lt
),
1670 GenericArg
::Lifetime(_
) => {}
1671 GenericArg
::Type(ty
) => s
.print_type(ty
),
1672 GenericArg
::Const(ct
) => s
.print_anon_const(&ct
.value
),
1673 GenericArg
::Infer(_inf
) => s
.word("_"),
1678 for binding
in generic_args
.bindings
{
1679 start_or_comma(self);
1680 self.print_type_binding(binding
);
1687 hir
::GenericArgsParentheses
::ParenSugar
=> {
1689 self.commasep(Inconsistent
, generic_args
.inputs(), |s
, ty
| s
.print_type(ty
));
1692 self.space_if_not_bol();
1693 self.word_space("->");
1694 self.print_type(generic_args
.bindings
[0].ty());
1696 hir
::GenericArgsParentheses
::ReturnTypeNotation
=> {
1702 fn print_type_binding(&mut self, binding
: &hir
::TypeBinding
<'_
>) {
1703 self.print_ident(binding
.ident
);
1704 self.print_generic_args(binding
.gen_args
, false);
1706 match binding
.kind
{
1707 hir
::TypeBindingKind
::Equality { ref term }
=> {
1708 self.word_space("=");
1710 Term
::Ty(ty
) => self.print_type(ty
),
1711 Term
::Const(ref c
) => self.print_anon_const(c
),
1714 hir
::TypeBindingKind
::Constraint { bounds }
=> {
1715 self.print_bounds(":", bounds
);
1720 fn print_pat(&mut self, pat
: &hir
::Pat
<'_
>) {
1721 self.maybe_print_comment(pat
.span
.lo());
1722 self.ann
.pre(self, AnnNode
::Pat(pat
));
1723 // Pat isn't normalized, but the beauty of it
1724 // is that it doesn't matter
1726 PatKind
::Wild
=> self.word("_"),
1727 PatKind
::Never
=> self.word("!"),
1728 PatKind
::Binding(BindingAnnotation(by_ref
, mutbl
), _
, ident
, sub
) => {
1729 if by_ref
== ByRef
::Yes
{
1730 self.word_nbsp("ref");
1733 self.word_nbsp("mut");
1735 self.print_ident(ident
);
1736 if let Some(p
) = sub
{
1741 PatKind
::TupleStruct(ref qpath
, elts
, ddpos
) => {
1742 self.print_qpath(qpath
, true);
1744 if let Some(ddpos
) = ddpos
.as_opt_usize() {
1745 self.commasep(Inconsistent
, &elts
[..ddpos
], |s
, p
| s
.print_pat(p
));
1747 self.word_space(",");
1750 if ddpos
!= elts
.len() {
1752 self.commasep(Inconsistent
, &elts
[ddpos
..], |s
, p
| s
.print_pat(p
));
1755 self.commasep(Inconsistent
, elts
, |s
, p
| s
.print_pat(p
));
1759 PatKind
::Path(ref qpath
) => {
1760 self.print_qpath(qpath
, true);
1762 PatKind
::Struct(ref qpath
, fields
, etc
) => {
1763 self.print_qpath(qpath
, true);
1766 let empty
= fields
.is_empty() && !etc
;
1770 self.commasep_cmnt(Consistent
, fields
, |s
, f
| s
.print_patfield(f
), |f
| f
.pat
.span
);
1772 if !fields
.is_empty() {
1773 self.word_space(",");
1782 PatKind
::Or(pats
) => {
1783 self.strsep("|", true, Inconsistent
, pats
, |s
, p
| s
.print_pat(p
));
1785 PatKind
::Tuple(elts
, ddpos
) => {
1787 if let Some(ddpos
) = ddpos
.as_opt_usize() {
1788 self.commasep(Inconsistent
, &elts
[..ddpos
], |s
, p
| s
.print_pat(p
));
1790 self.word_space(",");
1793 if ddpos
!= elts
.len() {
1795 self.commasep(Inconsistent
, &elts
[ddpos
..], |s
, p
| s
.print_pat(p
));
1798 self.commasep(Inconsistent
, elts
, |s
, p
| s
.print_pat(p
));
1799 if elts
.len() == 1 {
1805 PatKind
::Box(inner
) => {
1806 let is_range_inner
= matches
!(inner
.kind
, PatKind
::Range(..));
1811 self.print_pat(inner
);
1816 PatKind
::Ref(inner
, mutbl
) => {
1817 let is_range_inner
= matches
!(inner
.kind
, PatKind
::Range(..));
1819 self.word(mutbl
.prefix_str());
1823 self.print_pat(inner
);
1828 PatKind
::Lit(e
) => self.print_expr(e
),
1829 PatKind
::Range(begin
, end
, end_kind
) => {
1830 if let Some(expr
) = begin
{
1831 self.print_expr(expr
);
1834 RangeEnd
::Included
=> self.word("..."),
1835 RangeEnd
::Excluded
=> self.word(".."),
1837 if let Some(expr
) = end
{
1838 self.print_expr(expr
);
1841 PatKind
::Slice(before
, slice
, after
) => {
1843 self.commasep(Inconsistent
, before
, |s
, p
| s
.print_pat(p
));
1844 if let Some(p
) = slice
{
1845 if !before
.is_empty() {
1846 self.word_space(",");
1848 if let PatKind
::Wild
= p
.kind
{
1854 if !after
.is_empty() {
1855 self.word_space(",");
1858 self.commasep(Inconsistent
, after
, |s
, p
| s
.print_pat(p
));
1862 self.ann
.post(self, AnnNode
::Pat(pat
))
1865 fn print_patfield(&mut self, field
: &hir
::PatField
<'_
>) {
1866 if self.attrs(field
.hir_id
).is_empty() {
1869 self.cbox(INDENT_UNIT
);
1870 self.print_outer_attributes(self.attrs(field
.hir_id
));
1871 if !field
.is_shorthand
{
1872 self.print_ident(field
.ident
);
1873 self.word_nbsp(":");
1875 self.print_pat(field
.pat
);
1879 fn print_param(&mut self, arg
: &hir
::Param
<'_
>) {
1880 self.print_outer_attributes(self.attrs(arg
.hir_id
));
1881 self.print_pat(arg
.pat
);
1884 fn print_arm(&mut self, arm
: &hir
::Arm
<'_
>) {
1885 // I have no idea why this check is necessary, but here it
1887 if self.attrs(arm
.hir_id
).is_empty() {
1890 self.cbox(INDENT_UNIT
);
1891 self.ann
.pre(self, AnnNode
::Arm(arm
));
1893 self.print_outer_attributes(self.attrs(arm
.hir_id
));
1894 self.print_pat(arm
.pat
);
1896 if let Some(ref g
) = arm
.guard
{
1898 hir
::Guard
::If(e
) => {
1899 self.word_space("if");
1903 hir
::Guard
::IfLet(&hir
::Let { pat, ty, init, .. }
) => {
1904 self.word_nbsp("if");
1905 self.print_let(pat
, ty
, init
);
1909 self.word_space("=>");
1911 match arm
.body
.kind
{
1912 hir
::ExprKind
::Block(blk
, opt_label
) => {
1913 if let Some(label
) = opt_label
{
1914 self.print_ident(label
.ident
);
1915 self.word_space(":");
1917 // the block will close the pattern's ibox
1918 self.print_block_unclosed(blk
);
1920 // If it is a user-provided unsafe block, print a comma after it
1921 if let hir
::BlockCheckMode
::UnsafeBlock(hir
::UnsafeSource
::UserProvided
) = blk
.rules
1927 self.end(); // close the ibox for the pattern
1928 self.print_expr(arm
.body
);
1932 self.ann
.post(self, AnnNode
::Arm(arm
));
1933 self.end() // close enclosing cbox
1938 decl
: &hir
::FnDecl
<'_
>,
1939 header
: hir
::FnHeader
,
1940 name
: Option
<Symbol
>,
1941 generics
: &hir
::Generics
<'_
>,
1942 arg_names
: &[Ident
],
1943 body_id
: Option
<hir
::BodyId
>,
1945 self.print_fn_header_info(header
);
1947 if let Some(name
) = name
{
1949 self.print_name(name
);
1951 self.print_generic_params(generics
.params
);
1954 // Make sure we aren't supplied *both* `arg_names` and `body_id`.
1955 assert
!(arg_names
.is_empty() || body_id
.is_none());
1957 let mut print_arg
= |s
: &mut Self| {
1958 if let Some(arg_name
) = arg_names
.get(i
) {
1959 s
.word(arg_name
.to_string());
1962 } else if let Some(body_id
) = body_id
{
1963 s
.ann
.nested(s
, Nested
::BodyParamPat(body_id
, i
));
1969 self.commasep(Inconsistent
, decl
.inputs
, |s
, ty
| {
1970 s
.ibox(INDENT_UNIT
);
1975 if decl
.c_variadic
{
1982 self.print_fn_output(decl
);
1983 self.print_where_clause(generics
)
1986 fn print_closure_params(&mut self, decl
: &hir
::FnDecl
<'_
>, body_id
: hir
::BodyId
) {
1989 self.commasep(Inconsistent
, decl
.inputs
, |s
, ty
| {
1990 s
.ibox(INDENT_UNIT
);
1992 s
.ann
.nested(s
, Nested
::BodyParamPat(body_id
, i
));
1995 if let hir
::TyKind
::Infer
= ty
.kind
{
2007 hir
::FnRetTy
::Return(ty
) => {
2008 self.space_if_not_bol();
2009 self.word_space("->");
2010 self.print_type(ty
);
2011 self.maybe_print_comment(ty
.span
.lo());
2013 hir
::FnRetTy
::DefaultReturn(..) => {}
2017 fn print_capture_clause(&mut self, capture_clause
: hir
::CaptureBy
) {
2018 match capture_clause
{
2019 hir
::CaptureBy
::Value { .. }
=> self.word_space("move"),
2020 hir
::CaptureBy
::Ref
=> {}
2024 fn print_closure_binder(
2026 binder
: hir
::ClosureBinder
,
2027 generic_params
: &[GenericParam
<'_
>],
2029 let generic_params
= generic_params
2035 kind
: GenericParamKind
::Lifetime { kind: LifetimeParamKind::Explicit }
,
2040 .collect
::<Vec
<_
>>();
2043 hir
::ClosureBinder
::Default
=> {}
2044 // We need to distinguish `|...| {}` from `for<> |...| {}` as `for<>` adds additional
2046 hir
::ClosureBinder
::For { .. }
if generic_params
.is_empty() => self.word("for<>"),
2047 hir
::ClosureBinder
::For { .. }
=> {
2051 self.commasep(Inconsistent
, &generic_params
, |s
, param
| {
2052 s
.print_generic_param(param
)
2061 fn print_bounds
<'b
>(
2063 prefix
: &'
static str,
2064 bounds
: impl IntoIterator
<Item
= &'b hir
::GenericBound
<'b
>>,
2066 let mut first
= true;
2067 for bound
in bounds
{
2071 if !(first
&& prefix
.is_empty()) {
2077 self.word_space("+");
2081 GenericBound
::Trait(tref
, modifier
) => {
2082 if modifier
== &TraitBoundModifier
::Maybe
{
2085 self.print_poly_trait_ref(tref
);
2087 GenericBound
::Outlives(lt
) => {
2088 self.print_lifetime(lt
);
2094 fn print_generic_params(&mut self, generic_params
: &[GenericParam
<'_
>]) {
2095 if !generic_params
.is_empty() {
2098 self.commasep(Inconsistent
, generic_params
, |s
, param
| s
.print_generic_param(param
));
2104 fn print_generic_param(&mut self, param
: &GenericParam
<'_
>) {
2105 if let GenericParamKind
::Const { .. }
= param
.kind
{
2106 self.word_space("const");
2109 self.print_ident(param
.name
.ident());
2112 GenericParamKind
::Lifetime { .. }
=> {}
2113 GenericParamKind
::Type { default, .. }
=> {
2114 if let Some(default) = default {
2116 self.word_space("=");
2117 self.print_type(default);
2120 GenericParamKind
::Const { ty, ref default, is_host_effect: _ }
=> {
2121 self.word_space(":");
2122 self.print_type(ty
);
2123 if let Some(default) = default {
2125 self.word_space("=");
2126 self.print_anon_const(default);
2132 fn print_lifetime(&mut self, lifetime
: &hir
::Lifetime
) {
2133 self.print_ident(lifetime
.ident
)
2136 fn print_where_clause(&mut self, generics
: &hir
::Generics
<'_
>) {
2137 if generics
.predicates
.is_empty() {
2142 self.word_space("where");
2144 for (i
, predicate
) in generics
.predicates
.iter().enumerate() {
2146 self.word_space(",");
2150 hir
::WherePredicate
::BoundPredicate(hir
::WhereBoundPredicate
{
2151 bound_generic_params
,
2156 self.print_formal_generic_params(bound_generic_params
);
2157 self.print_type(bounded_ty
);
2158 self.print_bounds(":", bounds
);
2160 hir
::WherePredicate
::RegionPredicate(hir
::WhereRegionPredicate
{
2165 self.print_lifetime(lifetime
);
2168 for (i
, bound
) in bounds
.iter().enumerate() {
2170 GenericBound
::Outlives(lt
) => {
2171 self.print_lifetime(lt
);
2173 _
=> panic
!("unexpected bound on lifetime param: {bound:?}"),
2181 hir
::WherePredicate
::EqPredicate(hir
::WhereEqPredicate
{
2184 self.print_type(lhs_ty
);
2186 self.word_space("=");
2187 self.print_type(rhs_ty
);
2193 fn print_mutability(&mut self, mutbl
: hir
::Mutability
, print_const
: bool
) {
2195 hir
::Mutability
::Mut
=> self.word_nbsp("mut"),
2196 hir
::Mutability
::Not
=> {
2198 self.word_nbsp("const")
2204 fn print_mt(&mut self, mt
: &hir
::MutTy
<'_
>, print_const
: bool
) {
2205 self.print_mutability(mt
.mutbl
, print_const
);
2206 self.print_type(mt
.ty
);
2209 fn print_fn_output(&mut self, decl
: &hir
::FnDecl
<'_
>) {
2211 hir
::FnRetTy
::Return(ty
) => {
2212 self.space_if_not_bol();
2213 self.ibox(INDENT_UNIT
);
2214 self.word_space("->");
2215 self.print_type(ty
);
2217 hir
::FnRetTy
::DefaultReturn(..) => return,
2221 if let hir
::FnRetTy
::Return(output
) = decl
.output
{
2222 self.maybe_print_comment(output
.span
.lo());
2229 unsafety
: hir
::Unsafety
,
2230 decl
: &hir
::FnDecl
<'_
>,
2231 name
: Option
<Symbol
>,
2232 generic_params
: &[hir
::GenericParam
<'_
>],
2233 arg_names
: &[Ident
],
2235 self.ibox(INDENT_UNIT
);
2236 self.print_formal_generic_params(generic_params
);
2237 let generics
= hir
::Generics
::empty();
2243 constness
: hir
::Constness
::NotConst
,
2244 asyncness
: hir
::IsAsync
::NotAsync
,
2254 fn print_fn_header_info(&mut self, header
: hir
::FnHeader
) {
2255 self.print_constness(header
.constness
);
2257 match header
.asyncness
{
2258 hir
::IsAsync
::NotAsync
=> {}
2259 hir
::IsAsync
::Async(_
) => self.word_nbsp("async"),
2262 self.print_unsafety(header
.unsafety
);
2264 if header
.abi
!= Abi
::Rust
{
2265 self.word_nbsp("extern");
2266 self.word_nbsp(header
.abi
.to_string());
2272 fn print_constness(&mut self, s
: hir
::Constness
) {
2274 hir
::Constness
::NotConst
=> {}
2275 hir
::Constness
::Const
=> self.word_nbsp("const"),
2279 fn print_unsafety(&mut self, s
: hir
::Unsafety
) {
2281 hir
::Unsafety
::Normal
=> {}
2282 hir
::Unsafety
::Unsafe
=> self.word_nbsp("unsafe"),
2286 fn print_is_auto(&mut self, s
: hir
::IsAuto
) {
2288 hir
::IsAuto
::Yes
=> self.word_nbsp("auto"),
2289 hir
::IsAuto
::No
=> {}
2294 /// Does this expression require a semicolon to be treated
2295 /// as a statement? The negation of this: 'can this expression
2296 /// be used as a statement without a semicolon' -- is used
2297 /// as an early-bail-out in the parser so that, for instance,
2298 /// if true {...} else {...}
2300 /// isn't parsed as (if true {...} else {...} | x) | 5
2302 // Duplicated from `parse::classify`, but adapted for the HIR.
2303 fn expr_requires_semi_to_be_stmt(e
: &hir
::Expr
<'_
>) -> bool
{
2306 hir
::ExprKind
::If(..)
2307 | hir
::ExprKind
::Match(..)
2308 | hir
::ExprKind
::Block(..)
2309 | hir
::ExprKind
::Loop(..)
2313 /// This statement requires a semicolon after it.
2314 /// note that in one case (stmt_semi), we've already
2315 /// seen the semicolon, and thus don't need another.
2316 fn stmt_ends_with_semi(stmt
: &hir
::StmtKind
<'_
>) -> bool
{
2318 hir
::StmtKind
::Local(_
) => true,
2319 hir
::StmtKind
::Item(_
) => false,
2320 hir
::StmtKind
::Expr(e
) => expr_requires_semi_to_be_stmt(e
),
2321 hir
::StmtKind
::Semi(..) => false,
2325 fn bin_op_to_assoc_op(op
: hir
::BinOpKind
) -> AssocOp
{
2326 use crate::hir
::BinOpKind
::*;
2328 Add
=> AssocOp
::Add
,
2329 Sub
=> AssocOp
::Subtract
,
2330 Mul
=> AssocOp
::Multiply
,
2331 Div
=> AssocOp
::Divide
,
2332 Rem
=> AssocOp
::Modulus
,
2334 And
=> AssocOp
::LAnd
,
2337 BitXor
=> AssocOp
::BitXor
,
2338 BitAnd
=> AssocOp
::BitAnd
,
2339 BitOr
=> AssocOp
::BitOr
,
2340 Shl
=> AssocOp
::ShiftLeft
,
2341 Shr
=> AssocOp
::ShiftRight
,
2343 Eq
=> AssocOp
::Equal
,
2344 Lt
=> AssocOp
::Less
,
2345 Le
=> AssocOp
::LessEqual
,
2346 Ne
=> AssocOp
::NotEqual
,
2347 Ge
=> AssocOp
::GreaterEqual
,
2348 Gt
=> AssocOp
::Greater
,
2352 /// Expressions that syntactically contain an "exterior" struct literal, i.e., not surrounded by any
2353 /// parens or other delimiters, e.g., `X { y: 1 }`, `X { y: 1 }.method()`, `foo == X { y: 1 }` and
2354 /// `X { y: 1 } == foo` all do, but `(X { y: 1 }) == foo` does not.
2355 fn contains_exterior_struct_lit(value
: &hir
::Expr
<'_
>) -> bool
{
2357 hir
::ExprKind
::Struct(..) => true,
2359 hir
::ExprKind
::Assign(lhs
, rhs
, _
)
2360 | hir
::ExprKind
::AssignOp(_
, lhs
, rhs
)
2361 | hir
::ExprKind
::Binary(_
, lhs
, rhs
) => {
2362 // `X { y: 1 } + X { y: 2 }`
2363 contains_exterior_struct_lit(lhs
) || contains_exterior_struct_lit(rhs
)
2365 hir
::ExprKind
::Unary(_
, x
)
2366 | hir
::ExprKind
::Cast(x
, _
)
2367 | hir
::ExprKind
::Type(x
, _
)
2368 | hir
::ExprKind
::Field(x
, _
)
2369 | hir
::ExprKind
::Index(x
, _
, _
) => {
2370 // `&X { y: 1 }, X { y: 1 }.y`
2371 contains_exterior_struct_lit(x
)
2374 hir
::ExprKind
::MethodCall(_
, receiver
, ..) => {
2375 // `X { y: 1 }.bar(...)`
2376 contains_exterior_struct_lit(receiver
)