1 #![recursion_limit = "256"]
4 use rustc_ast
::util
::parser
::{self, AssocOp, Fixity}
;
5 use rustc_ast_pretty
::pp
::Breaks
::{Consistent, Inconsistent}
;
6 use rustc_ast_pretty
::pp
::{self, Breaks}
;
7 use rustc_ast_pretty
::pprust
::{Comments, PrintState}
;
9 use rustc_hir
::{GenericArg, GenericParam, GenericParamKind, Node, Term}
;
10 use rustc_hir
::{GenericBound, PatKind, RangeEnd, TraitBoundModifier}
;
11 use rustc_span
::source_map
::{SourceMap, Spanned}
;
12 use rustc_span
::symbol
::{kw, Ident, IdentPrinter, Symbol}
;
13 use rustc_span
::{self, FileName}
;
14 use rustc_target
::spec
::abi
::Abi
;
20 pub fn id_to_string(map
: &dyn rustc_hir
::intravisit
::Map
<'_
>, hir_id
: hir
::HirId
) -> String
{
21 to_string(&map
, |s
| s
.print_node(map
.find(hir_id
).unwrap()))
24 pub enum AnnNode
<'a
> {
26 Block(&'a hir
::Block
<'a
>),
27 Item(&'a hir
::Item
<'a
>),
29 Expr(&'a hir
::Expr
<'a
>),
30 Pat(&'a hir
::Pat
<'a
>),
31 Arm(&'a hir
::Arm
<'a
>),
36 TraitItem(hir
::TraitItemId
),
37 ImplItem(hir
::ImplItemId
),
38 ForeignItem(hir
::ForeignItemId
),
40 BodyParamPat(hir
::BodyId
, usize),
44 fn nested(&self, _state
: &mut State
<'_
>, _nested
: Nested
) {}
45 fn pre(&self, _state
: &mut State
<'_
>, _node
: AnnNode
<'_
>) {}
46 fn post(&self, _state
: &mut State
<'_
>, _node
: AnnNode
<'_
>) {}
50 impl PpAnn
for NoAnn {}
51 pub const NO_ANN
: &dyn PpAnn
= &NoAnn
;
53 /// Identical to the `PpAnn` implementation for `hir::Crate`,
54 /// except it avoids creating a dependency on the whole crate.
55 impl PpAnn
for &dyn rustc_hir
::intravisit
::Map
<'_
> {
56 fn nested(&self, state
: &mut State
<'_
>, nested
: Nested
) {
58 Nested
::Item(id
) => state
.print_item(self.item(id
)),
59 Nested
::TraitItem(id
) => state
.print_trait_item(self.trait_item(id
)),
60 Nested
::ImplItem(id
) => state
.print_impl_item(self.impl_item(id
)),
61 Nested
::ForeignItem(id
) => state
.print_foreign_item(self.foreign_item(id
)),
62 Nested
::Body(id
) => state
.print_expr(&self.body(id
).value
),
63 Nested
::BodyParamPat(id
, i
) => state
.print_pat(&self.body(id
).params
[i
].pat
),
68 pub struct State
<'a
> {
70 comments
: Option
<Comments
<'a
>>,
71 attrs
: &'a
dyn Fn(hir
::HirId
) -> &'a
[ast
::Attribute
],
72 ann
: &'
a (dyn PpAnn
+ 'a
),
76 pub fn print_node(&mut self, node
: Node
<'_
>) {
78 Node
::Param(a
) => self.print_param(&a
),
79 Node
::Item(a
) => self.print_item(&a
),
80 Node
::ForeignItem(a
) => self.print_foreign_item(&a
),
81 Node
::TraitItem(a
) => self.print_trait_item(a
),
82 Node
::ImplItem(a
) => self.print_impl_item(a
),
83 Node
::Variant(a
) => self.print_variant(&a
),
84 Node
::AnonConst(a
) => self.print_anon_const(&a
),
85 Node
::Expr(a
) => self.print_expr(&a
),
86 Node
::Stmt(a
) => self.print_stmt(&a
),
87 Node
::PathSegment(a
) => self.print_path_segment(&a
),
88 Node
::Ty(a
) => self.print_type(&a
),
89 Node
::TraitRef(a
) => self.print_trait_ref(&a
),
90 Node
::Binding(a
) | Node
::Pat(a
) => self.print_pat(&a
),
91 Node
::Arm(a
) => self.print_arm(&a
),
92 Node
::Infer(_
) => self.word("_"),
94 // Containing cbox, will be closed by print-block at `}`.
95 self.cbox(INDENT_UNIT
);
96 // Head-ibox, will be closed by print-block after `{`.
100 Node
::Lifetime(a
) => self.print_lifetime(&a
),
101 Node
::Visibility(a
) => self.print_visibility(&a
),
102 Node
::GenericParam(_
) => panic
!("cannot print Node::GenericParam"),
103 Node
::Field(_
) => panic
!("cannot print Node::Field"),
104 // These cases do not carry enough information in the
105 // `hir_map` to reconstruct their full structure for pretty
107 Node
::Ctor(..) => panic
!("cannot print isolated Ctor"),
108 Node
::Local(a
) => self.print_local_decl(&a
),
109 Node
::Crate(..) => panic
!("cannot print Crate"),
114 impl std
::ops
::Deref
for State
<'_
> {
115 type Target
= pp
::Printer
;
116 fn deref(&self) -> &Self::Target
{
121 impl std
::ops
::DerefMut
for State
<'_
> {
122 fn deref_mut(&mut self) -> &mut Self::Target
{
127 impl<'a
> PrintState
<'a
> for State
<'a
> {
128 fn comments(&mut self) -> &mut Option
<Comments
<'a
>> {
132 fn print_ident(&mut self, ident
: Ident
) {
133 self.word(IdentPrinter
::for_ast_ident(ident
, ident
.is_raw_guess()).to_string());
134 self.ann
.post(self, AnnNode
::Name(&ident
.name
))
137 fn print_generic_args(&mut self, _
: &ast
::GenericArgs
, _colons_before_params
: bool
) {
138 panic
!("AST generic args printed by HIR pretty-printer");
142 pub const INDENT_UNIT
: isize = 4;
144 /// Requires you to pass an input filename and reader so that
145 /// it can scan the input text for comments to copy forward.
146 pub fn print_crate
<'a
>(
148 krate
: &hir
::Mod
<'_
>,
151 attrs
: &'a
dyn Fn(hir
::HirId
) -> &'a
[ast
::Attribute
],
154 let mut s
= State
::new_from_input(sm
, filename
, input
, attrs
, ann
);
156 // When printing the AST, we sometimes need to inject `#[no_std]` here.
157 // Since you can't compile the HIR, it's not necessary.
159 s
.print_mod(krate
, (*attrs
)(hir
::CRATE_HIR_ID
));
160 s
.print_remaining_comments();
165 pub fn new_from_input(
169 attrs
: &'a
dyn Fn(hir
::HirId
) -> &'a
[ast
::Attribute
],
173 s
: pp
::Printer
::new(),
174 comments
: Some(Comments
::new(sm
, filename
, input
)),
180 fn attrs(&self, id
: hir
::HirId
) -> &'a
[ast
::Attribute
] {
185 pub fn to_string
<F
>(ann
: &dyn PpAnn
, f
: F
) -> String
187 F
: FnOnce(&mut State
<'_
>),
189 let mut printer
= State { s: pp::Printer::new(), comments: None, attrs: &|_| &[], ann }
;
194 pub fn visibility_qualified
<S
: Into
<Cow
<'
static, str>>>(vis
: &hir
::Visibility
<'_
>, w
: S
) -> String
{
195 to_string(NO_ANN
, |s
| {
196 s
.print_visibility(vis
);
201 pub fn generic_params_to_string(generic_params
: &[GenericParam
<'_
>]) -> String
{
202 to_string(NO_ANN
, |s
| s
.print_generic_params(generic_params
))
205 pub fn bounds_to_string
<'b
>(bounds
: impl IntoIterator
<Item
= &'b hir
::GenericBound
<'b
>>) -> String
{
206 to_string(NO_ANN
, |s
| s
.print_bounds("", bounds
))
209 pub fn ty_to_string(ty
: &hir
::Ty
<'_
>) -> String
{
210 to_string(NO_ANN
, |s
| s
.print_type(ty
))
213 pub fn path_segment_to_string(segment
: &hir
::PathSegment
<'_
>) -> String
{
214 to_string(NO_ANN
, |s
| s
.print_path_segment(segment
))
217 pub fn path_to_string(segment
: &hir
::Path
<'_
>) -> String
{
218 to_string(NO_ANN
, |s
| s
.print_path(segment
, false))
222 decl
: &hir
::FnDecl
<'_
>,
223 header
: hir
::FnHeader
,
224 name
: Option
<Symbol
>,
225 generics
: &hir
::Generics
<'_
>,
226 vis
: &hir
::Visibility
<'_
>,
228 body_id
: Option
<hir
::BodyId
>,
230 to_string(NO_ANN
, |s
| s
.print_fn(decl
, header
, name
, generics
, vis
, arg_names
, body_id
))
233 pub fn enum_def_to_string(
234 enum_definition
: &hir
::EnumDef
<'_
>,
235 generics
: &hir
::Generics
<'_
>,
237 span
: rustc_span
::Span
,
238 visibility
: &hir
::Visibility
<'_
>,
240 to_string(NO_ANN
, |s
| s
.print_enum_def(enum_definition
, generics
, name
, span
, visibility
))
244 pub fn bclose_maybe_open(&mut self, span
: rustc_span
::Span
, close_box
: bool
) {
245 self.maybe_print_comment(span
.hi());
246 self.break_offset_if_not_bol(1, -(INDENT_UNIT
as isize));
249 self.end(); // close the outer-box
253 pub fn bclose(&mut self, span
: rustc_span
::Span
) {
254 self.bclose_maybe_open(span
, true)
257 pub fn commasep_cmnt
<T
, F
, G
>(&mut self, b
: Breaks
, elts
: &[T
], mut op
: F
, mut get_span
: G
)
259 F
: FnMut(&mut State
<'_
>, &T
),
260 G
: FnMut(&T
) -> rustc_span
::Span
,
263 let len
= elts
.len();
266 self.maybe_print_comment(get_span(elt
).hi());
271 self.maybe_print_trailing_comment(get_span(elt
), Some(get_span(&elts
[i
]).hi()));
272 self.space_if_not_bol();
278 pub fn commasep_exprs(&mut self, b
: Breaks
, exprs
: &[hir
::Expr
<'_
>]) {
279 self.commasep_cmnt(b
, exprs
, |s
, e
| s
.print_expr(&e
), |e
| e
.span
)
282 pub fn print_mod(&mut self, _mod
: &hir
::Mod
<'_
>, attrs
: &[ast
::Attribute
]) {
283 self.print_inner_attributes(attrs
);
284 for &item_id
in _mod
.item_ids
{
285 self.ann
.nested(self, Nested
::Item(item_id
));
289 pub fn print_opt_lifetime(&mut self, lifetime
: &hir
::Lifetime
) {
290 if !lifetime
.is_elided() {
291 self.print_lifetime(lifetime
);
296 pub fn print_type(&mut self, ty
: &hir
::Ty
<'_
>) {
297 self.maybe_print_comment(ty
.span
.lo());
300 hir
::TyKind
::Slice(ref ty
) => {
302 self.print_type(&ty
);
305 hir
::TyKind
::Ptr(ref mt
) => {
307 self.print_mt(mt
, true);
309 hir
::TyKind
::Rptr(ref lifetime
, ref mt
) => {
311 self.print_opt_lifetime(lifetime
);
312 self.print_mt(mt
, false);
314 hir
::TyKind
::Never
=> {
317 hir
::TyKind
::Tup(ref elts
) => {
319 self.commasep(Inconsistent
, &elts
, |s
, ty
| s
.print_type(&ty
));
325 hir
::TyKind
::BareFn(ref f
) => {
335 hir
::TyKind
::OpaqueDef(..) => self.word("/*impl Trait*/"),
336 hir
::TyKind
::Path(ref qpath
) => self.print_qpath(qpath
, false),
337 hir
::TyKind
::TraitObject(bounds
, ref lifetime
, syntax
) => {
338 if syntax
== ast
::TraitObjectSyntax
::Dyn
{
339 self.word_space("dyn");
341 let mut first
= true;
342 for bound
in bounds
{
347 self.word_space("+");
349 self.print_poly_trait_ref(bound
);
351 if !lifetime
.is_elided() {
353 self.word_space("+");
354 self.print_lifetime(lifetime
);
357 hir
::TyKind
::Array(ref ty
, ref length
) => {
359 self.print_type(&ty
);
361 self.print_array_length(length
);
364 hir
::TyKind
::Typeof(ref e
) => {
365 self.word("typeof(");
366 self.print_anon_const(e
);
369 hir
::TyKind
::Err
=> {
371 self.word("/*ERROR*/");
374 hir
::TyKind
::Infer
=> {
381 pub fn print_foreign_item(&mut self, item
: &hir
::ForeignItem
<'_
>) {
382 self.hardbreak_if_not_bol();
383 self.maybe_print_comment(item
.span
.lo());
384 self.print_outer_attributes(self.attrs(item
.hir_id()));
386 hir
::ForeignItemKind
::Fn(ref decl
, ref arg_names
, ref generics
) => {
391 unsafety
: hir
::Unsafety
::Normal
,
392 constness
: hir
::Constness
::NotConst
,
394 asyncness
: hir
::IsAsync
::NotAsync
,
396 Some(item
.ident
.name
),
402 self.end(); // end head-ibox
404 self.end() // end the outer fn box
406 hir
::ForeignItemKind
::Static(ref t
, m
) => {
407 self.head(visibility_qualified(&item
.vis
, "static"));
408 if m
== hir
::Mutability
::Mut
{
409 self.word_space("mut");
411 self.print_ident(item
.ident
);
412 self.word_space(":");
415 self.end(); // end the head-ibox
416 self.end() // end the outer cbox
418 hir
::ForeignItemKind
::Type
=> {
419 self.head(visibility_qualified(&item
.vis
, "type"));
420 self.print_ident(item
.ident
);
422 self.end(); // end the head-ibox
423 self.end() // end the outer cbox
428 fn print_associated_const(
432 default: Option
<hir
::BodyId
>,
433 vis
: &hir
::Visibility
<'_
>,
435 self.word(visibility_qualified(vis
, ""));
436 self.word_space("const");
437 self.print_ident(ident
);
438 self.word_space(":");
440 if let Some(expr
) = default {
442 self.word_space("=");
443 self.ann
.nested(self, Nested
::Body(expr
));
448 fn print_associated_type(
451 generics
: &hir
::Generics
<'_
>,
452 bounds
: Option
<hir
::GenericBounds
<'_
>>,
453 ty
: Option
<&hir
::Ty
<'_
>>,
455 self.word_space("type");
456 self.print_ident(ident
);
457 self.print_generic_params(&generics
.params
);
458 if let Some(bounds
) = bounds
{
459 self.print_bounds(":", bounds
);
461 self.print_where_clause(&generics
.where_clause
);
462 if let Some(ty
) = ty
{
464 self.word_space("=");
472 item
: &hir
::Item
<'_
>,
473 generics
: &hir
::Generics
<'_
>,
474 inner
: impl Fn(&mut Self),
476 self.head(visibility_qualified(&item
.vis
, "type"));
477 self.print_ident(item
.ident
);
478 self.print_generic_params(&generics
.params
);
479 self.end(); // end the inner ibox
481 self.print_where_clause(&generics
.where_clause
);
485 self.end(); // end the outer ibox
488 /// Pretty-print an item
489 pub fn print_item(&mut self, item
: &hir
::Item
<'_
>) {
490 self.hardbreak_if_not_bol();
491 self.maybe_print_comment(item
.span
.lo());
492 let attrs
= self.attrs(item
.hir_id());
493 self.print_outer_attributes(attrs
);
494 self.ann
.pre(self, AnnNode
::Item(item
));
496 hir
::ItemKind
::ExternCrate(orig_name
) => {
497 self.head(visibility_qualified(&item
.vis
, "extern crate"));
498 if let Some(orig_name
) = orig_name
{
499 self.print_name(orig_name
);
504 self.print_ident(item
.ident
);
506 self.end(); // end inner head-block
507 self.end(); // end outer head-block
509 hir
::ItemKind
::Use(ref path
, kind
) => {
510 self.head(visibility_qualified(&item
.vis
, "use"));
511 self.print_path(path
, false);
514 hir
::UseKind
::Single
=> {
515 if path
.segments
.last().unwrap().ident
!= item
.ident
{
517 self.word_space("as");
518 self.print_ident(item
.ident
);
522 hir
::UseKind
::Glob
=> self.word("::*;"),
523 hir
::UseKind
::ListStem
=> self.word("::{};"),
525 self.end(); // end inner head-block
526 self.end(); // end outer head-block
528 hir
::ItemKind
::Static(ref ty
, m
, expr
) => {
529 self.head(visibility_qualified(&item
.vis
, "static"));
530 if m
== hir
::Mutability
::Mut
{
531 self.word_space("mut");
533 self.print_ident(item
.ident
);
534 self.word_space(":");
535 self.print_type(&ty
);
537 self.end(); // end the head-ibox
539 self.word_space("=");
540 self.ann
.nested(self, Nested
::Body(expr
));
542 self.end(); // end the outer cbox
544 hir
::ItemKind
::Const(ref ty
, expr
) => {
545 self.head(visibility_qualified(&item
.vis
, "const"));
546 self.print_ident(item
.ident
);
547 self.word_space(":");
548 self.print_type(&ty
);
550 self.end(); // end the head-ibox
552 self.word_space("=");
553 self.ann
.nested(self, Nested
::Body(expr
));
555 self.end(); // end the outer cbox
557 hir
::ItemKind
::Fn(ref sig
, ref param_names
, body
) => {
562 Some(item
.ident
.name
),
569 self.end(); // need to close a box
570 self.end(); // need to close a box
571 self.ann
.nested(self, Nested
::Body(body
));
573 hir
::ItemKind
::Macro(ref macro_def
, _
) => {
574 self.print_mac_def(macro_def
, &item
.ident
, item
.span
, |state
| {
575 state
.print_visibility(&item
.vis
)
578 hir
::ItemKind
::Mod(ref _mod
) => {
579 self.head(visibility_qualified(&item
.vis
, "mod"));
580 self.print_ident(item
.ident
);
583 self.print_mod(_mod
, attrs
);
584 self.bclose(item
.span
);
586 hir
::ItemKind
::ForeignMod { abi, items }
=> {
588 self.word_nbsp(abi
.to_string());
590 self.print_inner_attributes(self.attrs(item
.hir_id()));
592 self.ann
.nested(self, Nested
::ForeignItem(item
.id
));
594 self.bclose(item
.span
);
596 hir
::ItemKind
::GlobalAsm(ref asm
) => {
597 self.head(visibility_qualified(&item
.vis
, "global_asm!"));
598 self.print_inline_asm(asm
);
601 hir
::ItemKind
::TyAlias(ref ty
, ref generics
) => {
602 self.print_item_type(item
, &generics
, |state
| {
603 state
.word_space("=");
604 state
.print_type(&ty
);
607 hir
::ItemKind
::OpaqueTy(ref opaque_ty
) => {
608 self.print_item_type(item
, &opaque_ty
.generics
, |state
| {
609 let mut real_bounds
= Vec
::with_capacity(opaque_ty
.bounds
.len());
610 for b
in opaque_ty
.bounds
.iter() {
611 if let GenericBound
::Trait(ref ptr
, hir
::TraitBoundModifier
::Maybe
) = *b
{
613 state
.word_space("for ?");
614 state
.print_trait_ref(&ptr
.trait_ref
);
619 state
.print_bounds("= impl", real_bounds
);
622 hir
::ItemKind
::Enum(ref enum_definition
, ref params
) => {
623 self.print_enum_def(enum_definition
, params
, item
.ident
.name
, item
.span
, &item
.vis
);
625 hir
::ItemKind
::Struct(ref struct_def
, ref generics
) => {
626 self.head(visibility_qualified(&item
.vis
, "struct"));
627 self.print_struct(struct_def
, generics
, item
.ident
.name
, item
.span
, true);
629 hir
::ItemKind
::Union(ref struct_def
, ref generics
) => {
630 self.head(visibility_qualified(&item
.vis
, "union"));
631 self.print_struct(struct_def
, generics
, item
.ident
.name
, item
.span
, true);
633 hir
::ItemKind
::Impl(hir
::Impl
{
645 self.print_visibility(&item
.vis
);
646 self.print_defaultness(defaultness
);
647 self.print_unsafety(unsafety
);
648 self.word_nbsp("impl");
650 if !generics
.params
.is_empty() {
651 self.print_generic_params(&generics
.params
);
655 if constness
== hir
::Constness
::Const
{
656 self.word_nbsp("const");
659 if let hir
::ImplPolarity
::Negative(_
) = polarity
{
663 if let Some(ref t
) = of_trait
{
664 self.print_trait_ref(t
);
666 self.word_space("for");
669 self.print_type(&self_ty
);
670 self.print_where_clause(&generics
.where_clause
);
674 self.print_inner_attributes(attrs
);
675 for impl_item
in items
{
676 self.ann
.nested(self, Nested
::ImplItem(impl_item
.id
));
678 self.bclose(item
.span
);
680 hir
::ItemKind
::Trait(is_auto
, unsafety
, ref generics
, ref bounds
, trait_items
) => {
682 self.print_visibility(&item
.vis
);
683 self.print_is_auto(is_auto
);
684 self.print_unsafety(unsafety
);
685 self.word_nbsp("trait");
686 self.print_ident(item
.ident
);
687 self.print_generic_params(&generics
.params
);
688 let mut real_bounds
= Vec
::with_capacity(bounds
.len());
689 for b
in bounds
.iter() {
690 if let GenericBound
::Trait(ref ptr
, hir
::TraitBoundModifier
::Maybe
) = *b
{
692 self.word_space("for ?");
693 self.print_trait_ref(&ptr
.trait_ref
);
698 self.print_bounds(":", real_bounds
);
699 self.print_where_clause(&generics
.where_clause
);
702 for trait_item
in trait_items
{
703 self.ann
.nested(self, Nested
::TraitItem(trait_item
.id
));
705 self.bclose(item
.span
);
707 hir
::ItemKind
::TraitAlias(ref generics
, ref bounds
) => {
708 self.head(visibility_qualified(&item
.vis
, "trait"));
709 self.print_ident(item
.ident
);
710 self.print_generic_params(&generics
.params
);
711 let mut real_bounds
= Vec
::with_capacity(bounds
.len());
712 // FIXME(durka) this seems to be some quite outdated syntax
713 for b
in bounds
.iter() {
714 if let GenericBound
::Trait(ref ptr
, hir
::TraitBoundModifier
::Maybe
) = *b
{
716 self.word_space("for ?");
717 self.print_trait_ref(&ptr
.trait_ref
);
723 self.print_bounds("=", real_bounds
);
724 self.print_where_clause(&generics
.where_clause
);
726 self.end(); // end inner head-block
727 self.end(); // end outer head-block
730 self.ann
.post(self, AnnNode
::Item(item
))
733 pub fn print_trait_ref(&mut self, t
: &hir
::TraitRef
<'_
>) {
734 self.print_path(&t
.path
, false)
737 fn print_formal_generic_params(&mut self, generic_params
: &[hir
::GenericParam
<'_
>]) {
738 if !generic_params
.is_empty() {
740 self.print_generic_params(generic_params
);
745 fn print_poly_trait_ref(&mut self, t
: &hir
::PolyTraitRef
<'_
>) {
746 self.print_formal_generic_params(&t
.bound_generic_params
);
747 self.print_trait_ref(&t
.trait_ref
)
750 pub fn print_enum_def(
752 enum_definition
: &hir
::EnumDef
<'_
>,
753 generics
: &hir
::Generics
<'_
>,
755 span
: rustc_span
::Span
,
756 visibility
: &hir
::Visibility
<'_
>,
758 self.head(visibility_qualified(visibility
, "enum"));
759 self.print_name(name
);
760 self.print_generic_params(&generics
.params
);
761 self.print_where_clause(&generics
.where_clause
);
763 self.print_variants(&enum_definition
.variants
, span
)
766 pub fn print_variants(&mut self, variants
: &[hir
::Variant
<'_
>], span
: rustc_span
::Span
) {
769 self.space_if_not_bol();
770 self.maybe_print_comment(v
.span
.lo());
771 self.print_outer_attributes(self.attrs(v
.id
));
772 self.ibox(INDENT_UNIT
);
773 self.print_variant(v
);
776 self.maybe_print_trailing_comment(v
.span
, None
);
781 pub fn print_visibility(&mut self, vis
: &hir
::Visibility
<'_
>) {
783 hir
::VisibilityKind
::Public
=> self.word_nbsp("pub"),
784 hir
::VisibilityKind
::Crate(ast
::CrateSugar
::JustCrate
) => self.word_nbsp("crate"),
785 hir
::VisibilityKind
::Crate(ast
::CrateSugar
::PubCrate
) => self.word_nbsp("pub(crate)"),
786 hir
::VisibilityKind
::Restricted { ref path, .. }
=> {
788 if path
.segments
.len() == 1 && path
.segments
[0].ident
.name
== kw
::Super
{
789 // Special case: `super` can print like `pub(super)`.
792 // Everything else requires `in` at present.
793 self.word_nbsp("in");
794 self.print_path(path
, false);
798 hir
::VisibilityKind
::Inherited
=> (),
802 pub fn print_defaultness(&mut self, defaultness
: hir
::Defaultness
) {
804 hir
::Defaultness
::Default { .. }
=> self.word_nbsp("default"),
805 hir
::Defaultness
::Final
=> (),
811 struct_def
: &hir
::VariantData
<'_
>,
812 generics
: &hir
::Generics
<'_
>,
814 span
: rustc_span
::Span
,
815 print_finalizer
: bool
,
817 self.print_name(name
);
818 self.print_generic_params(&generics
.params
);
820 hir
::VariantData
::Tuple(..) | hir
::VariantData
::Unit(..) => {
821 if let hir
::VariantData
::Tuple(..) = struct_def
{
823 self.commasep(Inconsistent
, struct_def
.fields(), |s
, field
| {
824 s
.maybe_print_comment(field
.span
.lo());
825 s
.print_outer_attributes(s
.attrs(field
.hir_id
));
826 s
.print_visibility(&field
.vis
);
827 s
.print_type(&field
.ty
)
831 self.print_where_clause(&generics
.where_clause
);
836 self.end() // close the outer-box
838 hir
::VariantData
::Struct(..) => {
839 self.print_where_clause(&generics
.where_clause
);
842 self.hardbreak_if_not_bol();
844 for field
in struct_def
.fields() {
845 self.hardbreak_if_not_bol();
846 self.maybe_print_comment(field
.span
.lo());
847 self.print_outer_attributes(self.attrs(field
.hir_id
));
848 self.print_visibility(&field
.vis
);
849 self.print_ident(field
.ident
);
851 self.print_type(&field
.ty
);
860 pub fn print_variant(&mut self, v
: &hir
::Variant
<'_
>) {
862 let generics
= hir
::Generics
::empty();
863 self.print_struct(&v
.data
, &generics
, v
.ident
.name
, v
.span
, false);
864 if let Some(ref d
) = v
.disr_expr
{
866 self.word_space("=");
867 self.print_anon_const(d
);
870 pub fn print_method_sig(
874 generics
: &hir
::Generics
<'_
>,
875 vis
: &hir
::Visibility
<'_
>,
877 body_id
: Option
<hir
::BodyId
>,
879 self.print_fn(&m
.decl
, m
.header
, Some(ident
.name
), generics
, vis
, arg_names
, body_id
)
882 pub fn print_trait_item(&mut self, ti
: &hir
::TraitItem
<'_
>) {
883 self.ann
.pre(self, AnnNode
::SubItem(ti
.hir_id()));
884 self.hardbreak_if_not_bol();
885 self.maybe_print_comment(ti
.span
.lo());
886 self.print_outer_attributes(self.attrs(ti
.hir_id()));
888 hir
::TraitItemKind
::Const(ref ty
, default) => {
890 Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited }
;
891 self.print_associated_const(ti
.ident
, &ty
, default, &vis
);
893 hir
::TraitItemKind
::Fn(ref sig
, hir
::TraitFn
::Required(ref arg_names
)) => {
895 Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited }
;
896 self.print_method_sig(ti
.ident
, sig
, &ti
.generics
, &vis
, arg_names
, None
);
899 hir
::TraitItemKind
::Fn(ref sig
, hir
::TraitFn
::Provided(body
)) => {
901 Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited }
;
903 self.print_method_sig(ti
.ident
, sig
, &ti
.generics
, &vis
, &[], Some(body
));
905 self.end(); // need to close a box
906 self.end(); // need to close a box
907 self.ann
.nested(self, Nested
::Body(body
));
909 hir
::TraitItemKind
::Type(ref bounds
, ref default) => {
910 self.print_associated_type(
914 default.as_ref().map(|ty
| &**ty
),
918 self.ann
.post(self, AnnNode
::SubItem(ti
.hir_id()))
921 pub fn print_impl_item(&mut self, ii
: &hir
::ImplItem
<'_
>) {
922 self.ann
.pre(self, AnnNode
::SubItem(ii
.hir_id()));
923 self.hardbreak_if_not_bol();
924 self.maybe_print_comment(ii
.span
.lo());
925 self.print_outer_attributes(self.attrs(ii
.hir_id()));
928 hir
::ImplItemKind
::Const(ref ty
, expr
) => {
929 self.print_associated_const(ii
.ident
, &ty
, Some(expr
), &ii
.vis
);
931 hir
::ImplItemKind
::Fn(ref sig
, body
) => {
933 self.print_method_sig(ii
.ident
, sig
, &ii
.generics
, &ii
.vis
, &[], Some(body
));
935 self.end(); // need to close a box
936 self.end(); // need to close a box
937 self.ann
.nested(self, Nested
::Body(body
));
939 hir
::ImplItemKind
::TyAlias(ref ty
) => {
940 self.print_associated_type(ii
.ident
, &ii
.generics
, None
, Some(ty
));
943 self.ann
.post(self, AnnNode
::SubItem(ii
.hir_id()))
946 pub fn print_local(&mut self, init
: Option
<&hir
::Expr
<'_
>>, decl
: impl Fn(&mut Self)) {
947 self.space_if_not_bol();
948 self.ibox(INDENT_UNIT
);
949 self.word_nbsp("let");
951 self.ibox(INDENT_UNIT
);
955 if let Some(ref init
) = init
{
957 self.word_space("=");
958 self.print_expr(&init
);
963 pub fn print_stmt(&mut self, st
: &hir
::Stmt
<'_
>) {
964 self.maybe_print_comment(st
.span
.lo());
966 hir
::StmtKind
::Local(ref loc
) => {
967 self.print_local(loc
.init
, |this
| this
.print_local_decl(&loc
));
969 hir
::StmtKind
::Item(item
) => self.ann
.nested(self, Nested
::Item(item
)),
970 hir
::StmtKind
::Expr(ref expr
) => {
971 self.space_if_not_bol();
972 self.print_expr(&expr
);
974 hir
::StmtKind
::Semi(ref expr
) => {
975 self.space_if_not_bol();
976 self.print_expr(&expr
);
980 if stmt_ends_with_semi(&st
.kind
) {
983 self.maybe_print_trailing_comment(st
.span
, None
)
986 pub fn print_block(&mut self, blk
: &hir
::Block
<'_
>) {
987 self.print_block_with_attrs(blk
, &[])
990 pub fn print_block_unclosed(&mut self, blk
: &hir
::Block
<'_
>) {
991 self.print_block_maybe_unclosed(blk
, &[], false)
994 pub fn print_block_with_attrs(&mut self, blk
: &hir
::Block
<'_
>, attrs
: &[ast
::Attribute
]) {
995 self.print_block_maybe_unclosed(blk
, attrs
, true)
998 pub fn print_block_maybe_unclosed(
1000 blk
: &hir
::Block
<'_
>,
1001 attrs
: &[ast
::Attribute
],
1005 hir
::BlockCheckMode
::UnsafeBlock(..) => self.word_space("unsafe"),
1006 hir
::BlockCheckMode
::DefaultBlock
=> (),
1008 self.maybe_print_comment(blk
.span
.lo());
1009 self.ann
.pre(self, AnnNode
::Block(blk
));
1012 self.print_inner_attributes(attrs
);
1014 for st
in blk
.stmts
{
1015 self.print_stmt(st
);
1017 if let Some(ref expr
) = blk
.expr
{
1018 self.space_if_not_bol();
1019 self.print_expr(&expr
);
1020 self.maybe_print_trailing_comment(expr
.span
, Some(blk
.span
.hi()));
1022 self.bclose_maybe_open(blk
.span
, close_box
);
1023 self.ann
.post(self, AnnNode
::Block(blk
))
1026 fn print_else(&mut self, els
: Option
<&hir
::Expr
<'_
>>) {
1027 if let Some(els_inner
) = els
{
1028 match els_inner
.kind
{
1029 // Another `else if` block.
1030 hir
::ExprKind
::If(ref i
, ref then
, ref e
) => {
1031 self.cbox(INDENT_UNIT
- 1);
1033 self.word(" else if ");
1034 self.print_expr_as_cond(&i
);
1036 self.print_expr(&then
);
1037 self.print_else(e
.as_ref().map(|e
| &**e
))
1039 // Final `else` block.
1040 hir
::ExprKind
::Block(ref b
, _
) => {
1041 self.cbox(INDENT_UNIT
- 1);
1043 self.word(" else ");
1044 self.print_block(&b
)
1046 // Constraints would be great here!
1048 panic
!("print_if saw if with weird alternative");
1056 test
: &hir
::Expr
<'_
>,
1057 blk
: &hir
::Expr
<'_
>,
1058 elseopt
: Option
<&hir
::Expr
<'_
>>,
1061 self.print_expr_as_cond(test
);
1063 self.print_expr(blk
);
1064 self.print_else(elseopt
)
1067 pub fn print_array_length(&mut self, len
: &hir
::ArrayLen
) {
1069 hir
::ArrayLen
::Infer(_
, _
) => self.word("_"),
1070 hir
::ArrayLen
::Body(ct
) => self.print_anon_const(ct
),
1074 pub fn print_anon_const(&mut self, constant
: &hir
::AnonConst
) {
1075 self.ann
.nested(self, Nested
::Body(constant
.body
))
1078 fn print_call_post(&mut self, args
: &[hir
::Expr
<'_
>]) {
1080 self.commasep_exprs(Inconsistent
, args
);
1084 fn print_expr_maybe_paren(&mut self, expr
: &hir
::Expr
<'_
>, prec
: i8) {
1085 self.print_expr_cond_paren(expr
, expr
.precedence().order() < prec
)
1088 /// Prints an expr using syntax that's acceptable in a condition position, such as the `cond` in
1089 /// `if cond { ... }`.
1090 pub fn print_expr_as_cond(&mut self, expr
: &hir
::Expr
<'_
>) {
1091 self.print_expr_cond_paren(expr
, Self::cond_needs_par(expr
))
1094 /// Prints `expr` or `(expr)` when `needs_par` holds.
1095 fn print_expr_cond_paren(&mut self, expr
: &hir
::Expr
<'_
>, needs_par
: bool
) {
1099 if let hir
::ExprKind
::DropTemps(ref actual_expr
) = expr
.kind
{
1100 self.print_expr(actual_expr
);
1102 self.print_expr(expr
);
1109 /// Print a `let pat = expr` expression.
1110 fn print_let(&mut self, pat
: &hir
::Pat
<'_
>, ty
: Option
<&hir
::Ty
<'_
>>, init
: &hir
::Expr
<'_
>) {
1111 self.word_space("let");
1112 self.print_pat(pat
);
1113 if let Some(ty
) = ty
{
1114 self.word_space(":");
1115 self.print_type(ty
);
1118 self.word_space("=");
1119 let npals
= || parser
::needs_par_as_let_scrutinee(init
.precedence().order());
1120 self.print_expr_cond_paren(init
, Self::cond_needs_par(init
) || npals())
1123 // Does `expr` need parentheses when printed in a condition position?
1125 // These cases need parens due to the parse error observed in #26461: `if return {}`
1126 // parses as the erroneous construct `if (return {})`, not `if (return) {}`.
1127 fn cond_needs_par(expr
: &hir
::Expr
<'_
>) -> bool
{
1129 hir
::ExprKind
::Break(..) | hir
::ExprKind
::Closure(..) | hir
::ExprKind
::Ret(..) => true,
1130 _
=> contains_exterior_struct_lit(expr
),
1134 fn print_expr_vec(&mut self, exprs
: &[hir
::Expr
<'_
>]) {
1135 self.ibox(INDENT_UNIT
);
1137 self.commasep_exprs(Inconsistent
, exprs
);
1142 fn print_expr_anon_const(&mut self, anon_const
: &hir
::AnonConst
) {
1143 self.ibox(INDENT_UNIT
);
1144 self.word_space("const");
1145 self.print_anon_const(anon_const
);
1149 fn print_expr_repeat(&mut self, element
: &hir
::Expr
<'_
>, count
: &hir
::ArrayLen
) {
1150 self.ibox(INDENT_UNIT
);
1152 self.print_expr(element
);
1153 self.word_space(";");
1154 self.print_array_length(count
);
1159 fn print_expr_struct(
1161 qpath
: &hir
::QPath
<'_
>,
1162 fields
: &[hir
::ExprField
<'_
>],
1163 wth
: &Option
<&hir
::Expr
<'_
>>,
1165 self.print_qpath(qpath
, true);
1171 s
.ibox(INDENT_UNIT
);
1172 if !field
.is_shorthand
{
1173 s
.print_ident(field
.ident
);
1176 s
.print_expr(&field
.expr
);
1183 self.ibox(INDENT_UNIT
);
1184 if !fields
.is_empty() {
1189 self.print_expr(&expr
);
1193 if !fields
.is_empty() {
1201 fn print_expr_tup(&mut self, exprs
: &[hir
::Expr
<'_
>]) {
1203 self.commasep_exprs(Inconsistent
, exprs
);
1204 if exprs
.len() == 1 {
1210 fn print_expr_call(&mut self, func
: &hir
::Expr
<'_
>, args
: &[hir
::Expr
<'_
>]) {
1211 let prec
= match func
.kind
{
1212 hir
::ExprKind
::Field(..) => parser
::PREC_FORCE_PAREN
,
1213 _
=> parser
::PREC_POSTFIX
,
1216 self.print_expr_maybe_paren(func
, prec
);
1217 self.print_call_post(args
)
1220 fn print_expr_method_call(&mut self, segment
: &hir
::PathSegment
<'_
>, args
: &[hir
::Expr
<'_
>]) {
1221 let base_args
= &args
[1..];
1222 self.print_expr_maybe_paren(&args
[0], parser
::PREC_POSTFIX
);
1224 self.print_ident(segment
.ident
);
1226 let generic_args
= segment
.args();
1227 if !generic_args
.args
.is_empty() || !generic_args
.bindings
.is_empty() {
1228 self.print_generic_args(generic_args
, segment
.infer_args
, true);
1231 self.print_call_post(base_args
)
1234 fn print_expr_binary(&mut self, op
: hir
::BinOp
, lhs
: &hir
::Expr
<'_
>, rhs
: &hir
::Expr
<'_
>) {
1235 let assoc_op
= bin_op_to_assoc_op(op
.node
);
1236 let prec
= assoc_op
.precedence() as i8;
1237 let fixity
= assoc_op
.fixity();
1239 let (left_prec
, right_prec
) = match fixity
{
1240 Fixity
::Left
=> (prec
, prec
+ 1),
1241 Fixity
::Right
=> (prec
+ 1, prec
),
1242 Fixity
::None
=> (prec
+ 1, prec
+ 1),
1245 let left_prec
= match (&lhs
.kind
, op
.node
) {
1246 // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
1247 // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
1248 // of `(x as i32) < ...`. We need to convince it _not_ to do that.
1249 (&hir
::ExprKind
::Cast { .. }
, hir
::BinOpKind
::Lt
| hir
::BinOpKind
::Shl
) => {
1250 parser
::PREC_FORCE_PAREN
1252 (&hir
::ExprKind
::Let { .. }
, _
) if !parser
::needs_par_as_let_scrutinee(prec
) => {
1253 parser
::PREC_FORCE_PAREN
1258 self.print_expr_maybe_paren(lhs
, left_prec
);
1260 self.word_space(op
.node
.as_str());
1261 self.print_expr_maybe_paren(rhs
, right_prec
)
1264 fn print_expr_unary(&mut self, op
: hir
::UnOp
, expr
: &hir
::Expr
<'_
>) {
1265 self.word(op
.as_str());
1266 self.print_expr_maybe_paren(expr
, parser
::PREC_PREFIX
)
1269 fn print_expr_addr_of(
1271 kind
: hir
::BorrowKind
,
1272 mutability
: hir
::Mutability
,
1273 expr
: &hir
::Expr
<'_
>,
1277 hir
::BorrowKind
::Ref
=> self.print_mutability(mutability
, false),
1278 hir
::BorrowKind
::Raw
=> {
1279 self.word_nbsp("raw");
1280 self.print_mutability(mutability
, true);
1283 self.print_expr_maybe_paren(expr
, parser
::PREC_PREFIX
)
1286 fn print_literal(&mut self, lit
: &hir
::Lit
) {
1287 self.maybe_print_comment(lit
.span
.lo());
1288 self.word(lit
.node
.to_lit_token().to_string())
1291 fn print_inline_asm(&mut self, asm
: &hir
::InlineAsm
<'_
>) {
1294 Operand(&'a hir
::InlineAsmOperand
<'a
>),
1295 Options(ast
::InlineAsmOptions
),
1299 vec
![AsmArg
::Template(ast
::InlineAsmTemplatePiece
::to_string(&asm
.template
))];
1300 args
.extend(asm
.operands
.iter().map(|(o
, _
)| AsmArg
::Operand(o
)));
1301 if !asm
.options
.is_empty() {
1302 args
.push(AsmArg
::Options(asm
.options
));
1306 self.commasep(Consistent
, &args
, |s
, arg
| match arg
{
1307 AsmArg
::Template(template
) => s
.print_string(&template
, ast
::StrStyle
::Cooked
),
1308 AsmArg
::Operand(op
) => match op
{
1309 hir
::InlineAsmOperand
::In { reg, expr }
=> {
1312 s
.word(format
!("{}", reg
));
1317 hir
::InlineAsmOperand
::Out { reg, late, expr }
=> {
1318 s
.word(if *late { "lateout" }
else { "out" }
);
1320 s
.word(format
!("{}", reg
));
1324 Some(expr
) => s
.print_expr(expr
),
1325 None
=> s
.word("_"),
1328 hir
::InlineAsmOperand
::InOut { reg, late, expr }
=> {
1329 s
.word(if *late { "inlateout" }
else { "inout" }
);
1331 s
.word(format
!("{}", reg
));
1336 hir
::InlineAsmOperand
::SplitInOut { reg, late, in_expr, out_expr }
=> {
1337 s
.word(if *late { "inlateout" }
else { "inout" }
);
1339 s
.word(format
!("{}", reg
));
1342 s
.print_expr(in_expr
);
1346 Some(out_expr
) => s
.print_expr(out_expr
),
1347 None
=> s
.word("_"),
1350 hir
::InlineAsmOperand
::Const { anon_const }
=> {
1353 s
.print_anon_const(anon_const
);
1355 hir
::InlineAsmOperand
::Sym { expr }
=> {
1361 AsmArg
::Options(opts
) => {
1364 let mut options
= vec
![];
1365 if opts
.contains(ast
::InlineAsmOptions
::PURE
) {
1366 options
.push("pure");
1368 if opts
.contains(ast
::InlineAsmOptions
::NOMEM
) {
1369 options
.push("nomem");
1371 if opts
.contains(ast
::InlineAsmOptions
::READONLY
) {
1372 options
.push("readonly");
1374 if opts
.contains(ast
::InlineAsmOptions
::PRESERVES_FLAGS
) {
1375 options
.push("preserves_flags");
1377 if opts
.contains(ast
::InlineAsmOptions
::NORETURN
) {
1378 options
.push("noreturn");
1380 if opts
.contains(ast
::InlineAsmOptions
::NOSTACK
) {
1381 options
.push("nostack");
1383 if opts
.contains(ast
::InlineAsmOptions
::ATT_SYNTAX
) {
1384 options
.push("att_syntax");
1386 if opts
.contains(ast
::InlineAsmOptions
::RAW
) {
1387 options
.push("raw");
1389 if opts
.contains(ast
::InlineAsmOptions
::MAY_UNWIND
) {
1390 options
.push("may_unwind");
1392 s
.commasep(Inconsistent
, &options
, |s
, &opt
| {
1401 pub fn print_expr(&mut self, expr
: &hir
::Expr
<'_
>) {
1402 self.maybe_print_comment(expr
.span
.lo());
1403 self.print_outer_attributes(self.attrs(expr
.hir_id
));
1404 self.ibox(INDENT_UNIT
);
1405 self.ann
.pre(self, AnnNode
::Expr(expr
));
1407 hir
::ExprKind
::Box(ref expr
) => {
1408 self.word_space("box");
1409 self.print_expr_maybe_paren(expr
, parser
::PREC_PREFIX
);
1411 hir
::ExprKind
::Array(ref exprs
) => {
1412 self.print_expr_vec(exprs
);
1414 hir
::ExprKind
::ConstBlock(ref anon_const
) => {
1415 self.print_expr_anon_const(anon_const
);
1417 hir
::ExprKind
::Repeat(ref element
, ref count
) => {
1418 self.print_expr_repeat(&element
, count
);
1420 hir
::ExprKind
::Struct(ref qpath
, fields
, ref wth
) => {
1421 self.print_expr_struct(qpath
, fields
, wth
);
1423 hir
::ExprKind
::Tup(ref exprs
) => {
1424 self.print_expr_tup(exprs
);
1426 hir
::ExprKind
::Call(ref func
, ref args
) => {
1427 self.print_expr_call(&func
, args
);
1429 hir
::ExprKind
::MethodCall(ref segment
, ref args
, _
) => {
1430 self.print_expr_method_call(segment
, args
);
1432 hir
::ExprKind
::Binary(op
, ref lhs
, ref rhs
) => {
1433 self.print_expr_binary(op
, &lhs
, &rhs
);
1435 hir
::ExprKind
::Unary(op
, ref expr
) => {
1436 self.print_expr_unary(op
, &expr
);
1438 hir
::ExprKind
::AddrOf(k
, m
, ref expr
) => {
1439 self.print_expr_addr_of(k
, m
, &expr
);
1441 hir
::ExprKind
::Lit(ref lit
) => {
1442 self.print_literal(&lit
);
1444 hir
::ExprKind
::Cast(ref expr
, ref ty
) => {
1445 let prec
= AssocOp
::As
.precedence() as i8;
1446 self.print_expr_maybe_paren(&expr
, prec
);
1448 self.word_space("as");
1449 self.print_type(&ty
);
1451 hir
::ExprKind
::Type(ref expr
, ref ty
) => {
1452 let prec
= AssocOp
::Colon
.precedence() as i8;
1453 self.print_expr_maybe_paren(&expr
, prec
);
1454 self.word_space(":");
1455 self.print_type(&ty
);
1457 hir
::ExprKind
::DropTemps(ref init
) => {
1459 self.cbox(INDENT_UNIT
);
1463 // Print `let _t = $init;`:
1464 let temp
= Ident
::from_str("_t");
1465 self.print_local(Some(init
), |this
| this
.print_ident(temp
));
1469 self.space_if_not_bol();
1470 self.print_ident(temp
);
1473 self.bclose_maybe_open(expr
.span
, true);
1475 hir
::ExprKind
::Let(hir
::Let { pat, ty, init, .. }
) => {
1476 self.print_let(pat
, *ty
, init
);
1478 hir
::ExprKind
::If(ref test
, ref blk
, ref elseopt
) => {
1479 self.print_if(&test
, &blk
, elseopt
.as_ref().map(|e
| &**e
));
1481 hir
::ExprKind
::Loop(ref blk
, opt_label
, _
, _
) => {
1482 if let Some(label
) = opt_label
{
1483 self.print_ident(label
.ident
);
1484 self.word_space(":");
1487 self.print_block(&blk
);
1489 hir
::ExprKind
::Match(ref expr
, arms
, _
) => {
1490 self.cbox(INDENT_UNIT
);
1491 self.ibox(INDENT_UNIT
);
1492 self.word_nbsp("match");
1493 self.print_expr_as_cond(&expr
);
1497 self.print_arm(arm
);
1499 self.bclose(expr
.span
);
1501 hir
::ExprKind
::Closure(capture_clause
, ref decl
, body
, _fn_decl_span
, _gen
) => {
1502 self.print_capture_clause(capture_clause
);
1504 self.print_closure_params(&decl
, body
);
1507 // This is a bare expression.
1508 self.ann
.nested(self, Nested
::Body(body
));
1509 self.end(); // need to close a box
1511 // A box will be closed by `print_expr`, but we didn't want an overall
1512 // wrapper so we closed the corresponding opening. so create an
1513 // empty box to satisfy the close.
1516 hir
::ExprKind
::Block(ref blk
, opt_label
) => {
1517 if let Some(label
) = opt_label
{
1518 self.print_ident(label
.ident
);
1519 self.word_space(":");
1521 // containing cbox, will be closed by print-block at `}`
1522 self.cbox(INDENT_UNIT
);
1523 // head-box, will be closed by print-block after `{`
1525 self.print_block(&blk
);
1527 hir
::ExprKind
::Assign(ref lhs
, ref rhs
, _
) => {
1528 let prec
= AssocOp
::Assign
.precedence() as i8;
1529 self.print_expr_maybe_paren(&lhs
, prec
+ 1);
1531 self.word_space("=");
1532 self.print_expr_maybe_paren(&rhs
, prec
);
1534 hir
::ExprKind
::AssignOp(op
, ref lhs
, ref rhs
) => {
1535 let prec
= AssocOp
::Assign
.precedence() as i8;
1536 self.print_expr_maybe_paren(&lhs
, prec
+ 1);
1538 self.word(op
.node
.as_str());
1539 self.word_space("=");
1540 self.print_expr_maybe_paren(&rhs
, prec
);
1542 hir
::ExprKind
::Field(ref expr
, ident
) => {
1543 self.print_expr_maybe_paren(expr
, parser
::PREC_POSTFIX
);
1545 self.print_ident(ident
);
1547 hir
::ExprKind
::Index(ref expr
, ref index
) => {
1548 self.print_expr_maybe_paren(&expr
, parser
::PREC_POSTFIX
);
1550 self.print_expr(&index
);
1553 hir
::ExprKind
::Path(ref qpath
) => self.print_qpath(qpath
, true),
1554 hir
::ExprKind
::Break(destination
, ref opt_expr
) => {
1556 if let Some(label
) = destination
.label
{
1558 self.print_ident(label
.ident
);
1560 if let Some(ref expr
) = *opt_expr
{
1562 self.print_expr_maybe_paren(expr
, parser
::PREC_JUMP
);
1565 hir
::ExprKind
::Continue(destination
) => {
1566 self.word("continue");
1567 if let Some(label
) = destination
.label
{
1569 self.print_ident(label
.ident
);
1572 hir
::ExprKind
::Ret(ref result
) => {
1573 self.word("return");
1574 if let Some(ref expr
) = *result
{
1576 self.print_expr_maybe_paren(&expr
, parser
::PREC_JUMP
);
1579 hir
::ExprKind
::InlineAsm(ref asm
) => {
1581 self.print_inline_asm(asm
);
1583 hir
::ExprKind
::Yield(ref expr
, _
) => {
1584 self.word_space("yield");
1585 self.print_expr_maybe_paren(&expr
, parser
::PREC_JUMP
);
1587 hir
::ExprKind
::Err
=> {
1589 self.word("/*ERROR*/");
1593 self.ann
.post(self, AnnNode
::Expr(expr
));
1597 pub fn print_local_decl(&mut self, loc
: &hir
::Local
<'_
>) {
1598 self.print_pat(&loc
.pat
);
1599 if let Some(ref ty
) = loc
.ty
{
1600 self.word_space(":");
1601 self.print_type(&ty
);
1605 pub fn print_name(&mut self, name
: Symbol
) {
1606 self.print_ident(Ident
::with_dummy_span(name
))
1609 pub fn print_path(&mut self, path
: &hir
::Path
<'_
>, colons_before_params
: bool
) {
1610 self.maybe_print_comment(path
.span
.lo());
1612 for (i
, segment
) in path
.segments
.iter().enumerate() {
1616 if segment
.ident
.name
!= kw
::PathRoot
{
1617 self.print_ident(segment
.ident
);
1618 self.print_generic_args(segment
.args(), segment
.infer_args
, colons_before_params
);
1623 pub fn print_path_segment(&mut self, segment
: &hir
::PathSegment
<'_
>) {
1624 if segment
.ident
.name
!= kw
::PathRoot
{
1625 self.print_ident(segment
.ident
);
1626 self.print_generic_args(segment
.args(), segment
.infer_args
, false);
1630 pub fn print_qpath(&mut self, qpath
: &hir
::QPath
<'_
>, colons_before_params
: bool
) {
1632 hir
::QPath
::Resolved(None
, ref path
) => self.print_path(path
, colons_before_params
),
1633 hir
::QPath
::Resolved(Some(ref qself
), ref path
) => {
1635 self.print_type(qself
);
1637 self.word_space("as");
1639 for (i
, segment
) in path
.segments
[..path
.segments
.len() - 1].iter().enumerate() {
1643 if segment
.ident
.name
!= kw
::PathRoot
{
1644 self.print_ident(segment
.ident
);
1645 self.print_generic_args(
1648 colons_before_params
,
1655 let item_segment
= path
.segments
.last().unwrap();
1656 self.print_ident(item_segment
.ident
);
1657 self.print_generic_args(
1658 item_segment
.args(),
1659 item_segment
.infer_args
,
1660 colons_before_params
,
1663 hir
::QPath
::TypeRelative(ref qself
, ref item_segment
) => {
1664 // If we've got a compound-qualified-path, let's push an additional pair of angle
1665 // brackets, so that we pretty-print `<<A::B>::C>` as `<A::B>::C`, instead of just
1666 // `A::B::C` (since the latter could be ambiguous to the user)
1667 if let hir
::TyKind
::Path(hir
::QPath
::Resolved(None
, _
)) = &qself
.kind
{
1668 self.print_type(qself
);
1671 self.print_type(qself
);
1676 self.print_ident(item_segment
.ident
);
1677 self.print_generic_args(
1678 item_segment
.args(),
1679 item_segment
.infer_args
,
1680 colons_before_params
,
1683 hir
::QPath
::LangItem(lang_item
, span
, _
) => {
1684 self.word("#[lang = \"");
1685 self.print_ident(Ident
::new(lang_item
.name(), span
));
1691 fn print_generic_args(
1693 generic_args
: &hir
::GenericArgs
<'_
>,
1695 colons_before_params
: bool
,
1697 if generic_args
.parenthesized
{
1699 self.commasep(Inconsistent
, generic_args
.inputs(), |s
, ty
| s
.print_type(&ty
));
1702 self.space_if_not_bol();
1703 self.word_space("->");
1704 self.print_type(generic_args
.bindings
[0].ty());
1706 let start
= if colons_before_params { "::<" }
else { "<" }
;
1707 let empty
= Cell
::new(true);
1708 let start_or_comma
= |this
: &mut Self| {
1713 this
.word_space(",")
1717 let mut nonelided_generic_args
: bool
= false;
1718 let elide_lifetimes
= generic_args
.args
.iter().all(|arg
| match arg
{
1719 GenericArg
::Lifetime(lt
) => lt
.is_elided(),
1721 nonelided_generic_args
= true;
1726 if nonelided_generic_args
{
1727 start_or_comma(self);
1731 |s
, generic_arg
| match generic_arg
{
1732 GenericArg
::Lifetime(lt
) if !elide_lifetimes
=> s
.print_lifetime(lt
),
1733 GenericArg
::Lifetime(_
) => {}
1734 GenericArg
::Type(ty
) => s
.print_type(ty
),
1735 GenericArg
::Const(ct
) => s
.print_anon_const(&ct
.value
),
1736 GenericArg
::Infer(_inf
) => s
.word("_"),
1741 // FIXME(eddyb): this would leak into error messages (e.g.,
1742 // "non-exhaustive patterns: `Some::<..>(_)` not covered").
1743 if infer_args
&& false {
1744 start_or_comma(self);
1748 for binding
in generic_args
.bindings
.iter() {
1749 start_or_comma(self);
1750 self.print_ident(binding
.ident
);
1751 self.print_generic_args(binding
.gen_args
, false, false);
1753 match generic_args
.bindings
[0].kind
{
1754 hir
::TypeBindingKind
::Equality { ref term }
=> {
1755 self.word_space("=");
1757 Term
::Ty(ref ty
) => self.print_type(ty
),
1758 Term
::Const(ref c
) => self.print_anon_const(c
),
1761 hir
::TypeBindingKind
::Constraint { bounds }
=> {
1762 self.print_bounds(":", bounds
);
1773 pub fn print_pat(&mut self, pat
: &hir
::Pat
<'_
>) {
1774 self.maybe_print_comment(pat
.span
.lo());
1775 self.ann
.pre(self, AnnNode
::Pat(pat
));
1776 // Pat isn't normalized, but the beauty of it
1777 // is that it doesn't matter
1779 PatKind
::Wild
=> self.word("_"),
1780 PatKind
::Binding(binding_mode
, _
, ident
, ref sub
) => {
1781 match binding_mode
{
1782 hir
::BindingAnnotation
::Ref
=> {
1783 self.word_nbsp("ref");
1784 self.print_mutability(hir
::Mutability
::Not
, false);
1786 hir
::BindingAnnotation
::RefMut
=> {
1787 self.word_nbsp("ref");
1788 self.print_mutability(hir
::Mutability
::Mut
, false);
1790 hir
::BindingAnnotation
::Unannotated
=> {}
1791 hir
::BindingAnnotation
::Mutable
=> {
1792 self.word_nbsp("mut");
1795 self.print_ident(ident
);
1796 if let Some(ref p
) = *sub
{
1801 PatKind
::TupleStruct(ref qpath
, ref elts
, ddpos
) => {
1802 self.print_qpath(qpath
, true);
1804 if let Some(ddpos
) = ddpos
{
1805 self.commasep(Inconsistent
, &elts
[..ddpos
], |s
, p
| s
.print_pat(&p
));
1807 self.word_space(",");
1810 if ddpos
!= elts
.len() {
1812 self.commasep(Inconsistent
, &elts
[ddpos
..], |s
, p
| s
.print_pat(&p
));
1815 self.commasep(Inconsistent
, &elts
, |s
, p
| s
.print_pat(&p
));
1819 PatKind
::Path(ref qpath
) => {
1820 self.print_qpath(qpath
, true);
1822 PatKind
::Struct(ref qpath
, ref fields
, etc
) => {
1823 self.print_qpath(qpath
, true);
1826 let empty
= fields
.is_empty() && !etc
;
1834 s
.cbox(INDENT_UNIT
);
1835 if !f
.is_shorthand
{
1836 s
.print_ident(f
.ident
);
1839 s
.print_pat(&f
.pat
);
1845 if !fields
.is_empty() {
1846 self.word_space(",");
1855 PatKind
::Or(ref pats
) => {
1856 self.strsep("|", true, Inconsistent
, &pats
, |s
, p
| s
.print_pat(&p
));
1858 PatKind
::Tuple(ref elts
, ddpos
) => {
1860 if let Some(ddpos
) = ddpos
{
1861 self.commasep(Inconsistent
, &elts
[..ddpos
], |s
, p
| s
.print_pat(&p
));
1863 self.word_space(",");
1866 if ddpos
!= elts
.len() {
1868 self.commasep(Inconsistent
, &elts
[ddpos
..], |s
, p
| s
.print_pat(&p
));
1871 self.commasep(Inconsistent
, &elts
[..], |s
, p
| s
.print_pat(&p
));
1872 if elts
.len() == 1 {
1878 PatKind
::Box(ref inner
) => {
1879 let is_range_inner
= matches
!(inner
.kind
, PatKind
::Range(..));
1884 self.print_pat(&inner
);
1889 PatKind
::Ref(ref inner
, mutbl
) => {
1890 let is_range_inner
= matches
!(inner
.kind
, PatKind
::Range(..));
1892 self.word(mutbl
.prefix_str());
1896 self.print_pat(&inner
);
1901 PatKind
::Lit(ref e
) => self.print_expr(&e
),
1902 PatKind
::Range(ref begin
, ref end
, ref end_kind
) => {
1903 if let Some(expr
) = begin
{
1904 self.print_expr(expr
);
1907 RangeEnd
::Included
=> self.word("..."),
1908 RangeEnd
::Excluded
=> self.word(".."),
1910 if let Some(expr
) = end
{
1911 self.print_expr(expr
);
1914 PatKind
::Slice(ref before
, ref slice
, ref after
) => {
1916 self.commasep(Inconsistent
, &before
, |s
, p
| s
.print_pat(&p
));
1917 if let Some(ref p
) = *slice
{
1918 if !before
.is_empty() {
1919 self.word_space(",");
1921 if let PatKind
::Wild
= p
.kind
{
1927 if !after
.is_empty() {
1928 self.word_space(",");
1931 self.commasep(Inconsistent
, &after
, |s
, p
| s
.print_pat(&p
));
1935 self.ann
.post(self, AnnNode
::Pat(pat
))
1938 pub fn print_param(&mut self, arg
: &hir
::Param
<'_
>) {
1939 self.print_outer_attributes(self.attrs(arg
.hir_id
));
1940 self.print_pat(&arg
.pat
);
1943 pub fn print_arm(&mut self, arm
: &hir
::Arm
<'_
>) {
1944 // I have no idea why this check is necessary, but here it
1946 if self.attrs(arm
.hir_id
).is_empty() {
1949 self.cbox(INDENT_UNIT
);
1950 self.ann
.pre(self, AnnNode
::Arm(arm
));
1952 self.print_outer_attributes(&self.attrs(arm
.hir_id
));
1953 self.print_pat(&arm
.pat
);
1955 if let Some(ref g
) = arm
.guard
{
1957 hir
::Guard
::If(e
) => {
1958 self.word_space("if");
1959 self.print_expr(&e
);
1962 hir
::Guard
::IfLet(pat
, e
) => {
1963 self.word_nbsp("if");
1964 self.word_nbsp("let");
1965 self.print_pat(&pat
);
1967 self.word_space("=");
1968 self.print_expr(&e
);
1973 self.word_space("=>");
1975 match arm
.body
.kind
{
1976 hir
::ExprKind
::Block(ref blk
, opt_label
) => {
1977 if let Some(label
) = opt_label
{
1978 self.print_ident(label
.ident
);
1979 self.word_space(":");
1981 // the block will close the pattern's ibox
1982 self.print_block_unclosed(&blk
);
1984 // If it is a user-provided unsafe block, print a comma after it
1985 if let hir
::BlockCheckMode
::UnsafeBlock(hir
::UnsafeSource
::UserProvided
) = blk
.rules
1991 self.end(); // close the ibox for the pattern
1992 self.print_expr(&arm
.body
);
1996 self.ann
.post(self, AnnNode
::Arm(arm
));
1997 self.end() // close enclosing cbox
2002 decl
: &hir
::FnDecl
<'_
>,
2003 header
: hir
::FnHeader
,
2004 name
: Option
<Symbol
>,
2005 generics
: &hir
::Generics
<'_
>,
2006 vis
: &hir
::Visibility
<'_
>,
2007 arg_names
: &[Ident
],
2008 body_id
: Option
<hir
::BodyId
>,
2010 self.print_fn_header_info(header
, vis
);
2012 if let Some(name
) = name
{
2014 self.print_name(name
);
2016 self.print_generic_params(&generics
.params
);
2020 // Make sure we aren't supplied *both* `arg_names` and `body_id`.
2021 assert
!(arg_names
.is_empty() || body_id
.is_none());
2022 self.commasep(Inconsistent
, &decl
.inputs
, |s
, ty
| {
2023 s
.ibox(INDENT_UNIT
);
2024 if let Some(arg_name
) = arg_names
.get(i
) {
2025 s
.word(arg_name
.to_string());
2028 } else if let Some(body_id
) = body_id
{
2029 s
.ann
.nested(s
, Nested
::BodyParamPat(body_id
, i
));
2037 if decl
.c_variadic
{
2042 self.print_fn_output(decl
);
2043 self.print_where_clause(&generics
.where_clause
)
2046 fn print_closure_params(&mut self, decl
: &hir
::FnDecl
<'_
>, body_id
: hir
::BodyId
) {
2049 self.commasep(Inconsistent
, &decl
.inputs
, |s
, ty
| {
2050 s
.ibox(INDENT_UNIT
);
2052 s
.ann
.nested(s
, Nested
::BodyParamPat(body_id
, i
));
2055 if let hir
::TyKind
::Infer
= ty
.kind
{
2066 if let hir
::FnRetTy
::DefaultReturn(..) = decl
.output
{
2070 self.space_if_not_bol();
2071 self.word_space("->");
2073 hir
::FnRetTy
::Return(ref ty
) => {
2074 self.print_type(&ty
);
2075 self.maybe_print_comment(ty
.span
.lo());
2077 hir
::FnRetTy
::DefaultReturn(..) => unreachable
!(),
2081 pub fn print_capture_clause(&mut self, capture_clause
: hir
::CaptureBy
) {
2082 match capture_clause
{
2083 hir
::CaptureBy
::Value
=> self.word_space("move"),
2084 hir
::CaptureBy
::Ref
=> {}
2088 pub fn print_bounds
<'b
>(
2090 prefix
: &'
static str,
2091 bounds
: impl IntoIterator
<Item
= &'b hir
::GenericBound
<'b
>>,
2093 let mut first
= true;
2094 for bound
in bounds
{
2098 if !(first
&& prefix
.is_empty()) {
2104 self.word_space("+");
2108 GenericBound
::Trait(tref
, modifier
) => {
2109 if modifier
== &TraitBoundModifier
::Maybe
{
2112 self.print_poly_trait_ref(tref
);
2114 GenericBound
::LangItemTrait(lang_item
, span
, ..) => {
2115 self.word("#[lang = \"");
2116 self.print_ident(Ident
::new(lang_item
.name(), *span
));
2119 GenericBound
::Outlives(lt
) => {
2120 self.print_lifetime(lt
);
2126 pub fn print_generic_params(&mut self, generic_params
: &[GenericParam
<'_
>]) {
2127 if !generic_params
.is_empty() {
2130 self.commasep(Inconsistent
, generic_params
, |s
, param
| s
.print_generic_param(param
));
2136 pub fn print_generic_param(&mut self, param
: &GenericParam
<'_
>) {
2137 if let GenericParamKind
::Const { .. }
= param
.kind
{
2138 self.word_space("const");
2141 self.print_ident(param
.name
.ident());
2144 GenericParamKind
::Lifetime { .. }
=> {
2146 for bound
in param
.bounds
{
2148 GenericBound
::Outlives(ref lt
) => {
2150 self.print_lifetime(lt
);
2157 GenericParamKind
::Type { ref default, .. }
=> {
2158 self.print_bounds(":", param
.bounds
);
2159 if let Some(default) = default {
2161 self.word_space("=");
2162 self.print_type(&default)
2165 GenericParamKind
::Const { ref ty, ref default }
=> {
2166 self.word_space(":");
2167 self.print_type(ty
);
2168 if let Some(ref default) = default {
2170 self.word_space("=");
2171 self.print_anon_const(&default)
2177 pub fn print_lifetime(&mut self, lifetime
: &hir
::Lifetime
) {
2178 self.print_ident(lifetime
.name
.ident())
2181 pub fn print_where_clause(&mut self, where_clause
: &hir
::WhereClause
<'_
>) {
2182 if where_clause
.predicates
.is_empty() {
2187 self.word_space("where");
2189 for (i
, predicate
) in where_clause
.predicates
.iter().enumerate() {
2191 self.word_space(",");
2195 hir
::WherePredicate
::BoundPredicate(hir
::WhereBoundPredicate
{
2196 bound_generic_params
,
2201 self.print_formal_generic_params(bound_generic_params
);
2202 self.print_type(&bounded_ty
);
2203 self.print_bounds(":", *bounds
);
2205 hir
::WherePredicate
::RegionPredicate(hir
::WhereRegionPredicate
{
2210 self.print_lifetime(lifetime
);
2213 for (i
, bound
) in bounds
.iter().enumerate() {
2215 GenericBound
::Outlives(lt
) => {
2216 self.print_lifetime(lt
);
2226 hir
::WherePredicate
::EqPredicate(hir
::WhereEqPredicate
{
2229 self.print_type(lhs_ty
);
2231 self.word_space("=");
2232 self.print_type(rhs_ty
);
2238 pub fn print_mutability(&mut self, mutbl
: hir
::Mutability
, print_const
: bool
) {
2240 hir
::Mutability
::Mut
=> self.word_nbsp("mut"),
2241 hir
::Mutability
::Not
=> {
2243 self.word_nbsp("const")
2249 pub fn print_mt(&mut self, mt
: &hir
::MutTy
<'_
>, print_const
: bool
) {
2250 self.print_mutability(mt
.mutbl
, print_const
);
2251 self.print_type(&mt
.ty
)
2254 pub fn print_fn_output(&mut self, decl
: &hir
::FnDecl
<'_
>) {
2255 if let hir
::FnRetTy
::DefaultReturn(..) = decl
.output
{
2259 self.space_if_not_bol();
2260 self.ibox(INDENT_UNIT
);
2261 self.word_space("->");
2263 hir
::FnRetTy
::DefaultReturn(..) => unreachable
!(),
2264 hir
::FnRetTy
::Return(ref ty
) => self.print_type(&ty
),
2268 if let hir
::FnRetTy
::Return(ref output
) = decl
.output
{
2269 self.maybe_print_comment(output
.span
.lo());
2276 unsafety
: hir
::Unsafety
,
2277 decl
: &hir
::FnDecl
<'_
>,
2278 name
: Option
<Symbol
>,
2279 generic_params
: &[hir
::GenericParam
<'_
>],
2280 arg_names
: &[Ident
],
2282 self.ibox(INDENT_UNIT
);
2283 self.print_formal_generic_params(generic_params
);
2284 let generics
= hir
::Generics
{
2286 where_clause
: hir
::WhereClause { predicates: &[], span: rustc_span::DUMMY_SP }
,
2287 span
: rustc_span
::DUMMY_SP
,
2294 constness
: hir
::Constness
::NotConst
,
2295 asyncness
: hir
::IsAsync
::NotAsync
,
2299 &Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited }
,
2306 pub fn print_fn_header_info(&mut self, header
: hir
::FnHeader
, vis
: &hir
::Visibility
<'_
>) {
2307 self.word(visibility_qualified(vis
, ""));
2309 match header
.constness
{
2310 hir
::Constness
::NotConst
=> {}
2311 hir
::Constness
::Const
=> self.word_nbsp("const"),
2314 match header
.asyncness
{
2315 hir
::IsAsync
::NotAsync
=> {}
2316 hir
::IsAsync
::Async
=> self.word_nbsp("async"),
2319 self.print_unsafety(header
.unsafety
);
2321 if header
.abi
!= Abi
::Rust
{
2322 self.word_nbsp("extern");
2323 self.word_nbsp(header
.abi
.to_string());
2329 pub fn print_unsafety(&mut self, s
: hir
::Unsafety
) {
2331 hir
::Unsafety
::Normal
=> {}
2332 hir
::Unsafety
::Unsafe
=> self.word_nbsp("unsafe"),
2336 pub fn print_is_auto(&mut self, s
: hir
::IsAuto
) {
2338 hir
::IsAuto
::Yes
=> self.word_nbsp("auto"),
2339 hir
::IsAuto
::No
=> {}
2344 /// Does this expression require a semicolon to be treated
2345 /// as a statement? The negation of this: 'can this expression
2346 /// be used as a statement without a semicolon' -- is used
2347 /// as an early-bail-out in the parser so that, for instance,
2348 /// if true {...} else {...}
2350 /// isn't parsed as (if true {...} else {...} | x) | 5
2352 // Duplicated from `parse::classify`, but adapted for the HIR.
2353 fn expr_requires_semi_to_be_stmt(e
: &hir
::Expr
<'_
>) -> bool
{
2356 hir
::ExprKind
::If(..)
2357 | hir
::ExprKind
::Match(..)
2358 | hir
::ExprKind
::Block(..)
2359 | hir
::ExprKind
::Loop(..)
2363 /// This statement requires a semicolon after it.
2364 /// note that in one case (stmt_semi), we've already
2365 /// seen the semicolon, and thus don't need another.
2366 fn stmt_ends_with_semi(stmt
: &hir
::StmtKind
<'_
>) -> bool
{
2368 hir
::StmtKind
::Local(_
) => true,
2369 hir
::StmtKind
::Item(_
) => false,
2370 hir
::StmtKind
::Expr(ref e
) => expr_requires_semi_to_be_stmt(&e
),
2371 hir
::StmtKind
::Semi(..) => false,
2375 fn bin_op_to_assoc_op(op
: hir
::BinOpKind
) -> AssocOp
{
2376 use crate::hir
::BinOpKind
::*;
2378 Add
=> AssocOp
::Add
,
2379 Sub
=> AssocOp
::Subtract
,
2380 Mul
=> AssocOp
::Multiply
,
2381 Div
=> AssocOp
::Divide
,
2382 Rem
=> AssocOp
::Modulus
,
2384 And
=> AssocOp
::LAnd
,
2387 BitXor
=> AssocOp
::BitXor
,
2388 BitAnd
=> AssocOp
::BitAnd
,
2389 BitOr
=> AssocOp
::BitOr
,
2390 Shl
=> AssocOp
::ShiftLeft
,
2391 Shr
=> AssocOp
::ShiftRight
,
2393 Eq
=> AssocOp
::Equal
,
2394 Lt
=> AssocOp
::Less
,
2395 Le
=> AssocOp
::LessEqual
,
2396 Ne
=> AssocOp
::NotEqual
,
2397 Ge
=> AssocOp
::GreaterEqual
,
2398 Gt
=> AssocOp
::Greater
,
2402 /// Expressions that syntactically contain an "exterior" struct literal, i.e., not surrounded by any
2403 /// parens or other delimiters, e.g., `X { y: 1 }`, `X { y: 1 }.method()`, `foo == X { y: 1 }` and
2404 /// `X { y: 1 } == foo` all do, but `(X { y: 1 }) == foo` does not.
2405 fn contains_exterior_struct_lit(value
: &hir
::Expr
<'_
>) -> bool
{
2407 hir
::ExprKind
::Struct(..) => true,
2409 hir
::ExprKind
::Assign(ref lhs
, ref rhs
, _
)
2410 | hir
::ExprKind
::AssignOp(_
, ref lhs
, ref rhs
)
2411 | hir
::ExprKind
::Binary(_
, ref lhs
, ref rhs
) => {
2412 // `X { y: 1 } + X { y: 2 }`
2413 contains_exterior_struct_lit(&lhs
) || contains_exterior_struct_lit(&rhs
)
2415 hir
::ExprKind
::Unary(_
, ref x
)
2416 | hir
::ExprKind
::Cast(ref x
, _
)
2417 | hir
::ExprKind
::Type(ref x
, _
)
2418 | hir
::ExprKind
::Field(ref x
, _
)
2419 | hir
::ExprKind
::Index(ref x
, _
) => {
2420 // `&X { y: 1 }, X { y: 1 }.y`
2421 contains_exterior_struct_lit(&x
)
2424 hir
::ExprKind
::MethodCall(.., ref exprs
, _
) => {
2425 // `X { y: 1 }.bar(...)`
2426 contains_exterior_struct_lit(&exprs
[0])