1 #![feature(or_patterns)]
2 #![recursion_limit = "256"]
5 use rustc_ast
::util
::parser
::{self, AssocOp, Fixity}
;
6 use rustc_ast_pretty
::pp
::Breaks
::{Consistent, Inconsistent}
;
7 use rustc_ast_pretty
::pp
::{self, Breaks}
;
8 use rustc_ast_pretty
::pprust
::{Comments, PrintState}
;
10 use rustc_hir
::{GenericArg, GenericParam, GenericParamKind, Node}
;
11 use rustc_hir
::{GenericBound, PatKind, RangeEnd, TraitBoundModifier}
;
12 use rustc_span
::source_map
::{SourceMap, Spanned}
;
13 use rustc_span
::symbol
::{kw, Ident, IdentPrinter, Symbol}
;
14 use rustc_span
::{self, BytePos, FileName}
;
15 use rustc_target
::spec
::abi
::Abi
;
21 pub fn id_to_string(map
: &dyn rustc_hir
::intravisit
::Map
<'_
>, hir_id
: hir
::HirId
) -> String
{
22 to_string(&map
, |s
| s
.print_node(map
.find(hir_id
).unwrap()))
25 pub enum AnnNode
<'a
> {
27 Block(&'a hir
::Block
<'a
>),
28 Item(&'a hir
::Item
<'a
>),
30 Expr(&'a hir
::Expr
<'a
>),
31 Pat(&'a hir
::Pat
<'a
>),
32 Arm(&'a hir
::Arm
<'a
>),
37 TraitItem(hir
::TraitItemId
),
38 ImplItem(hir
::ImplItemId
),
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
<'_
>) {}
47 fn try_fetch_item(&self, _
: hir
::HirId
) -> Option
<&hir
::Item
<'_
>> {
53 impl PpAnn
for NoAnn {}
54 pub const NO_ANN
: &dyn PpAnn
= &NoAnn
;
56 impl PpAnn
for hir
::Crate
<'_
> {
57 fn try_fetch_item(&self, item
: hir
::HirId
) -> Option
<&hir
::Item
<'_
>> {
60 fn nested(&self, state
: &mut State
<'_
>, nested
: Nested
) {
62 Nested
::Item(id
) => state
.print_item(self.item(id
.id
)),
63 Nested
::TraitItem(id
) => state
.print_trait_item(self.trait_item(id
)),
64 Nested
::ImplItem(id
) => state
.print_impl_item(self.impl_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 /// Identical to the `PpAnn` implementation for `hir::Crate`,
72 /// except it avoids creating a dependency on the whole crate.
73 impl PpAnn
for &dyn rustc_hir
::intravisit
::Map
<'_
> {
74 fn nested(&self, state
: &mut State
<'_
>, nested
: Nested
) {
76 Nested
::Item(id
) => state
.print_item(self.item(id
.id
)),
77 Nested
::TraitItem(id
) => state
.print_trait_item(self.trait_item(id
)),
78 Nested
::ImplItem(id
) => state
.print_impl_item(self.impl_item(id
)),
79 Nested
::Body(id
) => state
.print_expr(&self.body(id
).value
),
80 Nested
::BodyParamPat(id
, i
) => state
.print_pat(&self.body(id
).params
[i
].pat
),
85 pub struct State
<'a
> {
87 comments
: Option
<Comments
<'a
>>,
88 ann
: &'
a (dyn PpAnn
+ 'a
),
92 pub fn print_node(&mut self, node
: Node
<'_
>) {
94 Node
::Param(a
) => self.print_param(&a
),
95 Node
::Item(a
) => self.print_item(&a
),
96 Node
::ForeignItem(a
) => self.print_foreign_item(&a
),
97 Node
::TraitItem(a
) => self.print_trait_item(a
),
98 Node
::ImplItem(a
) => self.print_impl_item(a
),
99 Node
::Variant(a
) => self.print_variant(&a
),
100 Node
::AnonConst(a
) => self.print_anon_const(&a
),
101 Node
::Expr(a
) => self.print_expr(&a
),
102 Node
::Stmt(a
) => self.print_stmt(&a
),
103 Node
::PathSegment(a
) => self.print_path_segment(&a
),
104 Node
::Ty(a
) => self.print_type(&a
),
105 Node
::TraitRef(a
) => self.print_trait_ref(&a
),
106 Node
::Binding(a
) | Node
::Pat(a
) => self.print_pat(&a
),
107 Node
::Arm(a
) => self.print_arm(&a
),
109 // Containing cbox, will be closed by print-block at `}`.
110 self.cbox(INDENT_UNIT
);
111 // Head-ibox, will be closed by print-block after `{`.
115 Node
::Lifetime(a
) => self.print_lifetime(&a
),
116 Node
::Visibility(a
) => self.print_visibility(&a
),
117 Node
::GenericParam(_
) => panic
!("cannot print Node::GenericParam"),
118 Node
::Field(_
) => panic
!("cannot print StructField"),
119 // These cases do not carry enough information in the
120 // `hir_map` to reconstruct their full structure for pretty
122 Node
::Ctor(..) => panic
!("cannot print isolated Ctor"),
123 Node
::Local(a
) => self.print_local_decl(&a
),
124 Node
::MacroDef(_
) => panic
!("cannot print MacroDef"),
125 Node
::Crate(..) => panic
!("cannot print Crate"),
130 impl std
::ops
::Deref
for State
<'_
> {
131 type Target
= pp
::Printer
;
132 fn deref(&self) -> &Self::Target
{
137 impl std
::ops
::DerefMut
for State
<'_
> {
138 fn deref_mut(&mut self) -> &mut Self::Target
{
143 impl<'a
> PrintState
<'a
> for State
<'a
> {
144 fn comments(&mut self) -> &mut Option
<Comments
<'a
>> {
148 fn print_ident(&mut self, ident
: Ident
) {
149 self.s
.word(IdentPrinter
::for_ast_ident(ident
, ident
.is_raw_guess()).to_string());
150 self.ann
.post(self, AnnNode
::Name(&ident
.name
))
153 fn print_generic_args(&mut self, _
: &ast
::GenericArgs
, _colons_before_params
: bool
) {
154 panic
!("AST generic args printed by HIR pretty-printer");
158 pub const INDENT_UNIT
: usize = 4;
160 /// Requires you to pass an input filename and reader so that
161 /// it can scan the input text for comments to copy forward.
162 pub fn print_crate
<'a
>(
164 krate
: &hir
::Crate
<'_
>,
169 let mut s
= State
::new_from_input(sm
, filename
, input
, ann
);
171 // When printing the AST, we sometimes need to inject `#[no_std]` here.
172 // Since you can't compile the HIR, it's not necessary.
174 s
.print_mod(&krate
.item
.module
, &krate
.item
.attrs
);
175 s
.print_remaining_comments();
180 pub fn new_from_input(
186 State { s: pp::mk_printer(), comments: Some(Comments::new(sm, filename, input)), ann }
190 pub fn to_string
<F
>(ann
: &dyn PpAnn
, f
: F
) -> String
192 F
: FnOnce(&mut State
<'_
>),
194 let mut printer
= State { s: pp::mk_printer(), comments: None, ann }
;
199 pub fn visibility_qualified
<S
: Into
<Cow
<'
static, str>>>(vis
: &hir
::Visibility
<'_
>, w
: S
) -> String
{
200 to_string(NO_ANN
, |s
| {
201 s
.print_visibility(vis
);
206 pub fn generic_params_to_string(generic_params
: &[GenericParam
<'_
>]) -> String
{
207 to_string(NO_ANN
, |s
| s
.print_generic_params(generic_params
))
210 pub fn bounds_to_string
<'b
>(bounds
: impl IntoIterator
<Item
= &'b hir
::GenericBound
<'b
>>) -> String
{
211 to_string(NO_ANN
, |s
| s
.print_bounds("", bounds
))
214 pub fn param_to_string(arg
: &hir
::Param
<'_
>) -> String
{
215 to_string(NO_ANN
, |s
| s
.print_param(arg
))
218 pub fn ty_to_string(ty
: &hir
::Ty
<'_
>) -> String
{
219 to_string(NO_ANN
, |s
| s
.print_type(ty
))
222 pub fn path_segment_to_string(segment
: &hir
::PathSegment
<'_
>) -> String
{
223 to_string(NO_ANN
, |s
| s
.print_path_segment(segment
))
226 pub fn path_to_string(segment
: &hir
::Path
<'_
>) -> String
{
227 to_string(NO_ANN
, |s
| s
.print_path(segment
, false))
231 decl
: &hir
::FnDecl
<'_
>,
232 header
: hir
::FnHeader
,
233 name
: Option
<Symbol
>,
234 generics
: &hir
::Generics
<'_
>,
235 vis
: &hir
::Visibility
<'_
>,
237 body_id
: Option
<hir
::BodyId
>,
239 to_string(NO_ANN
, |s
| s
.print_fn(decl
, header
, name
, generics
, vis
, arg_names
, body_id
))
242 pub fn enum_def_to_string(
243 enum_definition
: &hir
::EnumDef
<'_
>,
244 generics
: &hir
::Generics
<'_
>,
246 span
: rustc_span
::Span
,
247 visibility
: &hir
::Visibility
<'_
>,
249 to_string(NO_ANN
, |s
| s
.print_enum_def(enum_definition
, generics
, name
, span
, visibility
))
253 pub fn cbox(&mut self, u
: usize) {
257 pub fn nbsp(&mut self) {
261 pub fn word_nbsp
<S
: Into
<Cow
<'
static, str>>>(&mut self, w
: S
) {
266 pub fn head
<S
: Into
<Cow
<'
static, str>>>(&mut self, w
: S
) {
268 // outer-box is consistent
269 self.cbox(INDENT_UNIT
);
270 // head-box is inconsistent
271 self.ibox(w
.len() + 1);
272 // keyword that starts the head
278 pub fn bopen(&mut self) {
280 self.end(); // close the head-box
283 pub fn bclose_maybe_open(&mut self, span
: rustc_span
::Span
, close_box
: bool
) {
284 self.maybe_print_comment(span
.hi());
285 self.break_offset_if_not_bol(1, -(INDENT_UNIT
as isize));
288 self.end(); // close the outer-box
292 pub fn bclose(&mut self, span
: rustc_span
::Span
) {
293 self.bclose_maybe_open(span
, true)
296 pub fn space_if_not_bol(&mut self) {
297 if !self.s
.is_beginning_of_line() {
302 pub fn break_offset_if_not_bol(&mut self, n
: usize, off
: isize) {
303 if !self.s
.is_beginning_of_line() {
304 self.s
.break_offset(n
, off
)
306 if off
!= 0 && self.s
.last_token().is_hardbreak_tok() {
307 // We do something pretty sketchy here: tuck the nonzero
308 // offset-adjustment we were going to deposit along with the
309 // break into the previous hardbreak.
310 self.s
.replace_last_token(pp
::Printer
::hardbreak_tok_offset(off
));
315 // Synthesizes a comment that was not textually present in the original source
317 pub fn synth_comment(&mut self, text
: String
) {
325 pub fn commasep_cmnt
<T
, F
, G
>(&mut self, b
: Breaks
, elts
: &[T
], mut op
: F
, mut get_span
: G
)
327 F
: FnMut(&mut State
<'_
>, &T
),
328 G
: FnMut(&T
) -> rustc_span
::Span
,
331 let len
= elts
.len();
334 self.maybe_print_comment(get_span(elt
).hi());
339 self.maybe_print_trailing_comment(get_span(elt
), Some(get_span(&elts
[i
]).hi()));
340 self.space_if_not_bol();
346 pub fn commasep_exprs(&mut self, b
: Breaks
, exprs
: &[hir
::Expr
<'_
>]) {
347 self.commasep_cmnt(b
, exprs
, |s
, e
| s
.print_expr(&e
), |e
| e
.span
)
350 pub fn print_mod(&mut self, _mod
: &hir
::Mod
<'_
>, attrs
: &[ast
::Attribute
]) {
351 self.print_inner_attributes(attrs
);
352 for &item_id
in _mod
.item_ids
{
353 self.ann
.nested(self, Nested
::Item(item_id
));
357 pub fn print_foreign_mod(&mut self, nmod
: &hir
::ForeignMod
<'_
>, attrs
: &[ast
::Attribute
]) {
358 self.print_inner_attributes(attrs
);
359 for item
in nmod
.items
{
360 self.print_foreign_item(item
);
364 pub fn print_opt_lifetime(&mut self, lifetime
: &hir
::Lifetime
) {
365 if !lifetime
.is_elided() {
366 self.print_lifetime(lifetime
);
371 pub fn print_type(&mut self, ty
: &hir
::Ty
<'_
>) {
372 self.maybe_print_comment(ty
.span
.lo());
375 hir
::TyKind
::Slice(ref ty
) => {
377 self.print_type(&ty
);
380 hir
::TyKind
::Ptr(ref mt
) => {
382 self.print_mt(mt
, true);
384 hir
::TyKind
::Rptr(ref lifetime
, ref mt
) => {
386 self.print_opt_lifetime(lifetime
);
387 self.print_mt(mt
, false);
389 hir
::TyKind
::Never
=> {
392 hir
::TyKind
::Tup(ref elts
) => {
394 self.commasep(Inconsistent
, &elts
[..], |s
, ty
| s
.print_type(&ty
));
400 hir
::TyKind
::BareFn(ref f
) => {
410 hir
::TyKind
::OpaqueDef(..) => self.s
.word("/*impl Trait*/"),
411 hir
::TyKind
::Path(ref qpath
) => self.print_qpath(qpath
, false),
412 hir
::TyKind
::TraitObject(bounds
, ref lifetime
) => {
413 let mut first
= true;
414 for bound
in bounds
{
419 self.word_space("+");
421 self.print_poly_trait_ref(bound
);
423 if !lifetime
.is_elided() {
425 self.word_space("+");
426 self.print_lifetime(lifetime
);
429 hir
::TyKind
::Array(ref ty
, ref length
) => {
431 self.print_type(&ty
);
433 self.print_anon_const(length
);
436 hir
::TyKind
::Typeof(ref e
) => {
437 self.s
.word("typeof(");
438 self.print_anon_const(e
);
441 hir
::TyKind
::Infer
=> {
444 hir
::TyKind
::Err
=> {
446 self.s
.word("/*ERROR*/");
453 pub fn print_foreign_item(&mut self, item
: &hir
::ForeignItem
<'_
>) {
454 self.hardbreak_if_not_bol();
455 self.maybe_print_comment(item
.span
.lo());
456 self.print_outer_attributes(&item
.attrs
);
458 hir
::ForeignItemKind
::Fn(ref decl
, ref arg_names
, ref generics
) => {
463 unsafety
: hir
::Unsafety
::Normal
,
464 constness
: hir
::Constness
::NotConst
,
466 asyncness
: hir
::IsAsync
::NotAsync
,
468 Some(item
.ident
.name
),
474 self.end(); // end head-ibox
476 self.end() // end the outer fn box
478 hir
::ForeignItemKind
::Static(ref t
, m
) => {
479 self.head(visibility_qualified(&item
.vis
, "static"));
480 if m
== hir
::Mutability
::Mut
{
481 self.word_space("mut");
483 self.print_ident(item
.ident
);
484 self.word_space(":");
487 self.end(); // end the head-ibox
488 self.end() // end the outer cbox
490 hir
::ForeignItemKind
::Type
=> {
491 self.head(visibility_qualified(&item
.vis
, "type"));
492 self.print_ident(item
.ident
);
494 self.end(); // end the head-ibox
495 self.end() // end the outer cbox
500 fn print_associated_const(
504 default: Option
<hir
::BodyId
>,
505 vis
: &hir
::Visibility
<'_
>,
507 self.s
.word(visibility_qualified(vis
, ""));
508 self.word_space("const");
509 self.print_ident(ident
);
510 self.word_space(":");
512 if let Some(expr
) = default {
514 self.word_space("=");
515 self.ann
.nested(self, Nested
::Body(expr
));
520 fn print_associated_type(
523 generics
: &hir
::Generics
<'_
>,
524 bounds
: Option
<hir
::GenericBounds
<'_
>>,
525 ty
: Option
<&hir
::Ty
<'_
>>,
527 self.word_space("type");
528 self.print_ident(ident
);
529 self.print_generic_params(&generics
.params
);
530 if let Some(bounds
) = bounds
{
531 self.print_bounds(":", bounds
);
533 self.print_where_clause(&generics
.where_clause
);
534 if let Some(ty
) = ty
{
536 self.word_space("=");
544 item
: &hir
::Item
<'_
>,
545 generics
: &hir
::Generics
<'_
>,
546 inner
: impl Fn(&mut Self),
548 self.head(visibility_qualified(&item
.vis
, "type"));
549 self.print_ident(item
.ident
);
550 self.print_generic_params(&generics
.params
);
551 self.end(); // end the inner ibox
553 self.print_where_clause(&generics
.where_clause
);
557 self.end(); // end the outer ibox
560 /// Pretty-print an item
561 pub fn print_item(&mut self, item
: &hir
::Item
<'_
>) {
562 self.hardbreak_if_not_bol();
563 self.maybe_print_comment(item
.span
.lo());
564 self.print_outer_attributes(&item
.attrs
);
565 self.ann
.pre(self, AnnNode
::Item(item
));
567 hir
::ItemKind
::ExternCrate(orig_name
) => {
568 self.head(visibility_qualified(&item
.vis
, "extern crate"));
569 if let Some(orig_name
) = orig_name
{
570 self.print_name(orig_name
);
575 self.print_ident(item
.ident
);
577 self.end(); // end inner head-block
578 self.end(); // end outer head-block
580 hir
::ItemKind
::Use(ref path
, kind
) => {
581 self.head(visibility_qualified(&item
.vis
, "use"));
582 self.print_path(path
, false);
585 hir
::UseKind
::Single
=> {
586 if path
.segments
.last().unwrap().ident
!= item
.ident
{
588 self.word_space("as");
589 self.print_ident(item
.ident
);
593 hir
::UseKind
::Glob
=> self.s
.word("::*;"),
594 hir
::UseKind
::ListStem
=> self.s
.word("::{};"),
596 self.end(); // end inner head-block
597 self.end(); // end outer head-block
599 hir
::ItemKind
::Static(ref ty
, m
, expr
) => {
600 self.head(visibility_qualified(&item
.vis
, "static"));
601 if m
== hir
::Mutability
::Mut
{
602 self.word_space("mut");
604 self.print_ident(item
.ident
);
605 self.word_space(":");
606 self.print_type(&ty
);
608 self.end(); // end the head-ibox
610 self.word_space("=");
611 self.ann
.nested(self, Nested
::Body(expr
));
613 self.end(); // end the outer cbox
615 hir
::ItemKind
::Const(ref ty
, expr
) => {
616 self.head(visibility_qualified(&item
.vis
, "const"));
617 self.print_ident(item
.ident
);
618 self.word_space(":");
619 self.print_type(&ty
);
621 self.end(); // end the head-ibox
623 self.word_space("=");
624 self.ann
.nested(self, Nested
::Body(expr
));
626 self.end(); // end the outer cbox
628 hir
::ItemKind
::Fn(ref sig
, ref param_names
, body
) => {
633 Some(item
.ident
.name
),
640 self.end(); // need to close a box
641 self.end(); // need to close a box
642 self.ann
.nested(self, Nested
::Body(body
));
644 hir
::ItemKind
::Mod(ref _mod
) => {
645 self.head(visibility_qualified(&item
.vis
, "mod"));
646 self.print_ident(item
.ident
);
649 self.print_mod(_mod
, &item
.attrs
);
650 self.bclose(item
.span
);
652 hir
::ItemKind
::ForeignMod(ref nmod
) => {
654 self.word_nbsp(nmod
.abi
.to_string());
656 self.print_foreign_mod(nmod
, &item
.attrs
);
657 self.bclose(item
.span
);
659 hir
::ItemKind
::GlobalAsm(ref ga
) => {
660 self.head(visibility_qualified(&item
.vis
, "global asm"));
661 self.s
.word(ga
.asm
.to_string());
664 hir
::ItemKind
::TyAlias(ref ty
, ref generics
) => {
665 self.print_item_type(item
, &generics
, |state
| {
666 state
.word_space("=");
667 state
.print_type(&ty
);
670 hir
::ItemKind
::OpaqueTy(ref opaque_ty
) => {
671 self.print_item_type(item
, &opaque_ty
.generics
, |state
| {
672 let mut real_bounds
= Vec
::with_capacity(opaque_ty
.bounds
.len());
673 for b
in opaque_ty
.bounds
.iter() {
674 if let GenericBound
::Trait(ref ptr
, hir
::TraitBoundModifier
::Maybe
) = *b
{
676 state
.word_space("for ?");
677 state
.print_trait_ref(&ptr
.trait_ref
);
682 state
.print_bounds("= impl", real_bounds
);
685 hir
::ItemKind
::Enum(ref enum_definition
, ref params
) => {
686 self.print_enum_def(enum_definition
, params
, item
.ident
.name
, item
.span
, &item
.vis
);
688 hir
::ItemKind
::Struct(ref struct_def
, ref generics
) => {
689 self.head(visibility_qualified(&item
.vis
, "struct"));
690 self.print_struct(struct_def
, generics
, item
.ident
.name
, item
.span
, true);
692 hir
::ItemKind
::Union(ref struct_def
, ref generics
) => {
693 self.head(visibility_qualified(&item
.vis
, "union"));
694 self.print_struct(struct_def
, generics
, item
.ident
.name
, item
.span
, true);
696 hir
::ItemKind
::Impl
{
708 self.print_visibility(&item
.vis
);
709 self.print_defaultness(defaultness
);
710 self.print_unsafety(unsafety
);
711 self.word_nbsp("impl");
713 if !generics
.params
.is_empty() {
714 self.print_generic_params(&generics
.params
);
718 if constness
== hir
::Constness
::Const
{
719 self.word_nbsp("const");
722 if let hir
::ImplPolarity
::Negative(_
) = polarity
{
726 if let Some(ref t
) = of_trait
{
727 self.print_trait_ref(t
);
729 self.word_space("for");
732 self.print_type(&self_ty
);
733 self.print_where_clause(&generics
.where_clause
);
737 self.print_inner_attributes(&item
.attrs
);
738 for impl_item
in items
{
739 self.ann
.nested(self, Nested
::ImplItem(impl_item
.id
));
741 self.bclose(item
.span
);
743 hir
::ItemKind
::Trait(is_auto
, unsafety
, ref generics
, ref bounds
, trait_items
) => {
745 self.print_visibility(&item
.vis
);
746 self.print_is_auto(is_auto
);
747 self.print_unsafety(unsafety
);
748 self.word_nbsp("trait");
749 self.print_ident(item
.ident
);
750 self.print_generic_params(&generics
.params
);
751 let mut real_bounds
= Vec
::with_capacity(bounds
.len());
752 for b
in bounds
.iter() {
753 if let GenericBound
::Trait(ref ptr
, hir
::TraitBoundModifier
::Maybe
) = *b
{
755 self.word_space("for ?");
756 self.print_trait_ref(&ptr
.trait_ref
);
761 self.print_bounds(":", real_bounds
);
762 self.print_where_clause(&generics
.where_clause
);
765 for trait_item
in trait_items
{
766 self.ann
.nested(self, Nested
::TraitItem(trait_item
.id
));
768 self.bclose(item
.span
);
770 hir
::ItemKind
::TraitAlias(ref generics
, ref bounds
) => {
772 self.print_visibility(&item
.vis
);
773 self.word_nbsp("trait");
774 self.print_ident(item
.ident
);
775 self.print_generic_params(&generics
.params
);
776 let mut real_bounds
= Vec
::with_capacity(bounds
.len());
777 // FIXME(durka) this seems to be some quite outdated syntax
778 for b
in bounds
.iter() {
779 if let GenericBound
::Trait(ref ptr
, hir
::TraitBoundModifier
::Maybe
) = *b
{
781 self.word_space("for ?");
782 self.print_trait_ref(&ptr
.trait_ref
);
788 self.print_bounds("=", real_bounds
);
789 self.print_where_clause(&generics
.where_clause
);
793 self.ann
.post(self, AnnNode
::Item(item
))
796 pub fn print_trait_ref(&mut self, t
: &hir
::TraitRef
<'_
>) {
797 self.print_path(&t
.path
, false)
800 fn print_formal_generic_params(&mut self, generic_params
: &[hir
::GenericParam
<'_
>]) {
801 if !generic_params
.is_empty() {
803 self.print_generic_params(generic_params
);
808 fn print_poly_trait_ref(&mut self, t
: &hir
::PolyTraitRef
<'_
>) {
809 self.print_formal_generic_params(&t
.bound_generic_params
);
810 self.print_trait_ref(&t
.trait_ref
)
813 pub fn print_enum_def(
815 enum_definition
: &hir
::EnumDef
<'_
>,
816 generics
: &hir
::Generics
<'_
>,
818 span
: rustc_span
::Span
,
819 visibility
: &hir
::Visibility
<'_
>,
821 self.head(visibility_qualified(visibility
, "enum"));
822 self.print_name(name
);
823 self.print_generic_params(&generics
.params
);
824 self.print_where_clause(&generics
.where_clause
);
826 self.print_variants(&enum_definition
.variants
, span
)
829 pub fn print_variants(&mut self, variants
: &[hir
::Variant
<'_
>], span
: rustc_span
::Span
) {
832 self.space_if_not_bol();
833 self.maybe_print_comment(v
.span
.lo());
834 self.print_outer_attributes(&v
.attrs
);
835 self.ibox(INDENT_UNIT
);
836 self.print_variant(v
);
839 self.maybe_print_trailing_comment(v
.span
, None
);
844 pub fn print_visibility(&mut self, vis
: &hir
::Visibility
<'_
>) {
846 hir
::VisibilityKind
::Public
=> self.word_nbsp("pub"),
847 hir
::VisibilityKind
::Crate(ast
::CrateSugar
::JustCrate
) => self.word_nbsp("crate"),
848 hir
::VisibilityKind
::Crate(ast
::CrateSugar
::PubCrate
) => self.word_nbsp("pub(crate)"),
849 hir
::VisibilityKind
::Restricted { ref path, .. }
=> {
851 if path
.segments
.len() == 1 && path
.segments
[0].ident
.name
== kw
::Super
{
852 // Special case: `super` can print like `pub(super)`.
853 self.s
.word("super");
855 // Everything else requires `in` at present.
856 self.word_nbsp("in");
857 self.print_path(path
, false);
861 hir
::VisibilityKind
::Inherited
=> (),
865 pub fn print_defaultness(&mut self, defaultness
: hir
::Defaultness
) {
867 hir
::Defaultness
::Default { .. }
=> self.word_nbsp("default"),
868 hir
::Defaultness
::Final
=> (),
874 struct_def
: &hir
::VariantData
<'_
>,
875 generics
: &hir
::Generics
<'_
>,
877 span
: rustc_span
::Span
,
878 print_finalizer
: bool
,
880 self.print_name(name
);
881 self.print_generic_params(&generics
.params
);
883 hir
::VariantData
::Tuple(..) | hir
::VariantData
::Unit(..) => {
884 if let hir
::VariantData
::Tuple(..) = struct_def
{
886 self.commasep(Inconsistent
, struct_def
.fields(), |s
, field
| {
887 s
.maybe_print_comment(field
.span
.lo());
888 s
.print_outer_attributes(&field
.attrs
);
889 s
.print_visibility(&field
.vis
);
890 s
.print_type(&field
.ty
)
894 self.print_where_clause(&generics
.where_clause
);
899 self.end() // close the outer-box
901 hir
::VariantData
::Struct(..) => {
902 self.print_where_clause(&generics
.where_clause
);
905 self.hardbreak_if_not_bol();
907 for field
in struct_def
.fields() {
908 self.hardbreak_if_not_bol();
909 self.maybe_print_comment(field
.span
.lo());
910 self.print_outer_attributes(&field
.attrs
);
911 self.print_visibility(&field
.vis
);
912 self.print_ident(field
.ident
);
914 self.print_type(&field
.ty
);
923 pub fn print_variant(&mut self, v
: &hir
::Variant
<'_
>) {
925 let generics
= hir
::Generics
::empty();
926 self.print_struct(&v
.data
, &generics
, v
.ident
.name
, v
.span
, false);
927 if let Some(ref d
) = v
.disr_expr
{
929 self.word_space("=");
930 self.print_anon_const(d
);
933 pub fn print_method_sig(
937 generics
: &hir
::Generics
<'_
>,
938 vis
: &hir
::Visibility
<'_
>,
940 body_id
: Option
<hir
::BodyId
>,
942 self.print_fn(&m
.decl
, m
.header
, Some(ident
.name
), generics
, vis
, arg_names
, body_id
)
945 pub fn print_trait_item(&mut self, ti
: &hir
::TraitItem
<'_
>) {
946 self.ann
.pre(self, AnnNode
::SubItem(ti
.hir_id
));
947 self.hardbreak_if_not_bol();
948 self.maybe_print_comment(ti
.span
.lo());
949 self.print_outer_attributes(&ti
.attrs
);
951 hir
::TraitItemKind
::Const(ref ty
, default) => {
953 Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited }
;
954 self.print_associated_const(ti
.ident
, &ty
, default, &vis
);
956 hir
::TraitItemKind
::Fn(ref sig
, hir
::TraitFn
::Required(ref arg_names
)) => {
958 Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited }
;
959 self.print_method_sig(ti
.ident
, sig
, &ti
.generics
, &vis
, arg_names
, None
);
962 hir
::TraitItemKind
::Fn(ref sig
, hir
::TraitFn
::Provided(body
)) => {
964 Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited }
;
966 self.print_method_sig(ti
.ident
, sig
, &ti
.generics
, &vis
, &[], Some(body
));
968 self.end(); // need to close a box
969 self.end(); // need to close a box
970 self.ann
.nested(self, Nested
::Body(body
));
972 hir
::TraitItemKind
::Type(ref bounds
, ref default) => {
973 self.print_associated_type(
977 default.as_ref().map(|ty
| &**ty
),
981 self.ann
.post(self, AnnNode
::SubItem(ti
.hir_id
))
984 pub fn print_impl_item(&mut self, ii
: &hir
::ImplItem
<'_
>) {
985 self.ann
.pre(self, AnnNode
::SubItem(ii
.hir_id
));
986 self.hardbreak_if_not_bol();
987 self.maybe_print_comment(ii
.span
.lo());
988 self.print_outer_attributes(&ii
.attrs
);
989 self.print_defaultness(ii
.defaultness
);
992 hir
::ImplItemKind
::Const(ref ty
, expr
) => {
993 self.print_associated_const(ii
.ident
, &ty
, Some(expr
), &ii
.vis
);
995 hir
::ImplItemKind
::Fn(ref sig
, body
) => {
997 self.print_method_sig(ii
.ident
, sig
, &ii
.generics
, &ii
.vis
, &[], Some(body
));
999 self.end(); // need to close a box
1000 self.end(); // need to close a box
1001 self.ann
.nested(self, Nested
::Body(body
));
1003 hir
::ImplItemKind
::TyAlias(ref ty
) => {
1004 self.print_associated_type(ii
.ident
, &ii
.generics
, None
, Some(ty
));
1007 self.ann
.post(self, AnnNode
::SubItem(ii
.hir_id
))
1010 pub fn print_local(&mut self, init
: Option
<&hir
::Expr
<'_
>>, decl
: impl Fn(&mut Self)) {
1011 self.space_if_not_bol();
1012 self.ibox(INDENT_UNIT
);
1013 self.word_nbsp("let");
1015 self.ibox(INDENT_UNIT
);
1019 if let Some(ref init
) = init
{
1021 self.word_space("=");
1022 self.print_expr(&init
);
1027 pub fn print_stmt(&mut self, st
: &hir
::Stmt
<'_
>) {
1028 self.maybe_print_comment(st
.span
.lo());
1030 hir
::StmtKind
::Local(ref loc
) => {
1031 self.print_local(loc
.init
.as_deref(), |this
| this
.print_local_decl(&loc
));
1033 hir
::StmtKind
::Item(item
) => self.ann
.nested(self, Nested
::Item(item
)),
1034 hir
::StmtKind
::Expr(ref expr
) => {
1035 self.space_if_not_bol();
1036 self.print_expr(&expr
);
1038 hir
::StmtKind
::Semi(ref expr
) => {
1039 self.space_if_not_bol();
1040 self.print_expr(&expr
);
1044 if stmt_ends_with_semi(&st
.kind
) {
1047 self.maybe_print_trailing_comment(st
.span
, None
)
1050 pub fn print_block(&mut self, blk
: &hir
::Block
<'_
>) {
1051 self.print_block_with_attrs(blk
, &[])
1054 pub fn print_block_unclosed(&mut self, blk
: &hir
::Block
<'_
>) {
1055 self.print_block_maybe_unclosed(blk
, &[], false)
1058 pub fn print_block_with_attrs(&mut self, blk
: &hir
::Block
<'_
>, attrs
: &[ast
::Attribute
]) {
1059 self.print_block_maybe_unclosed(blk
, attrs
, true)
1062 pub fn print_block_maybe_unclosed(
1064 blk
: &hir
::Block
<'_
>,
1065 attrs
: &[ast
::Attribute
],
1069 hir
::BlockCheckMode
::UnsafeBlock(..) => self.word_space("unsafe"),
1070 hir
::BlockCheckMode
::PushUnsafeBlock(..) => self.word_space("push_unsafe"),
1071 hir
::BlockCheckMode
::PopUnsafeBlock(..) => self.word_space("pop_unsafe"),
1072 hir
::BlockCheckMode
::DefaultBlock
=> (),
1074 self.maybe_print_comment(blk
.span
.lo());
1075 self.ann
.pre(self, AnnNode
::Block(blk
));
1078 self.print_inner_attributes(attrs
);
1080 for st
in blk
.stmts
{
1081 self.print_stmt(st
);
1083 if let Some(ref expr
) = blk
.expr
{
1084 self.space_if_not_bol();
1085 self.print_expr(&expr
);
1086 self.maybe_print_trailing_comment(expr
.span
, Some(blk
.span
.hi()));
1088 self.bclose_maybe_open(blk
.span
, close_box
);
1089 self.ann
.post(self, AnnNode
::Block(blk
))
1092 pub fn print_anon_const(&mut self, constant
: &hir
::AnonConst
) {
1093 self.ann
.nested(self, Nested
::Body(constant
.body
))
1096 fn print_call_post(&mut self, args
: &[hir
::Expr
<'_
>]) {
1098 self.commasep_exprs(Inconsistent
, args
);
1102 pub fn print_expr_maybe_paren(&mut self, expr
: &hir
::Expr
<'_
>, prec
: i8) {
1103 let needs_par
= expr
.precedence().order() < prec
;
1107 self.print_expr(expr
);
1113 /// Print an expr using syntax that's acceptable in a condition position, such as the `cond` in
1114 /// `if cond { ... }`.
1115 pub fn print_expr_as_cond(&mut self, expr
: &hir
::Expr
<'_
>) {
1116 let needs_par
= match expr
.kind
{
1117 // These cases need parens due to the parse error observed in #26461: `if return {}`
1118 // parses as the erroneous construct `if (return {})`, not `if (return) {}`.
1119 hir
::ExprKind
::Closure(..) | hir
::ExprKind
::Ret(..) | hir
::ExprKind
::Break(..) => true,
1121 _
=> contains_exterior_struct_lit(expr
),
1127 self.print_expr(expr
);
1133 fn print_expr_vec(&mut self, exprs
: &[hir
::Expr
<'_
>]) {
1134 self.ibox(INDENT_UNIT
);
1136 self.commasep_exprs(Inconsistent
, exprs
);
1141 fn print_expr_repeat(&mut self, element
: &hir
::Expr
<'_
>, count
: &hir
::AnonConst
) {
1142 self.ibox(INDENT_UNIT
);
1144 self.print_expr(element
);
1145 self.word_space(";");
1146 self.print_anon_const(count
);
1151 fn print_expr_struct(
1153 qpath
: &hir
::QPath
<'_
>,
1154 fields
: &[hir
::Field
<'_
>],
1155 wth
: &Option
<&hir
::Expr
<'_
>>,
1157 self.print_qpath(qpath
, true);
1163 s
.ibox(INDENT_UNIT
);
1164 if !field
.is_shorthand
{
1165 s
.print_ident(field
.ident
);
1168 s
.print_expr(&field
.expr
);
1175 self.ibox(INDENT_UNIT
);
1176 if !fields
.is_empty() {
1181 self.print_expr(&expr
);
1185 if !fields
.is_empty() {
1193 fn print_expr_tup(&mut self, exprs
: &[hir
::Expr
<'_
>]) {
1195 self.commasep_exprs(Inconsistent
, exprs
);
1196 if exprs
.len() == 1 {
1202 fn print_expr_call(&mut self, func
: &hir
::Expr
<'_
>, args
: &[hir
::Expr
<'_
>]) {
1203 let prec
= match func
.kind
{
1204 hir
::ExprKind
::Field(..) => parser
::PREC_FORCE_PAREN
,
1205 _
=> parser
::PREC_POSTFIX
,
1208 self.print_expr_maybe_paren(func
, prec
);
1209 self.print_call_post(args
)
1212 fn print_expr_method_call(&mut self, segment
: &hir
::PathSegment
<'_
>, args
: &[hir
::Expr
<'_
>]) {
1213 let base_args
= &args
[1..];
1214 self.print_expr_maybe_paren(&args
[0], parser
::PREC_POSTFIX
);
1216 self.print_ident(segment
.ident
);
1218 let generic_args
= segment
.generic_args();
1219 if !generic_args
.args
.is_empty() || !generic_args
.bindings
.is_empty() {
1220 self.print_generic_args(generic_args
, segment
.infer_args
, true);
1223 self.print_call_post(base_args
)
1226 fn print_expr_binary(&mut self, op
: hir
::BinOp
, lhs
: &hir
::Expr
<'_
>, rhs
: &hir
::Expr
<'_
>) {
1227 let assoc_op
= bin_op_to_assoc_op(op
.node
);
1228 let prec
= assoc_op
.precedence() as i8;
1229 let fixity
= assoc_op
.fixity();
1231 let (left_prec
, right_prec
) = match fixity
{
1232 Fixity
::Left
=> (prec
, prec
+ 1),
1233 Fixity
::Right
=> (prec
+ 1, prec
),
1234 Fixity
::None
=> (prec
+ 1, prec
+ 1),
1237 let left_prec
= match (&lhs
.kind
, op
.node
) {
1238 // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
1239 // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
1240 // of `(x as i32) < ...`. We need to convince it _not_ to do that.
1241 (&hir
::ExprKind
::Cast { .. }
, hir
::BinOpKind
::Lt
| hir
::BinOpKind
::Shl
) => {
1242 parser
::PREC_FORCE_PAREN
1247 self.print_expr_maybe_paren(lhs
, left_prec
);
1249 self.word_space(op
.node
.as_str());
1250 self.print_expr_maybe_paren(rhs
, right_prec
)
1253 fn print_expr_unary(&mut self, op
: hir
::UnOp
, expr
: &hir
::Expr
<'_
>) {
1254 self.s
.word(op
.as_str());
1255 self.print_expr_maybe_paren(expr
, parser
::PREC_PREFIX
)
1258 fn print_expr_addr_of(
1260 kind
: hir
::BorrowKind
,
1261 mutability
: hir
::Mutability
,
1262 expr
: &hir
::Expr
<'_
>,
1266 hir
::BorrowKind
::Ref
=> self.print_mutability(mutability
, false),
1267 hir
::BorrowKind
::Raw
=> {
1268 self.word_nbsp("raw");
1269 self.print_mutability(mutability
, true);
1272 self.print_expr_maybe_paren(expr
, parser
::PREC_PREFIX
)
1275 fn print_literal(&mut self, lit
: &hir
::Lit
) {
1276 self.maybe_print_comment(lit
.span
.lo());
1277 self.word(lit
.node
.to_lit_token().to_string())
1280 pub fn print_expr(&mut self, expr
: &hir
::Expr
<'_
>) {
1281 self.maybe_print_comment(expr
.span
.lo());
1282 self.print_outer_attributes(&expr
.attrs
);
1283 self.ibox(INDENT_UNIT
);
1284 self.ann
.pre(self, AnnNode
::Expr(expr
));
1286 hir
::ExprKind
::Box(ref expr
) => {
1287 self.word_space("box");
1288 self.print_expr_maybe_paren(expr
, parser
::PREC_PREFIX
);
1290 hir
::ExprKind
::Array(ref exprs
) => {
1291 self.print_expr_vec(exprs
);
1293 hir
::ExprKind
::Repeat(ref element
, ref count
) => {
1294 self.print_expr_repeat(&element
, count
);
1296 hir
::ExprKind
::Struct(ref qpath
, fields
, ref wth
) => {
1297 self.print_expr_struct(qpath
, fields
, wth
);
1299 hir
::ExprKind
::Tup(ref exprs
) => {
1300 self.print_expr_tup(exprs
);
1302 hir
::ExprKind
::Call(ref func
, ref args
) => {
1303 self.print_expr_call(&func
, args
);
1305 hir
::ExprKind
::MethodCall(ref segment
, _
, ref args
, _
) => {
1306 self.print_expr_method_call(segment
, args
);
1308 hir
::ExprKind
::Binary(op
, ref lhs
, ref rhs
) => {
1309 self.print_expr_binary(op
, &lhs
, &rhs
);
1311 hir
::ExprKind
::Unary(op
, ref expr
) => {
1312 self.print_expr_unary(op
, &expr
);
1314 hir
::ExprKind
::AddrOf(k
, m
, ref expr
) => {
1315 self.print_expr_addr_of(k
, m
, &expr
);
1317 hir
::ExprKind
::Lit(ref lit
) => {
1318 self.print_literal(&lit
);
1320 hir
::ExprKind
::Cast(ref expr
, ref ty
) => {
1321 let prec
= AssocOp
::As
.precedence() as i8;
1322 self.print_expr_maybe_paren(&expr
, prec
);
1324 self.word_space("as");
1325 self.print_type(&ty
);
1327 hir
::ExprKind
::Type(ref expr
, ref ty
) => {
1328 let prec
= AssocOp
::Colon
.precedence() as i8;
1329 self.print_expr_maybe_paren(&expr
, prec
);
1330 self.word_space(":");
1331 self.print_type(&ty
);
1333 hir
::ExprKind
::DropTemps(ref init
) => {
1335 self.cbox(INDENT_UNIT
);
1339 // Print `let _t = $init;`:
1340 let temp
= Ident
::from_str("_t");
1341 self.print_local(Some(init
), |this
| this
.print_ident(temp
));
1345 self.space_if_not_bol();
1346 self.print_ident(temp
);
1349 self.bclose_maybe_open(expr
.span
, true);
1351 hir
::ExprKind
::Loop(ref blk
, opt_label
, _
) => {
1352 if let Some(label
) = opt_label
{
1353 self.print_ident(label
.ident
);
1354 self.word_space(":");
1358 self.print_block(&blk
);
1360 hir
::ExprKind
::Match(ref expr
, arms
, _
) => {
1361 self.cbox(INDENT_UNIT
);
1362 self.ibox(INDENT_UNIT
);
1363 self.word_nbsp("match");
1364 self.print_expr_as_cond(&expr
);
1368 self.print_arm(arm
);
1370 self.bclose(expr
.span
);
1372 hir
::ExprKind
::Closure(capture_clause
, ref decl
, body
, _fn_decl_span
, _gen
) => {
1373 self.print_capture_clause(capture_clause
);
1375 self.print_closure_params(&decl
, body
);
1378 // This is a bare expression.
1379 self.ann
.nested(self, Nested
::Body(body
));
1380 self.end(); // need to close a box
1382 // A box will be closed by `print_expr`, but we didn't want an overall
1383 // wrapper so we closed the corresponding opening. so create an
1384 // empty box to satisfy the close.
1387 hir
::ExprKind
::Block(ref blk
, opt_label
) => {
1388 if let Some(label
) = opt_label
{
1389 self.print_ident(label
.ident
);
1390 self.word_space(":");
1392 // containing cbox, will be closed by print-block at `}`
1393 self.cbox(INDENT_UNIT
);
1394 // head-box, will be closed by print-block after `{`
1396 self.print_block(&blk
);
1398 hir
::ExprKind
::Assign(ref lhs
, ref rhs
, _
) => {
1399 let prec
= AssocOp
::Assign
.precedence() as i8;
1400 self.print_expr_maybe_paren(&lhs
, prec
+ 1);
1402 self.word_space("=");
1403 self.print_expr_maybe_paren(&rhs
, prec
);
1405 hir
::ExprKind
::AssignOp(op
, ref lhs
, ref rhs
) => {
1406 let prec
= AssocOp
::Assign
.precedence() as i8;
1407 self.print_expr_maybe_paren(&lhs
, prec
+ 1);
1409 self.s
.word(op
.node
.as_str());
1410 self.word_space("=");
1411 self.print_expr_maybe_paren(&rhs
, prec
);
1413 hir
::ExprKind
::Field(ref expr
, ident
) => {
1414 self.print_expr_maybe_paren(expr
, parser
::PREC_POSTFIX
);
1416 self.print_ident(ident
);
1418 hir
::ExprKind
::Index(ref expr
, ref index
) => {
1419 self.print_expr_maybe_paren(&expr
, parser
::PREC_POSTFIX
);
1421 self.print_expr(&index
);
1424 hir
::ExprKind
::Path(ref qpath
) => self.print_qpath(qpath
, true),
1425 hir
::ExprKind
::Break(destination
, ref opt_expr
) => {
1426 self.s
.word("break");
1428 if let Some(label
) = destination
.label
{
1429 self.print_ident(label
.ident
);
1432 if let Some(ref expr
) = *opt_expr
{
1433 self.print_expr_maybe_paren(expr
, parser
::PREC_JUMP
);
1437 hir
::ExprKind
::Continue(destination
) => {
1438 self.s
.word("continue");
1440 if let Some(label
) = destination
.label
{
1441 self.print_ident(label
.ident
);
1445 hir
::ExprKind
::Ret(ref result
) => {
1446 self.s
.word("return");
1447 if let Some(ref expr
) = *result
{
1449 self.print_expr_maybe_paren(&expr
, parser
::PREC_JUMP
);
1452 hir
::ExprKind
::InlineAsm(ref a
) => {
1455 Operand(&'a hir
::InlineAsmOperand
<'a
>),
1456 Options(ast
::InlineAsmOptions
),
1459 let mut args
= vec
![];
1460 args
.push(AsmArg
::Template(ast
::InlineAsmTemplatePiece
::to_string(&a
.template
)));
1461 args
.extend(a
.operands
.iter().map(|o
| AsmArg
::Operand(o
)));
1462 if !a
.options
.is_empty() {
1463 args
.push(AsmArg
::Options(a
.options
));
1468 self.commasep(Consistent
, &args
, |s
, arg
| match arg
{
1469 AsmArg
::Template(template
) => s
.print_string(&template
, ast
::StrStyle
::Cooked
),
1470 AsmArg
::Operand(op
) => match op
{
1471 hir
::InlineAsmOperand
::In { reg, expr }
=> {
1474 s
.word(format
!("{}", reg
));
1479 hir
::InlineAsmOperand
::Out { reg, late, expr }
=> {
1480 s
.word(if *late { "lateout" }
else { "out" }
);
1482 s
.word(format
!("{}", reg
));
1486 Some(expr
) => s
.print_expr(expr
),
1487 None
=> s
.word("_"),
1490 hir
::InlineAsmOperand
::InOut { reg, late, expr }
=> {
1491 s
.word(if *late { "inlateout" }
else { "inout" }
);
1493 s
.word(format
!("{}", reg
));
1498 hir
::InlineAsmOperand
::SplitInOut { reg, late, in_expr, out_expr }
=> {
1499 s
.word(if *late { "inlateout" }
else { "inout" }
);
1501 s
.word(format
!("{}", reg
));
1504 s
.print_expr(in_expr
);
1508 Some(out_expr
) => s
.print_expr(out_expr
),
1509 None
=> s
.word("_"),
1512 hir
::InlineAsmOperand
::Const { expr }
=> {
1517 hir
::InlineAsmOperand
::Sym { expr }
=> {
1523 AsmArg
::Options(opts
) => {
1526 let mut options
= vec
![];
1527 if opts
.contains(ast
::InlineAsmOptions
::PURE
) {
1528 options
.push("pure");
1530 if opts
.contains(ast
::InlineAsmOptions
::NOMEM
) {
1531 options
.push("nomem");
1533 if opts
.contains(ast
::InlineAsmOptions
::READONLY
) {
1534 options
.push("readonly");
1536 if opts
.contains(ast
::InlineAsmOptions
::PRESERVES_FLAGS
) {
1537 options
.push("preserves_flags");
1539 if opts
.contains(ast
::InlineAsmOptions
::NORETURN
) {
1540 options
.push("noreturn");
1542 if opts
.contains(ast
::InlineAsmOptions
::NOSTACK
) {
1543 options
.push("nostack");
1545 if opts
.contains(ast
::InlineAsmOptions
::ATT_SYNTAX
) {
1546 options
.push("att_syntax");
1548 s
.commasep(Inconsistent
, &options
, |s
, &opt
| {
1556 hir
::ExprKind
::LlvmInlineAsm(ref a
) => {
1558 self.s
.word("llvm_asm!");
1560 self.print_symbol(i
.asm
, i
.asm_str_style
);
1561 self.word_space(":");
1563 let mut out_idx
= 0;
1564 self.commasep(Inconsistent
, &i
.outputs
, |s
, out
| {
1565 let constraint
= out
.constraint
.as_str();
1566 let mut ch
= constraint
.chars();
1568 Some('
='
) if out
.is_rw
=> {
1569 s
.print_string(&format
!("+{}", ch
.as_str()), ast
::StrStyle
::Cooked
)
1571 _
=> s
.print_string(&constraint
, ast
::StrStyle
::Cooked
),
1574 s
.print_expr(&a
.outputs_exprs
[out_idx
]);
1579 self.word_space(":");
1582 self.commasep(Inconsistent
, &i
.inputs
, |s
, &co
| {
1583 s
.print_symbol(co
, ast
::StrStyle
::Cooked
);
1585 s
.print_expr(&a
.inputs_exprs
[in_idx
]);
1590 self.word_space(":");
1592 self.commasep(Inconsistent
, &i
.clobbers
, |s
, &co
| {
1593 s
.print_symbol(co
, ast
::StrStyle
::Cooked
);
1596 let mut options
= vec
![];
1598 options
.push("volatile");
1601 options
.push("alignstack");
1603 if i
.dialect
== ast
::LlvmAsmDialect
::Intel
{
1604 options
.push("intel");
1607 if !options
.is_empty() {
1609 self.word_space(":");
1610 self.commasep(Inconsistent
, &options
, |s
, &co
| {
1611 s
.print_string(co
, ast
::StrStyle
::Cooked
);
1617 hir
::ExprKind
::Yield(ref expr
, _
) => {
1618 self.word_space("yield");
1619 self.print_expr_maybe_paren(&expr
, parser
::PREC_JUMP
);
1621 hir
::ExprKind
::Err
=> {
1623 self.s
.word("/*ERROR*/");
1627 self.ann
.post(self, AnnNode
::Expr(expr
));
1631 pub fn print_local_decl(&mut self, loc
: &hir
::Local
<'_
>) {
1632 self.print_pat(&loc
.pat
);
1633 if let Some(ref ty
) = loc
.ty
{
1634 self.word_space(":");
1635 self.print_type(&ty
);
1639 pub fn print_usize(&mut self, i
: usize) {
1640 self.s
.word(i
.to_string())
1643 pub fn print_name(&mut self, name
: Symbol
) {
1644 self.print_ident(Ident
::with_dummy_span(name
))
1647 pub fn print_for_decl(&mut self, loc
: &hir
::Local
<'_
>, coll
: &hir
::Expr
<'_
>) {
1648 self.print_local_decl(loc
);
1650 self.word_space("in");
1651 self.print_expr(coll
)
1654 pub fn print_path(&mut self, path
: &hir
::Path
<'_
>, colons_before_params
: bool
) {
1655 self.maybe_print_comment(path
.span
.lo());
1657 for (i
, segment
) in path
.segments
.iter().enumerate() {
1661 if segment
.ident
.name
!= kw
::PathRoot
{
1662 self.print_ident(segment
.ident
);
1663 self.print_generic_args(
1664 segment
.generic_args(),
1666 colons_before_params
,
1672 pub fn print_path_segment(&mut self, segment
: &hir
::PathSegment
<'_
>) {
1673 if segment
.ident
.name
!= kw
::PathRoot
{
1674 self.print_ident(segment
.ident
);
1675 self.print_generic_args(segment
.generic_args(), segment
.infer_args
, false);
1679 pub fn print_qpath(&mut self, qpath
: &hir
::QPath
<'_
>, colons_before_params
: bool
) {
1681 hir
::QPath
::Resolved(None
, ref path
) => self.print_path(path
, colons_before_params
),
1682 hir
::QPath
::Resolved(Some(ref qself
), ref path
) => {
1684 self.print_type(qself
);
1686 self.word_space("as");
1688 for (i
, segment
) in path
.segments
[..path
.segments
.len() - 1].iter().enumerate() {
1692 if segment
.ident
.name
!= kw
::PathRoot
{
1693 self.print_ident(segment
.ident
);
1694 self.print_generic_args(
1695 segment
.generic_args(),
1697 colons_before_params
,
1704 let item_segment
= path
.segments
.last().unwrap();
1705 self.print_ident(item_segment
.ident
);
1706 self.print_generic_args(
1707 item_segment
.generic_args(),
1708 item_segment
.infer_args
,
1709 colons_before_params
,
1712 hir
::QPath
::TypeRelative(ref qself
, ref item_segment
) => {
1713 // If we've got a compound-qualified-path, let's push an additional pair of angle
1714 // brackets, so that we pretty-print `<<A::B>::C>` as `<A::B>::C`, instead of just
1715 // `A::B::C` (since the latter could be ambiguous to the user)
1716 if let hir
::TyKind
::Path(hir
::QPath
::Resolved(None
, _
)) = &qself
.kind
{
1717 self.print_type(qself
);
1720 self.print_type(qself
);
1725 self.print_ident(item_segment
.ident
);
1726 self.print_generic_args(
1727 item_segment
.generic_args(),
1728 item_segment
.infer_args
,
1729 colons_before_params
,
1732 hir
::QPath
::LangItem(lang_item
, span
) => {
1733 self.s
.word("#[lang = \"");
1734 self.print_ident(Ident
::new(lang_item
.name(), span
));
1740 fn print_generic_args(
1742 generic_args
: &hir
::GenericArgs
<'_
>,
1744 colons_before_params
: bool
,
1746 if generic_args
.parenthesized
{
1748 self.commasep(Inconsistent
, generic_args
.inputs(), |s
, ty
| s
.print_type(&ty
));
1751 self.space_if_not_bol();
1752 self.word_space("->");
1753 self.print_type(generic_args
.bindings
[0].ty());
1755 let start
= if colons_before_params { "::<" }
else { "<" }
;
1756 let empty
= Cell
::new(true);
1757 let start_or_comma
= |this
: &mut Self| {
1762 this
.word_space(",")
1766 let mut nonelided_generic_args
: bool
= false;
1767 let elide_lifetimes
= generic_args
.args
.iter().all(|arg
| match arg
{
1768 GenericArg
::Lifetime(lt
) => lt
.is_elided(),
1770 nonelided_generic_args
= true;
1775 if nonelided_generic_args
{
1776 start_or_comma(self);
1780 |s
, generic_arg
| match generic_arg
{
1781 GenericArg
::Lifetime(lt
) if !elide_lifetimes
=> s
.print_lifetime(lt
),
1782 GenericArg
::Lifetime(_
) => {}
1783 GenericArg
::Type(ty
) => s
.print_type(ty
),
1784 GenericArg
::Const(ct
) => s
.print_anon_const(&ct
.value
),
1789 // FIXME(eddyb): this would leak into error messages (e.g.,
1790 // "non-exhaustive patterns: `Some::<..>(_)` not covered").
1791 if infer_args
&& false {
1792 start_or_comma(self);
1796 for binding
in generic_args
.bindings
.iter() {
1797 start_or_comma(self);
1798 self.print_ident(binding
.ident
);
1800 match generic_args
.bindings
[0].kind
{
1801 hir
::TypeBindingKind
::Equality { ref ty }
=> {
1802 self.word_space("=");
1803 self.print_type(ty
);
1805 hir
::TypeBindingKind
::Constraint { bounds }
=> {
1806 self.print_bounds(":", bounds
);
1817 pub fn print_pat(&mut self, pat
: &hir
::Pat
<'_
>) {
1818 self.maybe_print_comment(pat
.span
.lo());
1819 self.ann
.pre(self, AnnNode
::Pat(pat
));
1820 // Pat isn't normalized, but the beauty of it
1821 // is that it doesn't matter
1823 PatKind
::Wild
=> self.s
.word("_"),
1824 PatKind
::Binding(binding_mode
, _
, ident
, ref sub
) => {
1825 match binding_mode
{
1826 hir
::BindingAnnotation
::Ref
=> {
1827 self.word_nbsp("ref");
1828 self.print_mutability(hir
::Mutability
::Not
, false);
1830 hir
::BindingAnnotation
::RefMut
=> {
1831 self.word_nbsp("ref");
1832 self.print_mutability(hir
::Mutability
::Mut
, false);
1834 hir
::BindingAnnotation
::Unannotated
=> {}
1835 hir
::BindingAnnotation
::Mutable
=> {
1836 self.word_nbsp("mut");
1839 self.print_ident(ident
);
1840 if let Some(ref p
) = *sub
{
1845 PatKind
::TupleStruct(ref qpath
, ref elts
, ddpos
) => {
1846 self.print_qpath(qpath
, true);
1848 if let Some(ddpos
) = ddpos
{
1849 self.commasep(Inconsistent
, &elts
[..ddpos
], |s
, p
| s
.print_pat(&p
));
1851 self.word_space(",");
1854 if ddpos
!= elts
.len() {
1856 self.commasep(Inconsistent
, &elts
[ddpos
..], |s
, p
| s
.print_pat(&p
));
1859 self.commasep(Inconsistent
, &elts
[..], |s
, p
| s
.print_pat(&p
));
1863 PatKind
::Path(ref qpath
) => {
1864 self.print_qpath(qpath
, true);
1866 PatKind
::Struct(ref qpath
, ref fields
, etc
) => {
1867 self.print_qpath(qpath
, true);
1869 self.word_space("{");
1874 s
.cbox(INDENT_UNIT
);
1875 if !f
.is_shorthand
{
1876 s
.print_ident(f
.ident
);
1879 s
.print_pat(&f
.pat
);
1885 if !fields
.is_empty() {
1886 self.word_space(",");
1893 PatKind
::Or(ref pats
) => {
1894 self.strsep("|", true, Inconsistent
, &pats
[..], |s
, p
| s
.print_pat(&p
));
1896 PatKind
::Tuple(ref elts
, ddpos
) => {
1898 if let Some(ddpos
) = ddpos
{
1899 self.commasep(Inconsistent
, &elts
[..ddpos
], |s
, p
| s
.print_pat(&p
));
1901 self.word_space(",");
1904 if ddpos
!= elts
.len() {
1906 self.commasep(Inconsistent
, &elts
[ddpos
..], |s
, p
| s
.print_pat(&p
));
1909 self.commasep(Inconsistent
, &elts
[..], |s
, p
| s
.print_pat(&p
));
1910 if elts
.len() == 1 {
1916 PatKind
::Box(ref inner
) => {
1917 let is_range_inner
= match inner
.kind
{
1918 PatKind
::Range(..) => true,
1921 self.s
.word("box ");
1925 self.print_pat(&inner
);
1930 PatKind
::Ref(ref inner
, mutbl
) => {
1931 let is_range_inner
= match inner
.kind
{
1932 PatKind
::Range(..) => true,
1936 self.s
.word(mutbl
.prefix_str());
1940 self.print_pat(&inner
);
1945 PatKind
::Lit(ref e
) => self.print_expr(&e
),
1946 PatKind
::Range(ref begin
, ref end
, ref end_kind
) => {
1947 if let Some(expr
) = begin
{
1948 self.print_expr(expr
);
1952 RangeEnd
::Included
=> self.s
.word("..."),
1953 RangeEnd
::Excluded
=> self.s
.word(".."),
1955 if let Some(expr
) = end
{
1956 self.print_expr(expr
);
1959 PatKind
::Slice(ref before
, ref slice
, ref after
) => {
1961 self.commasep(Inconsistent
, &before
[..], |s
, p
| s
.print_pat(&p
));
1962 if let Some(ref p
) = *slice
{
1963 if !before
.is_empty() {
1964 self.word_space(",");
1966 if let PatKind
::Wild
= p
.kind
{
1972 if !after
.is_empty() {
1973 self.word_space(",");
1976 self.commasep(Inconsistent
, &after
[..], |s
, p
| s
.print_pat(&p
));
1980 self.ann
.post(self, AnnNode
::Pat(pat
))
1983 pub fn print_param(&mut self, arg
: &hir
::Param
<'_
>) {
1984 self.print_outer_attributes(&arg
.attrs
);
1985 self.print_pat(&arg
.pat
);
1988 pub fn print_arm(&mut self, arm
: &hir
::Arm
<'_
>) {
1989 // I have no idea why this check is necessary, but here it
1991 if arm
.attrs
.is_empty() {
1994 self.cbox(INDENT_UNIT
);
1995 self.ann
.pre(self, AnnNode
::Arm(arm
));
1997 self.print_outer_attributes(&arm
.attrs
);
1998 self.print_pat(&arm
.pat
);
2000 if let Some(ref g
) = arm
.guard
{
2002 hir
::Guard
::If(e
) => {
2003 self.word_space("if");
2004 self.print_expr(&e
);
2009 self.word_space("=>");
2011 match arm
.body
.kind
{
2012 hir
::ExprKind
::Block(ref blk
, opt_label
) => {
2013 if let Some(label
) = opt_label
{
2014 self.print_ident(label
.ident
);
2015 self.word_space(":");
2017 // the block will close the pattern's ibox
2018 self.print_block_unclosed(&blk
);
2020 // If it is a user-provided unsafe block, print a comma after it
2021 if let hir
::BlockCheckMode
::UnsafeBlock(hir
::UnsafeSource
::UserProvided
) = blk
.rules
2027 self.end(); // close the ibox for the pattern
2028 self.print_expr(&arm
.body
);
2032 self.ann
.post(self, AnnNode
::Arm(arm
));
2033 self.end() // close enclosing cbox
2038 decl
: &hir
::FnDecl
<'_
>,
2039 header
: hir
::FnHeader
,
2040 name
: Option
<Symbol
>,
2041 generics
: &hir
::Generics
<'_
>,
2042 vis
: &hir
::Visibility
<'_
>,
2043 arg_names
: &[Ident
],
2044 body_id
: Option
<hir
::BodyId
>,
2046 self.print_fn_header_info(header
, vis
);
2048 if let Some(name
) = name
{
2050 self.print_name(name
);
2052 self.print_generic_params(&generics
.params
);
2056 // Make sure we aren't supplied *both* `arg_names` and `body_id`.
2057 assert
!(arg_names
.is_empty() || body_id
.is_none());
2058 self.commasep(Inconsistent
, &decl
.inputs
, |s
, ty
| {
2059 s
.ibox(INDENT_UNIT
);
2060 if let Some(arg_name
) = arg_names
.get(i
) {
2061 s
.s
.word(arg_name
.to_string());
2064 } else if let Some(body_id
) = body_id
{
2065 s
.ann
.nested(s
, Nested
::BodyParamPat(body_id
, i
));
2073 if decl
.c_variadic
{
2074 self.s
.word(", ...");
2078 self.print_fn_output(decl
);
2079 self.print_where_clause(&generics
.where_clause
)
2082 fn print_closure_params(&mut self, decl
: &hir
::FnDecl
<'_
>, body_id
: hir
::BodyId
) {
2085 self.commasep(Inconsistent
, &decl
.inputs
, |s
, ty
| {
2086 s
.ibox(INDENT_UNIT
);
2088 s
.ann
.nested(s
, Nested
::BodyParamPat(body_id
, i
));
2091 if let hir
::TyKind
::Infer
= ty
.kind
{
2102 if let hir
::FnRetTy
::DefaultReturn(..) = decl
.output
{
2106 self.space_if_not_bol();
2107 self.word_space("->");
2109 hir
::FnRetTy
::Return(ref ty
) => {
2110 self.print_type(&ty
);
2111 self.maybe_print_comment(ty
.span
.lo())
2113 hir
::FnRetTy
::DefaultReturn(..) => unreachable
!(),
2117 pub fn print_capture_clause(&mut self, capture_clause
: hir
::CaptureBy
) {
2118 match capture_clause
{
2119 hir
::CaptureBy
::Value
=> self.word_space("move"),
2120 hir
::CaptureBy
::Ref
=> {}
2124 pub fn print_bounds
<'b
>(
2126 prefix
: &'
static str,
2127 bounds
: impl IntoIterator
<Item
= &'b hir
::GenericBound
<'b
>>,
2129 let mut first
= true;
2130 for bound
in bounds
{
2132 self.s
.word(prefix
);
2134 if !(first
&& prefix
.is_empty()) {
2140 self.word_space("+");
2144 GenericBound
::Trait(tref
, modifier
) => {
2145 if modifier
== &TraitBoundModifier
::Maybe
{
2148 self.print_poly_trait_ref(tref
);
2150 GenericBound
::LangItemTrait(lang_item
, span
, ..) => {
2151 self.s
.word("#[lang = \"");
2152 self.print_ident(Ident
::new(lang_item
.name(), *span
));
2155 GenericBound
::Outlives(lt
) => {
2156 self.print_lifetime(lt
);
2162 pub fn print_generic_params(&mut self, generic_params
: &[GenericParam
<'_
>]) {
2163 if !generic_params
.is_empty() {
2166 self.commasep(Inconsistent
, generic_params
, |s
, param
| s
.print_generic_param(param
));
2172 pub fn print_generic_param(&mut self, param
: &GenericParam
<'_
>) {
2173 if let GenericParamKind
::Const { .. }
= param
.kind
{
2174 self.word_space("const");
2177 self.print_ident(param
.name
.ident());
2180 GenericParamKind
::Lifetime { .. }
=> {
2182 for bound
in param
.bounds
{
2184 GenericBound
::Outlives(ref lt
) => {
2186 self.print_lifetime(lt
);
2193 GenericParamKind
::Type { ref default, .. }
=> {
2194 self.print_bounds(":", param
.bounds
);
2195 if let Some(default) = default {
2197 self.word_space("=");
2198 self.print_type(&default)
2201 GenericParamKind
::Const { ref ty }
=> {
2202 self.word_space(":");
2208 pub fn print_lifetime(&mut self, lifetime
: &hir
::Lifetime
) {
2209 self.print_ident(lifetime
.name
.ident())
2212 pub fn print_where_clause(&mut self, where_clause
: &hir
::WhereClause
<'_
>) {
2213 if where_clause
.predicates
.is_empty() {
2218 self.word_space("where");
2220 for (i
, predicate
) in where_clause
.predicates
.iter().enumerate() {
2222 self.word_space(",");
2226 &hir
::WherePredicate
::BoundPredicate(hir
::WhereBoundPredicate
{
2227 ref bound_generic_params
,
2232 self.print_formal_generic_params(bound_generic_params
);
2233 self.print_type(&bounded_ty
);
2234 self.print_bounds(":", bounds
);
2236 &hir
::WherePredicate
::RegionPredicate(hir
::WhereRegionPredicate
{
2241 self.print_lifetime(lifetime
);
2244 for (i
, bound
) in bounds
.iter().enumerate() {
2246 GenericBound
::Outlives(lt
) => {
2247 self.print_lifetime(lt
);
2257 &hir
::WherePredicate
::EqPredicate(hir
::WhereEqPredicate
{
2262 self.print_type(lhs_ty
);
2264 self.word_space("=");
2265 self.print_type(rhs_ty
);
2271 pub fn print_mutability(&mut self, mutbl
: hir
::Mutability
, print_const
: bool
) {
2273 hir
::Mutability
::Mut
=> self.word_nbsp("mut"),
2274 hir
::Mutability
::Not
=> {
2276 self.word_nbsp("const")
2282 pub fn print_mt(&mut self, mt
: &hir
::MutTy
<'_
>, print_const
: bool
) {
2283 self.print_mutability(mt
.mutbl
, print_const
);
2284 self.print_type(&mt
.ty
)
2287 pub fn print_fn_output(&mut self, decl
: &hir
::FnDecl
<'_
>) {
2288 if let hir
::FnRetTy
::DefaultReturn(..) = decl
.output
{
2292 self.space_if_not_bol();
2293 self.ibox(INDENT_UNIT
);
2294 self.word_space("->");
2296 hir
::FnRetTy
::DefaultReturn(..) => unreachable
!(),
2297 hir
::FnRetTy
::Return(ref ty
) => self.print_type(&ty
),
2301 if let hir
::FnRetTy
::Return(ref output
) = decl
.output
{
2302 self.maybe_print_comment(output
.span
.lo())
2309 unsafety
: hir
::Unsafety
,
2310 decl
: &hir
::FnDecl
<'_
>,
2311 name
: Option
<Symbol
>,
2312 generic_params
: &[hir
::GenericParam
<'_
>],
2313 arg_names
: &[Ident
],
2315 self.ibox(INDENT_UNIT
);
2316 if !generic_params
.is_empty() {
2318 self.print_generic_params(generic_params
);
2320 let generics
= hir
::Generics
{
2322 where_clause
: hir
::WhereClause { predicates: &[], span: rustc_span::DUMMY_SP }
,
2323 span
: rustc_span
::DUMMY_SP
,
2330 constness
: hir
::Constness
::NotConst
,
2331 asyncness
: hir
::IsAsync
::NotAsync
,
2335 &Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited }
,
2342 pub fn maybe_print_trailing_comment(
2344 span
: rustc_span
::Span
,
2345 next_pos
: Option
<BytePos
>,
2347 if let Some(cmnts
) = self.comments() {
2348 if let Some(cmnt
) = cmnts
.trailing_comment(span
, next_pos
) {
2349 self.print_comment(&cmnt
);
2354 pub fn print_remaining_comments(&mut self) {
2355 // If there aren't any remaining comments, then we need to manually
2356 // make sure there is a line break at the end.
2357 if self.next_comment().is_none() {
2360 while let Some(ref cmnt
) = self.next_comment() {
2361 self.print_comment(cmnt
)
2365 pub fn print_opt_abi_and_extern_if_nondefault(&mut self, opt_abi
: Option
<Abi
>) {
2367 Some(Abi
::Rust
) => {}
2369 self.word_nbsp("extern");
2370 self.word_nbsp(abi
.to_string())
2376 pub fn print_extern_opt_abi(&mut self, opt_abi
: Option
<Abi
>) {
2377 if let Some(abi
) = opt_abi
{
2378 self.word_nbsp("extern");
2379 self.word_nbsp(abi
.to_string())
2383 pub fn print_fn_header_info(&mut self, header
: hir
::FnHeader
, vis
: &hir
::Visibility
<'_
>) {
2384 self.s
.word(visibility_qualified(vis
, ""));
2386 match header
.constness
{
2387 hir
::Constness
::NotConst
=> {}
2388 hir
::Constness
::Const
=> self.word_nbsp("const"),
2391 match header
.asyncness
{
2392 hir
::IsAsync
::NotAsync
=> {}
2393 hir
::IsAsync
::Async
=> self.word_nbsp("async"),
2396 self.print_unsafety(header
.unsafety
);
2398 if header
.abi
!= Abi
::Rust
{
2399 self.word_nbsp("extern");
2400 self.word_nbsp(header
.abi
.to_string());
2406 pub fn print_unsafety(&mut self, s
: hir
::Unsafety
) {
2408 hir
::Unsafety
::Normal
=> {}
2409 hir
::Unsafety
::Unsafe
=> self.word_nbsp("unsafe"),
2413 pub fn print_is_auto(&mut self, s
: hir
::IsAuto
) {
2415 hir
::IsAuto
::Yes
=> self.word_nbsp("auto"),
2416 hir
::IsAuto
::No
=> {}
2421 /// Does this expression require a semicolon to be treated
2422 /// as a statement? The negation of this: 'can this expression
2423 /// be used as a statement without a semicolon' -- is used
2424 /// as an early-bail-out in the parser so that, for instance,
2425 /// if true {...} else {...}
2427 /// isn't parsed as (if true {...} else {...} | x) | 5
2429 // Duplicated from `parse::classify`, but adapted for the HIR.
2430 fn expr_requires_semi_to_be_stmt(e
: &hir
::Expr
<'_
>) -> bool
{
2432 hir
::ExprKind
::Match(..) | hir
::ExprKind
::Block(..) | hir
::ExprKind
::Loop(..) => false,
2437 /// This statement requires a semicolon after it.
2438 /// note that in one case (stmt_semi), we've already
2439 /// seen the semicolon, and thus don't need another.
2440 fn stmt_ends_with_semi(stmt
: &hir
::StmtKind
<'_
>) -> bool
{
2442 hir
::StmtKind
::Local(_
) => true,
2443 hir
::StmtKind
::Item(_
) => false,
2444 hir
::StmtKind
::Expr(ref e
) => expr_requires_semi_to_be_stmt(&e
),
2445 hir
::StmtKind
::Semi(..) => false,
2449 fn bin_op_to_assoc_op(op
: hir
::BinOpKind
) -> AssocOp
{
2450 use crate::hir
::BinOpKind
::*;
2452 Add
=> AssocOp
::Add
,
2453 Sub
=> AssocOp
::Subtract
,
2454 Mul
=> AssocOp
::Multiply
,
2455 Div
=> AssocOp
::Divide
,
2456 Rem
=> AssocOp
::Modulus
,
2458 And
=> AssocOp
::LAnd
,
2461 BitXor
=> AssocOp
::BitXor
,
2462 BitAnd
=> AssocOp
::BitAnd
,
2463 BitOr
=> AssocOp
::BitOr
,
2464 Shl
=> AssocOp
::ShiftLeft
,
2465 Shr
=> AssocOp
::ShiftRight
,
2467 Eq
=> AssocOp
::Equal
,
2468 Lt
=> AssocOp
::Less
,
2469 Le
=> AssocOp
::LessEqual
,
2470 Ne
=> AssocOp
::NotEqual
,
2471 Ge
=> AssocOp
::GreaterEqual
,
2472 Gt
=> AssocOp
::Greater
,
2476 /// Expressions that syntactically contain an "exterior" struct literal, i.e., not surrounded by any
2477 /// parens or other delimiters, e.g., `X { y: 1 }`, `X { y: 1 }.method()`, `foo == X { y: 1 }` and
2478 /// `X { y: 1 } == foo` all do, but `(X { y: 1 }) == foo` does not.
2479 fn contains_exterior_struct_lit(value
: &hir
::Expr
<'_
>) -> bool
{
2481 hir
::ExprKind
::Struct(..) => true,
2483 hir
::ExprKind
::Assign(ref lhs
, ref rhs
, _
)
2484 | hir
::ExprKind
::AssignOp(_
, ref lhs
, ref rhs
)
2485 | hir
::ExprKind
::Binary(_
, ref lhs
, ref rhs
) => {
2486 // `X { y: 1 } + X { y: 2 }`
2487 contains_exterior_struct_lit(&lhs
) || contains_exterior_struct_lit(&rhs
)
2489 hir
::ExprKind
::Unary(_
, ref x
)
2490 | hir
::ExprKind
::Cast(ref x
, _
)
2491 | hir
::ExprKind
::Type(ref x
, _
)
2492 | hir
::ExprKind
::Field(ref x
, _
)
2493 | hir
::ExprKind
::Index(ref x
, _
) => {
2494 // `&X { y: 1 }, X { y: 1 }.y`
2495 contains_exterior_struct_lit(&x
)
2498 hir
::ExprKind
::MethodCall(.., ref exprs
, _
) => {
2499 // `X { y: 1 }.bar(...)`
2500 contains_exterior_struct_lit(&exprs
[0])