1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 pub use self::AnnNode
::*;
15 use syntax
::codemap
::{CodeMap, Spanned}
;
16 use syntax
::parse
::ParseSess
;
17 use syntax
::parse
::lexer
::comments
;
18 use syntax
::print
::pp
::{self, Breaks}
;
19 use syntax
::print
::pp
::Breaks
::{Consistent, Inconsistent}
;
20 use syntax
::print
::pprust
::PrintState
;
22 use syntax
::symbol
::keywords
;
23 use syntax
::util
::parser
::{self, AssocOp, Fixity}
;
24 use syntax_pos
::{self, BytePos}
;
27 use hir
::{PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier, RangeEnd}
;
30 use std
::io
::{self, Write, Read}
;
31 use std
::iter
::Peekable
;
34 pub enum AnnNode
<'a
> {
35 NodeName(&'a ast
::Name
),
36 NodeBlock(&'a hir
::Block
),
37 NodeItem(&'a hir
::Item
),
38 NodeSubItem(ast
::NodeId
),
39 NodeExpr(&'a hir
::Expr
),
40 NodePat(&'a hir
::Pat
),
45 TraitItem(hir
::TraitItemId
),
46 ImplItem(hir
::ImplItemId
),
48 BodyArgPat(hir
::BodyId
, usize)
52 fn nested(&self, _state
: &mut State
, _nested
: Nested
) -> io
::Result
<()> {
55 fn pre(&self, _state
: &mut State
, _node
: AnnNode
) -> io
::Result
<()> {
58 fn post(&self, _state
: &mut State
, _node
: AnnNode
) -> io
::Result
<()> {
64 impl PpAnn
for NoAnn {}
65 pub const NO_ANN
: &'
static PpAnn
= &NoAnn
;
67 impl PpAnn
for hir
::Crate
{
68 fn nested(&self, state
: &mut State
, nested
: Nested
) -> io
::Result
<()> {
70 Nested
::Item(id
) => state
.print_item(self.item(id
.id
)),
71 Nested
::TraitItem(id
) => state
.print_trait_item(self.trait_item(id
)),
72 Nested
::ImplItem(id
) => state
.print_impl_item(self.impl_item(id
)),
73 Nested
::Body(id
) => state
.print_expr(&self.body(id
).value
),
74 Nested
::BodyArgPat(id
, i
) => state
.print_pat(&self.body(id
).arguments
[i
].pat
)
79 pub struct State
<'a
> {
80 pub s
: pp
::Printer
<'a
>,
81 cm
: Option
<&'a CodeMap
>,
82 comments
: Option
<Vec
<comments
::Comment
>>,
83 literals
: Peekable
<vec
::IntoIter
<comments
::Literal
>>,
85 boxes
: Vec
<pp
::Breaks
>,
86 ann
: &'
a (PpAnn
+ 'a
),
89 impl<'a
> PrintState
<'a
> for State
<'a
> {
90 fn writer(&mut self) -> &mut pp
::Printer
<'a
> {
94 fn boxes(&mut self) -> &mut Vec
<pp
::Breaks
> {
98 fn comments(&mut self) -> &mut Option
<Vec
<comments
::Comment
>> {
102 fn cur_cmnt(&mut self) -> &mut usize {
106 fn cur_lit(&mut self) -> Option
<&comments
::Literal
> {
110 fn bump_lit(&mut self) -> Option
<comments
::Literal
> {
115 #[allow(non_upper_case_globals)]
116 pub const indent_unit
: usize = 4;
118 #[allow(non_upper_case_globals)]
119 pub const default_columns
: usize = 78;
122 /// Requires you to pass an input filename and reader so that
123 /// it can scan the input text for comments and literals to
125 pub fn print_crate
<'a
>(cm
: &'a CodeMap
,
130 out
: Box
<Write
+ 'a
>,
134 let mut s
= State
::new_from_input(cm
, sess
, filename
, input
, out
, ann
, is_expanded
);
136 // When printing the AST, we sometimes need to inject `#[no_std]` here.
137 // Since you can't compile the HIR, it's not necessary.
139 s
.print_mod(&krate
.module
, &krate
.attrs
)?
;
140 s
.print_remaining_comments()?
;
145 pub fn new_from_input(cm
: &'a CodeMap
,
149 out
: Box
<Write
+ 'a
>,
153 let (cmnts
, lits
) = comments
::gather_comments_and_literals(sess
, filename
, input
);
159 // If the code is post expansion, don't use the table of
160 // literals, since it doesn't correspond with the literals
161 // in the AST anymore.
169 pub fn new(cm
: &'a CodeMap
,
170 out
: Box
<Write
+ 'a
>,
172 comments
: Option
<Vec
<comments
::Comment
>>,
173 literals
: Option
<Vec
<comments
::Literal
>>)
176 s
: pp
::mk_printer(out
, default_columns
),
178 comments
: comments
.clone(),
179 literals
: literals
.unwrap_or_default().into_iter().peekable(),
187 pub fn to_string
<F
>(ann
: &PpAnn
, f
: F
) -> String
188 where F
: FnOnce(&mut State
) -> io
::Result
<()>
190 let mut wr
= Vec
::new();
192 let mut printer
= State
{
193 s
: pp
::mk_printer(Box
::new(&mut wr
), default_columns
),
196 literals
: vec
![].into_iter().peekable(),
201 f(&mut printer
).unwrap();
202 printer
.s
.eof().unwrap();
204 String
::from_utf8(wr
).unwrap()
207 pub fn visibility_qualified(vis
: &hir
::Visibility
, w
: &str) -> String
{
208 to_string(NO_ANN
, |s
| {
209 s
.print_visibility(vis
)?
;
215 pub fn cbox(&mut self, u
: usize) -> io
::Result
<()> {
216 self.boxes
.push(pp
::Breaks
::Consistent
);
220 pub fn nbsp(&mut self) -> io
::Result
<()> {
224 pub fn word_nbsp(&mut self, w
: &str) -> io
::Result
<()> {
229 pub fn head(&mut self, w
: &str) -> io
::Result
<()> {
230 // outer-box is consistent
231 self.cbox(indent_unit
)?
;
232 // head-box is inconsistent
233 self.ibox(w
.len() + 1)?
;
234 // keyword that starts the head
241 pub fn bopen(&mut self) -> io
::Result
<()> {
243 self.end() // close the head-box
246 pub fn bclose_(&mut self, span
: syntax_pos
::Span
, indented
: usize) -> io
::Result
<()> {
247 self.bclose_maybe_open(span
, indented
, true)
249 pub fn bclose_maybe_open(&mut self,
250 span
: syntax_pos
::Span
,
254 self.maybe_print_comment(span
.hi())?
;
255 self.break_offset_if_not_bol(1, -(indented
as isize))?
;
258 self.end()?
; // close the outer-box
262 pub fn bclose(&mut self, span
: syntax_pos
::Span
) -> io
::Result
<()> {
263 self.bclose_(span
, indent_unit
)
266 pub fn in_cbox(&self) -> bool
{
267 match self.boxes
.last() {
268 Some(&last_box
) => last_box
== pp
::Breaks
::Consistent
,
272 pub fn space_if_not_bol(&mut self) -> io
::Result
<()> {
278 pub fn break_offset_if_not_bol(&mut self, n
: usize, off
: isize) -> io
::Result
<()> {
280 self.s
.break_offset(n
, off
)
282 if off
!= 0 && self.s
.last_token().is_hardbreak_tok() {
283 // We do something pretty sketchy here: tuck the nonzero
284 // offset-adjustment we were going to deposit along with the
285 // break into the previous hardbreak.
286 self.s
.replace_last_token(pp
::Printer
::hardbreak_tok_offset(off
));
292 // Synthesizes a comment that was not textually present in the original source
294 pub fn synth_comment(&mut self, text
: String
) -> io
::Result
<()> {
297 self.s
.word(&text
[..])?
;
303 pub fn commasep_cmnt
<T
, F
, G
>(&mut self,
309 where F
: FnMut(&mut State
, &T
) -> io
::Result
<()>,
310 G
: FnMut(&T
) -> syntax_pos
::Span
313 let len
= elts
.len();
316 self.maybe_print_comment(get_span(elt
).hi())?
;
321 self.maybe_print_trailing_comment(get_span(elt
), Some(get_span(&elts
[i
]).hi()))?
;
322 self.space_if_not_bol()?
;
328 pub fn commasep_exprs(&mut self, b
: Breaks
, exprs
: &[hir
::Expr
]) -> io
::Result
<()> {
329 self.commasep_cmnt(b
, exprs
, |s
, e
| s
.print_expr(&e
), |e
| e
.span
)
332 pub fn print_mod(&mut self, _mod
: &hir
::Mod
, attrs
: &[ast
::Attribute
]) -> io
::Result
<()> {
333 self.print_inner_attributes(attrs
)?
;
334 for &item_id
in &_mod
.item_ids
{
335 self.ann
.nested(self, Nested
::Item(item_id
))?
;
340 pub fn print_foreign_mod(&mut self,
341 nmod
: &hir
::ForeignMod
,
342 attrs
: &[ast
::Attribute
])
344 self.print_inner_attributes(attrs
)?
;
345 for item
in &nmod
.items
{
346 self.print_foreign_item(item
)?
;
351 pub fn print_opt_lifetime(&mut self, lifetime
: &hir
::Lifetime
) -> io
::Result
<()> {
352 if !lifetime
.is_elided() {
353 self.print_lifetime(lifetime
)?
;
359 pub fn print_type(&mut self, ty
: &hir
::Ty
) -> io
::Result
<()> {
360 self.maybe_print_comment(ty
.span
.lo())?
;
363 hir
::TySlice(ref ty
) => {
365 self.print_type(&ty
)?
;
368 hir
::TyPtr(ref mt
) => {
371 hir
::MutMutable
=> self.word_nbsp("mut")?
,
372 hir
::MutImmutable
=> self.word_nbsp("const")?
,
374 self.print_type(&mt
.ty
)?
;
376 hir
::TyRptr(ref lifetime
, ref mt
) => {
378 self.print_opt_lifetime(lifetime
)?
;
384 hir
::TyTup(ref elts
) => {
386 self.commasep(Inconsistent
, &elts
[..], |s
, ty
| s
.print_type(&ty
))?
;
392 hir
::TyBareFn(ref f
) => {
393 let generics
= hir
::Generics
{
394 lifetimes
: f
.lifetimes
.clone(),
395 ty_params
: hir
::HirVec
::new(),
396 where_clause
: hir
::WhereClause
{
397 id
: ast
::DUMMY_NODE_ID
,
398 predicates
: hir
::HirVec
::new(),
400 span
: syntax_pos
::DUMMY_SP
,
402 self.print_ty_fn(f
.abi
, f
.unsafety
, &f
.decl
, None
, &generics
,
405 hir
::TyPath(ref qpath
) => {
406 self.print_qpath(qpath
, false)?
408 hir
::TyTraitObject(ref bounds
, ref lifetime
) => {
409 let mut first
= true;
410 for bound
in bounds
{
415 self.word_space("+")?
;
417 self.print_poly_trait_ref(bound
)?
;
419 if !lifetime
.is_elided() {
420 self.word_space("+")?
;
421 self.print_lifetime(lifetime
)?
;
424 hir
::TyImplTraitExistential(ref bounds
) |
425 hir
::TyImplTraitUniversal(_
, ref bounds
) => {
426 self.print_bounds("impl", &bounds
[..])?
;
428 hir
::TyArray(ref ty
, v
) => {
430 self.print_type(&ty
)?
;
432 self.ann
.nested(self, Nested
::Body(v
))?
;
435 hir
::TyTypeof(e
) => {
436 self.s
.word("typeof(")?
;
437 self.ann
.nested(self, Nested
::Body(e
))?
;
450 pub fn print_foreign_item(&mut self, item
: &hir
::ForeignItem
) -> io
::Result
<()> {
451 self.hardbreak_if_not_bol()?
;
452 self.maybe_print_comment(item
.span
.lo())?
;
453 self.print_outer_attributes(&item
.attrs
)?
;
455 hir
::ForeignItemFn(ref decl
, ref arg_names
, ref generics
) => {
458 hir
::Unsafety
::Normal
,
459 hir
::Constness
::NotConst
,
466 self.end()?
; // end head-ibox
468 self.end() // end the outer fn box
470 hir
::ForeignItemStatic(ref t
, m
) => {
471 self.head(&visibility_qualified(&item
.vis
, "static"))?
;
473 self.word_space("mut")?
;
475 self.print_name(item
.name
)?
;
476 self.word_space(":")?
;
477 self.print_type(&t
)?
;
479 self.end()?
; // end the head-ibox
480 self.end() // end the outer cbox
482 hir
::ForeignItemType
=> {
483 self.head(&visibility_qualified(&item
.vis
, "type"))?
;
484 self.print_name(item
.name
)?
;
486 self.end()?
; // end the head-ibox
487 self.end() // end the outer cbox
492 fn print_associated_const(&mut self,
495 default: Option
<hir
::BodyId
>,
496 vis
: &hir
::Visibility
)
498 self.s
.word(&visibility_qualified(vis
, ""))?
;
499 self.word_space("const")?
;
500 self.print_name(name
)?
;
501 self.word_space(":")?
;
502 self.print_type(ty
)?
;
503 if let Some(expr
) = default {
505 self.word_space("=")?
;
506 self.ann
.nested(self, Nested
::Body(expr
))?
;
511 fn print_associated_type(&mut self,
513 bounds
: Option
<&hir
::TyParamBounds
>,
514 ty
: Option
<&hir
::Ty
>)
516 self.word_space("type")?
;
517 self.print_name(name
)?
;
518 if let Some(bounds
) = bounds
{
519 self.print_bounds(":", bounds
)?
;
521 if let Some(ty
) = ty
{
523 self.word_space("=")?
;
524 self.print_type(ty
)?
;
529 /// Pretty-print an item
530 pub fn print_item(&mut self, item
: &hir
::Item
) -> io
::Result
<()> {
531 self.hardbreak_if_not_bol()?
;
532 self.maybe_print_comment(item
.span
.lo())?
;
533 self.print_outer_attributes(&item
.attrs
)?
;
534 self.ann
.pre(self, NodeItem(item
))?
;
536 hir
::ItemExternCrate(ref optional_path
) => {
537 self.head(&visibility_qualified(&item
.vis
, "extern crate"))?
;
538 if let Some(p
) = *optional_path
{
539 let val
= p
.as_str();
540 if val
.contains("-") {
541 self.print_string(&val
, ast
::StrStyle
::Cooked
)?
;
549 self.print_name(item
.name
)?
;
551 self.end()?
; // end inner head-block
552 self.end()?
; // end outer head-block
554 hir
::ItemUse(ref path
, kind
) => {
555 self.head(&visibility_qualified(&item
.vis
, "use"))?
;
556 self.print_path(path
, false)?
;
559 hir
::UseKind
::Single
=> {
560 if path
.segments
.last().unwrap().name
!= item
.name
{
562 self.word_space("as")?
;
563 self.print_name(item
.name
)?
;
567 hir
::UseKind
::Glob
=> self.s
.word("::*;")?
,
568 hir
::UseKind
::ListStem
=> self.s
.word("::{};")?
570 self.end()?
; // end inner head-block
571 self.end()?
; // end outer head-block
573 hir
::ItemStatic(ref ty
, m
, expr
) => {
574 self.head(&visibility_qualified(&item
.vis
, "static"))?
;
575 if m
== hir
::MutMutable
{
576 self.word_space("mut")?
;
578 self.print_name(item
.name
)?
;
579 self.word_space(":")?
;
580 self.print_type(&ty
)?
;
582 self.end()?
; // end the head-ibox
584 self.word_space("=")?
;
585 self.ann
.nested(self, Nested
::Body(expr
))?
;
587 self.end()?
; // end the outer cbox
589 hir
::ItemConst(ref ty
, expr
) => {
590 self.head(&visibility_qualified(&item
.vis
, "const"))?
;
591 self.print_name(item
.name
)?
;
592 self.word_space(":")?
;
593 self.print_type(&ty
)?
;
595 self.end()?
; // end the head-ibox
597 self.word_space("=")?
;
598 self.ann
.nested(self, Nested
::Body(expr
))?
;
600 self.end()?
; // end the outer cbox
602 hir
::ItemFn(ref decl
, unsafety
, constness
, abi
, ref typarams
, body
) => {
614 self.end()?
; // need to close a box
615 self.end()?
; // need to close a box
616 self.ann
.nested(self, Nested
::Body(body
))?
;
618 hir
::ItemMod(ref _mod
) => {
619 self.head(&visibility_qualified(&item
.vis
, "mod"))?
;
620 self.print_name(item
.name
)?
;
623 self.print_mod(_mod
, &item
.attrs
)?
;
624 self.bclose(item
.span
)?
;
626 hir
::ItemForeignMod(ref nmod
) => {
627 self.head("extern")?
;
628 self.word_nbsp(&nmod
.abi
.to_string())?
;
630 self.print_foreign_mod(nmod
, &item
.attrs
)?
;
631 self.bclose(item
.span
)?
;
633 hir
::ItemGlobalAsm(ref ga
) => {
634 self.head(&visibility_qualified(&item
.vis
, "global asm"))?
;
635 self.s
.word(&ga
.asm
.as_str())?
;
638 hir
::ItemTy(ref ty
, ref params
) => {
639 self.ibox(indent_unit
)?
;
641 self.word_nbsp(&visibility_qualified(&item
.vis
, "type"))?
;
642 self.print_name(item
.name
)?
;
643 self.print_generics(params
)?
;
644 self.end()?
; // end the inner ibox
646 self.print_where_clause(¶ms
.where_clause
)?
;
648 self.word_space("=")?
;
649 self.print_type(&ty
)?
;
651 self.end()?
; // end the outer ibox
653 hir
::ItemEnum(ref enum_definition
, ref params
) => {
654 self.print_enum_def(enum_definition
, params
, item
.name
, item
.span
, &item
.vis
)?
;
656 hir
::ItemStruct(ref struct_def
, ref generics
) => {
657 self.head(&visibility_qualified(&item
.vis
, "struct"))?
;
658 self.print_struct(struct_def
, generics
, item
.name
, item
.span
, true)?
;
660 hir
::ItemUnion(ref struct_def
, ref generics
) => {
661 self.head(&visibility_qualified(&item
.vis
, "union"))?
;
662 self.print_struct(struct_def
, generics
, item
.name
, item
.span
, true)?
;
664 hir
::ItemAutoImpl(unsafety
, ref trait_ref
) => {
666 self.print_visibility(&item
.vis
)?
;
667 self.print_unsafety(unsafety
)?
;
668 self.word_nbsp("impl")?
;
669 self.print_trait_ref(trait_ref
)?
;
671 self.word_space("for")?
;
672 self.word_space("..")?
;
674 self.bclose(item
.span
)?
;
676 hir
::ItemImpl(unsafety
,
684 self.print_visibility(&item
.vis
)?
;
685 self.print_defaultness(defaultness
)?
;
686 self.print_unsafety(unsafety
)?
;
687 self.word_nbsp("impl")?
;
689 if generics
.is_parameterized() {
690 self.print_generics(generics
)?
;
695 hir
::ImplPolarity
::Negative
=> {
703 self.print_trait_ref(t
)?
;
705 self.word_space("for")?
;
710 self.print_type(&ty
)?
;
711 self.print_where_clause(&generics
.where_clause
)?
;
715 self.print_inner_attributes(&item
.attrs
)?
;
716 for impl_item
in impl_items
{
717 self.ann
.nested(self, Nested
::ImplItem(impl_item
.id
))?
;
719 self.bclose(item
.span
)?
;
721 hir
::ItemTrait(is_auto
, unsafety
, ref generics
, ref bounds
, ref trait_items
) => {
723 self.print_visibility(&item
.vis
)?
;
724 self.print_is_auto(is_auto
)?
;
725 self.print_unsafety(unsafety
)?
;
726 self.word_nbsp("trait")?
;
727 self.print_name(item
.name
)?
;
728 self.print_generics(generics
)?
;
729 let mut real_bounds
= Vec
::with_capacity(bounds
.len());
730 for b
in bounds
.iter() {
731 if let TraitTyParamBound(ref ptr
, hir
::TraitBoundModifier
::Maybe
) = *b
{
733 self.word_space("for ?")?
;
734 self.print_trait_ref(&ptr
.trait_ref
)?
;
736 real_bounds
.push(b
.clone());
739 self.print_bounds(":", &real_bounds
[..])?
;
740 self.print_where_clause(&generics
.where_clause
)?
;
743 for trait_item
in trait_items
{
744 self.ann
.nested(self, Nested
::TraitItem(trait_item
.id
))?
;
746 self.bclose(item
.span
)?
;
749 self.ann
.post(self, NodeItem(item
))
752 pub fn print_trait_ref(&mut self, t
: &hir
::TraitRef
) -> io
::Result
<()> {
753 self.print_path(&t
.path
, false)
756 fn print_formal_lifetime_list(&mut self, lifetimes
: &[hir
::LifetimeDef
]) -> io
::Result
<()> {
757 if !lifetimes
.is_empty() {
758 self.s
.word("for<")?
;
759 let mut comma
= false;
760 for lifetime_def
in lifetimes
{
762 self.word_space(",")?
764 self.print_lifetime_def(lifetime_def
)?
;
772 fn print_poly_trait_ref(&mut self, t
: &hir
::PolyTraitRef
) -> io
::Result
<()> {
773 self.print_formal_lifetime_list(&t
.bound_lifetimes
)?
;
774 self.print_trait_ref(&t
.trait_ref
)
777 pub fn print_enum_def(&mut self,
778 enum_definition
: &hir
::EnumDef
,
779 generics
: &hir
::Generics
,
781 span
: syntax_pos
::Span
,
782 visibility
: &hir
::Visibility
)
784 self.head(&visibility_qualified(visibility
, "enum"))?
;
785 self.print_name(name
)?
;
786 self.print_generics(generics
)?
;
787 self.print_where_clause(&generics
.where_clause
)?
;
789 self.print_variants(&enum_definition
.variants
, span
)
792 pub fn print_variants(&mut self,
793 variants
: &[hir
::Variant
],
794 span
: syntax_pos
::Span
)
798 self.space_if_not_bol()?
;
799 self.maybe_print_comment(v
.span
.lo())?
;
800 self.print_outer_attributes(&v
.node
.attrs
)?
;
801 self.ibox(indent_unit
)?
;
802 self.print_variant(v
)?
;
805 self.maybe_print_trailing_comment(v
.span
, None
)?
;
810 pub fn print_visibility(&mut self, vis
: &hir
::Visibility
) -> io
::Result
<()> {
812 hir
::Public
=> self.word_nbsp("pub"),
813 hir
::Visibility
::Crate
=> self.word_nbsp("pub(crate)"),
814 hir
::Visibility
::Restricted { ref path, .. }
=> {
815 self.s
.word("pub(")?
;
816 self.print_path(path
, false)?
;
819 hir
::Inherited
=> Ok(()),
823 pub fn print_defaultness(&mut self, defaultness
: hir
::Defaultness
) -> io
::Result
<()> {
825 hir
::Defaultness
::Default { .. }
=> self.word_nbsp("default")?
,
826 hir
::Defaultness
::Final
=> (),
831 pub fn print_struct(&mut self,
832 struct_def
: &hir
::VariantData
,
833 generics
: &hir
::Generics
,
835 span
: syntax_pos
::Span
,
836 print_finalizer
: bool
)
838 self.print_name(name
)?
;
839 self.print_generics(generics
)?
;
840 if !struct_def
.is_struct() {
841 if struct_def
.is_tuple() {
843 self.commasep(Inconsistent
, struct_def
.fields(), |s
, field
| {
844 s
.maybe_print_comment(field
.span
.lo())?
;
845 s
.print_outer_attributes(&field
.attrs
)?
;
846 s
.print_visibility(&field
.vis
)?
;
847 s
.print_type(&field
.ty
)
851 self.print_where_clause(&generics
.where_clause
)?
;
856 self.end() // close the outer-box
858 self.print_where_clause(&generics
.where_clause
)?
;
861 self.hardbreak_if_not_bol()?
;
863 for field
in struct_def
.fields() {
864 self.hardbreak_if_not_bol()?
;
865 self.maybe_print_comment(field
.span
.lo())?
;
866 self.print_outer_attributes(&field
.attrs
)?
;
867 self.print_visibility(&field
.vis
)?
;
868 self.print_name(field
.name
)?
;
869 self.word_nbsp(":")?
;
870 self.print_type(&field
.ty
)?
;
878 pub fn print_variant(&mut self, v
: &hir
::Variant
) -> io
::Result
<()> {
880 let generics
= hir
::Generics
::empty();
881 self.print_struct(&v
.node
.data
, &generics
, v
.node
.name
, v
.span
, false)?
;
882 if let Some(d
) = v
.node
.disr_expr
{
884 self.word_space("=")?
;
885 self.ann
.nested(self, Nested
::Body(d
))?
;
889 pub fn print_method_sig(&mut self,
892 generics
: &hir
::Generics
,
893 vis
: &hir
::Visibility
,
894 arg_names
: &[Spanned
<ast
::Name
>],
895 body_id
: Option
<hir
::BodyId
>)
897 self.print_fn(&m
.decl
,
908 pub fn print_trait_item(&mut self, ti
: &hir
::TraitItem
) -> io
::Result
<()> {
909 self.ann
.pre(self, NodeSubItem(ti
.id
))?
;
910 self.hardbreak_if_not_bol()?
;
911 self.maybe_print_comment(ti
.span
.lo())?
;
912 self.print_outer_attributes(&ti
.attrs
)?
;
914 hir
::TraitItemKind
::Const(ref ty
, default) => {
915 self.print_associated_const(ti
.name
, &ty
, default, &hir
::Inherited
)?
;
917 hir
::TraitItemKind
::Method(ref sig
, hir
::TraitMethod
::Required(ref arg_names
)) => {
918 self.print_method_sig(ti
.name
, sig
, &ti
.generics
, &hir
::Inherited
, arg_names
,
922 hir
::TraitItemKind
::Method(ref sig
, hir
::TraitMethod
::Provided(body
)) => {
924 self.print_method_sig(ti
.name
, sig
, &ti
.generics
, &hir
::Inherited
, &[],
927 self.end()?
; // need to close a box
928 self.end()?
; // need to close a box
929 self.ann
.nested(self, Nested
::Body(body
))?
;
931 hir
::TraitItemKind
::Type(ref bounds
, ref default) => {
932 self.print_associated_type(ti
.name
,
934 default.as_ref().map(|ty
| &**ty
))?
;
937 self.ann
.post(self, NodeSubItem(ti
.id
))
940 pub fn print_impl_item(&mut self, ii
: &hir
::ImplItem
) -> io
::Result
<()> {
941 self.ann
.pre(self, NodeSubItem(ii
.id
))?
;
942 self.hardbreak_if_not_bol()?
;
943 self.maybe_print_comment(ii
.span
.lo())?
;
944 self.print_outer_attributes(&ii
.attrs
)?
;
945 self.print_defaultness(ii
.defaultness
)?
;
948 hir
::ImplItemKind
::Const(ref ty
, expr
) => {
949 self.print_associated_const(ii
.name
, &ty
, Some(expr
), &ii
.vis
)?
;
951 hir
::ImplItemKind
::Method(ref sig
, body
) => {
953 self.print_method_sig(ii
.name
, sig
, &ii
.generics
, &ii
.vis
, &[], Some(body
))?
;
955 self.end()?
; // need to close a box
956 self.end()?
; // need to close a box
957 self.ann
.nested(self, Nested
::Body(body
))?
;
959 hir
::ImplItemKind
::Type(ref ty
) => {
960 self.print_associated_type(ii
.name
, None
, Some(ty
))?
;
963 self.ann
.post(self, NodeSubItem(ii
.id
))
966 pub fn print_stmt(&mut self, st
: &hir
::Stmt
) -> io
::Result
<()> {
967 self.maybe_print_comment(st
.span
.lo())?
;
969 hir
::StmtDecl(ref decl
, _
) => {
970 self.print_decl(&decl
)?
;
972 hir
::StmtExpr(ref expr
, _
) => {
973 self.space_if_not_bol()?
;
974 self.print_expr(&expr
)?
;
976 hir
::StmtSemi(ref expr
, _
) => {
977 self.space_if_not_bol()?
;
978 self.print_expr(&expr
)?
;
982 if stmt_ends_with_semi(&st
.node
) {
985 self.maybe_print_trailing_comment(st
.span
, None
)
988 pub fn print_block(&mut self, blk
: &hir
::Block
) -> io
::Result
<()> {
989 self.print_block_with_attrs(blk
, &[])
992 pub fn print_block_unclosed(&mut self, blk
: &hir
::Block
) -> io
::Result
<()> {
993 self.print_block_unclosed_indent(blk
, indent_unit
)
996 pub fn print_block_unclosed_indent(&mut self,
1000 self.print_block_maybe_unclosed(blk
, indented
, &[], false)
1003 pub fn print_block_with_attrs(&mut self,
1005 attrs
: &[ast
::Attribute
])
1007 self.print_block_maybe_unclosed(blk
, indent_unit
, attrs
, true)
1010 pub fn print_block_maybe_unclosed(&mut self,
1013 attrs
: &[ast
::Attribute
],
1017 hir
::UnsafeBlock(..) => self.word_space("unsafe")?
,
1018 hir
::PushUnsafeBlock(..) => self.word_space("push_unsafe")?
,
1019 hir
::PopUnsafeBlock(..) => self.word_space("pop_unsafe")?
,
1020 hir
::DefaultBlock
=> (),
1022 self.maybe_print_comment(blk
.span
.lo())?
;
1023 self.ann
.pre(self, NodeBlock(blk
))?
;
1026 self.print_inner_attributes(attrs
)?
;
1028 for st
in &blk
.stmts
{
1029 self.print_stmt(st
)?
;
1033 self.space_if_not_bol()?
;
1034 self.print_expr(&expr
)?
;
1035 self.maybe_print_trailing_comment(expr
.span
, Some(blk
.span
.hi()))?
;
1039 self.bclose_maybe_open(blk
.span
, indented
, close_box
)?
;
1040 self.ann
.post(self, NodeBlock(blk
))
1043 fn print_else(&mut self, els
: Option
<&hir
::Expr
>) -> io
::Result
<()> {
1047 // "another else-if"
1048 hir
::ExprIf(ref i
, ref then
, ref e
) => {
1049 self.cbox(indent_unit
- 1)?
;
1051 self.s
.word(" else if ")?
;
1052 self.print_expr_as_cond(&i
)?
;
1054 self.print_expr(&then
)?
;
1055 self.print_else(e
.as_ref().map(|e
| &**e
))
1058 hir
::ExprBlock(ref b
) => {
1059 self.cbox(indent_unit
- 1)?
;
1061 self.s
.word(" else ")?
;
1062 self.print_block(&b
)
1064 // BLEAH, constraints would be great here
1066 panic
!("print_if saw if with weird alternative");
1074 pub fn print_if(&mut self,
1077 elseopt
: Option
<&hir
::Expr
>)
1080 self.print_expr_as_cond(test
)?
;
1082 self.print_expr(blk
)?
;
1083 self.print_else(elseopt
)
1086 pub fn print_if_let(&mut self,
1090 elseopt
: Option
<&hir
::Expr
>)
1092 self.head("if let")?
;
1093 self.print_pat(pat
)?
;
1095 self.word_space("=")?
;
1096 self.print_expr_as_cond(expr
)?
;
1098 self.print_block(blk
)?
;
1099 self.print_else(elseopt
)
1103 fn print_call_post(&mut self, args
: &[hir
::Expr
]) -> io
::Result
<()> {
1105 self.commasep_exprs(Inconsistent
, args
)?
;
1109 pub fn print_expr_maybe_paren(&mut self, expr
: &hir
::Expr
, prec
: i8) -> io
::Result
<()> {
1110 let needs_par
= expr_precedence(expr
) < prec
;
1114 self.print_expr(expr
)?
;
1121 /// Print an expr using syntax that's acceptable in a condition position, such as the `cond` in
1122 /// `if cond { ... }`.
1123 pub fn print_expr_as_cond(&mut self, expr
: &hir
::Expr
) -> io
::Result
<()> {
1124 let needs_par
= match expr
.node
{
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 hir
::ExprClosure(..) |
1129 hir
::ExprBreak(..) => true,
1131 _
=> contains_exterior_struct_lit(expr
),
1137 self.print_expr(expr
)?
;
1144 fn print_expr_vec(&mut self, exprs
: &[hir
::Expr
]) -> io
::Result
<()> {
1145 self.ibox(indent_unit
)?
;
1147 self.commasep_exprs(Inconsistent
, exprs
)?
;
1152 fn print_expr_repeat(&mut self, element
: &hir
::Expr
, count
: hir
::BodyId
) -> io
::Result
<()> {
1153 self.ibox(indent_unit
)?
;
1155 self.print_expr(element
)?
;
1156 self.word_space(";")?
;
1157 self.ann
.nested(self, Nested
::Body(count
))?
;
1162 fn print_expr_struct(&mut self,
1164 fields
: &[hir
::Field
],
1165 wth
: &Option
<P
<hir
::Expr
>>)
1167 self.print_qpath(qpath
, true)?
;
1169 self.commasep_cmnt(Consistent
,
1172 s
.ibox(indent_unit
)?
;
1173 if !field
.is_shorthand
{
1174 s
.print_name(field
.name
.node
)?
;
1177 s
.print_expr(&field
.expr
)?
;
1183 self.ibox(indent_unit
)?
;
1184 if !fields
.is_empty() {
1189 self.print_expr(&expr
)?
;
1192 _
=> if !fields
.is_empty() {
1200 fn print_expr_tup(&mut self, exprs
: &[hir
::Expr
]) -> io
::Result
<()> {
1202 self.commasep_exprs(Inconsistent
, exprs
)?
;
1203 if exprs
.len() == 1 {
1209 fn print_expr_call(&mut self, func
: &hir
::Expr
, args
: &[hir
::Expr
]) -> io
::Result
<()> {
1212 hir
::ExprField(..) |
1213 hir
::ExprTupField(..) => parser
::PREC_FORCE_PAREN
,
1214 _
=> parser
::PREC_POSTFIX
,
1217 self.print_expr_maybe_paren(func
, prec
)?
;
1218 self.print_call_post(args
)
1221 fn print_expr_method_call(&mut self,
1222 segment
: &hir
::PathSegment
,
1225 let base_args
= &args
[1..];
1226 self.print_expr_maybe_paren(&args
[0], parser
::PREC_POSTFIX
)?
;
1228 self.print_name(segment
.name
)?
;
1230 segment
.with_parameters(|parameters
| {
1231 if !parameters
.lifetimes
.is_empty() ||
1232 !parameters
.types
.is_empty() ||
1233 !parameters
.bindings
.is_empty()
1235 self.print_path_parameters(¶meters
, segment
.infer_types
, true)
1240 self.print_call_post(base_args
)
1243 fn print_expr_binary(&mut self,
1248 let assoc_op
= bin_op_to_assoc_op(op
.node
);
1249 let prec
= assoc_op
.precedence() as i8;
1250 let fixity
= assoc_op
.fixity();
1252 let (left_prec
, right_prec
) = match fixity
{
1253 Fixity
::Left
=> (prec
, prec
+ 1),
1254 Fixity
::Right
=> (prec
+ 1, prec
),
1255 Fixity
::None
=> (prec
+ 1, prec
+ 1),
1258 let left_prec
= match (&lhs
.node
, op
.node
) {
1259 // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
1260 // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
1261 // of `(x as i32) < ...`. We need to convince it _not_ to do that.
1262 (&hir
::ExprCast { .. }
, hir
::BinOp_
::BiLt
) |
1263 (&hir
::ExprCast { .. }
, hir
::BinOp_
::BiShl
) => parser
::PREC_FORCE_PAREN
,
1267 self.print_expr_maybe_paren(lhs
, left_prec
)?
;
1269 self.word_space(op
.node
.as_str())?
;
1270 self.print_expr_maybe_paren(rhs
, right_prec
)
1273 fn print_expr_unary(&mut self, op
: hir
::UnOp
, expr
: &hir
::Expr
) -> io
::Result
<()> {
1274 self.s
.word(op
.as_str())?
;
1275 self.print_expr_maybe_paren(expr
, parser
::PREC_PREFIX
)
1278 fn print_expr_addr_of(&mut self,
1279 mutability
: hir
::Mutability
,
1283 self.print_mutability(mutability
)?
;
1284 self.print_expr_maybe_paren(expr
, parser
::PREC_PREFIX
)
1287 pub fn print_expr(&mut self, expr
: &hir
::Expr
) -> io
::Result
<()> {
1288 self.maybe_print_comment(expr
.span
.lo())?
;
1289 self.print_outer_attributes(&expr
.attrs
)?
;
1290 self.ibox(indent_unit
)?
;
1291 self.ann
.pre(self, NodeExpr(expr
))?
;
1293 hir
::ExprBox(ref expr
) => {
1294 self.word_space("box")?
;
1295 self.print_expr_maybe_paren(expr
, parser
::PREC_PREFIX
)?
;
1297 hir
::ExprArray(ref exprs
) => {
1298 self.print_expr_vec(exprs
)?
;
1300 hir
::ExprRepeat(ref element
, count
) => {
1301 self.print_expr_repeat(&element
, count
)?
;
1303 hir
::ExprStruct(ref qpath
, ref fields
, ref wth
) => {
1304 self.print_expr_struct(qpath
, &fields
[..], wth
)?
;
1306 hir
::ExprTup(ref exprs
) => {
1307 self.print_expr_tup(exprs
)?
;
1309 hir
::ExprCall(ref func
, ref args
) => {
1310 self.print_expr_call(&func
, args
)?
;
1312 hir
::ExprMethodCall(ref segment
, _
, ref args
) => {
1313 self.print_expr_method_call(segment
, args
)?
;
1315 hir
::ExprBinary(op
, ref lhs
, ref rhs
) => {
1316 self.print_expr_binary(op
, &lhs
, &rhs
)?
;
1318 hir
::ExprUnary(op
, ref expr
) => {
1319 self.print_expr_unary(op
, &expr
)?
;
1321 hir
::ExprAddrOf(m
, ref expr
) => {
1322 self.print_expr_addr_of(m
, &expr
)?
;
1324 hir
::ExprLit(ref lit
) => {
1325 self.print_literal(&lit
)?
;
1327 hir
::ExprCast(ref expr
, ref ty
) => {
1328 let prec
= AssocOp
::As
.precedence() as i8;
1329 self.print_expr_maybe_paren(&expr
, prec
)?
;
1331 self.word_space("as")?
;
1332 self.print_type(&ty
)?
;
1334 hir
::ExprType(ref expr
, ref ty
) => {
1335 let prec
= AssocOp
::Colon
.precedence() as i8;
1336 self.print_expr_maybe_paren(&expr
, prec
)?
;
1337 self.word_space(":")?
;
1338 self.print_type(&ty
)?
;
1340 hir
::ExprIf(ref test
, ref blk
, ref elseopt
) => {
1341 self.print_if(&test
, &blk
, elseopt
.as_ref().map(|e
| &**e
))?
;
1343 hir
::ExprWhile(ref test
, ref blk
, opt_sp_name
) => {
1344 if let Some(sp_name
) = opt_sp_name
{
1345 self.print_name(sp_name
.node
)?
;
1346 self.word_space(":")?
;
1348 self.head("while")?
;
1349 self.print_expr_as_cond(&test
)?
;
1351 self.print_block(&blk
)?
;
1353 hir
::ExprLoop(ref blk
, opt_sp_name
, _
) => {
1354 if let Some(sp_name
) = opt_sp_name
{
1355 self.print_name(sp_name
.node
)?
;
1356 self.word_space(":")?
;
1360 self.print_block(&blk
)?
;
1362 hir
::ExprMatch(ref expr
, ref arms
, _
) => {
1363 self.cbox(indent_unit
)?
;
1365 self.word_nbsp("match")?
;
1366 self.print_expr_as_cond(&expr
)?
;
1370 self.print_arm(arm
)?
;
1372 self.bclose_(expr
.span
, indent_unit
)?
;
1374 hir
::ExprClosure(capture_clause
, ref decl
, body
, _fn_decl_span
, _gen
) => {
1375 self.print_capture_clause(capture_clause
)?
;
1377 self.print_closure_args(&decl
, body
)?
;
1380 // this is a bare expression
1381 self.ann
.nested(self, Nested
::Body(body
))?
;
1382 self.end()?
; // need to close a box
1384 // a box will be closed by print_expr, but we didn't want an overall
1385 // wrapper so we closed the corresponding opening. so create an
1386 // empty box to satisfy the close.
1389 hir
::ExprBlock(ref blk
) => {
1390 // containing cbox, will be closed by print-block at }
1391 self.cbox(indent_unit
)?
;
1392 // head-box, will be closed by print-block after {
1394 self.print_block(&blk
)?
;
1396 hir
::ExprAssign(ref lhs
, ref rhs
) => {
1397 let prec
= AssocOp
::Assign
.precedence() as i8;
1398 self.print_expr_maybe_paren(&lhs
, prec
+ 1)?
;
1400 self.word_space("=")?
;
1401 self.print_expr_maybe_paren(&rhs
, prec
)?
;
1403 hir
::ExprAssignOp(op
, ref lhs
, ref rhs
) => {
1404 let prec
= AssocOp
::Assign
.precedence() as i8;
1405 self.print_expr_maybe_paren(&lhs
, prec
+ 1)?
;
1407 self.s
.word(op
.node
.as_str())?
;
1408 self.word_space("=")?
;
1409 self.print_expr_maybe_paren(&rhs
, prec
)?
;
1411 hir
::ExprField(ref expr
, name
) => {
1412 self.print_expr_maybe_paren(expr
, parser
::PREC_POSTFIX
)?
;
1414 self.print_name(name
.node
)?
;
1416 hir
::ExprTupField(ref expr
, id
) => {
1417 self.print_expr_maybe_paren(&expr
, parser
::PREC_POSTFIX
)?
;
1419 self.print_usize(id
.node
)?
;
1421 hir
::ExprIndex(ref expr
, ref index
) => {
1422 self.print_expr_maybe_paren(&expr
, parser
::PREC_POSTFIX
)?
;
1424 self.print_expr(&index
)?
;
1427 hir
::ExprPath(ref qpath
) => {
1428 self.print_qpath(qpath
, true)?
1430 hir
::ExprBreak(label
, ref opt_expr
) => {
1431 self.s
.word("break")?
;
1433 if let Some(label_ident
) = label
.ident
{
1434 self.print_name(label_ident
.node
.name
)?
;
1437 if let Some(ref expr
) = *opt_expr
{
1438 self.print_expr_maybe_paren(expr
, parser
::PREC_JUMP
)?
;
1442 hir
::ExprAgain(label
) => {
1443 self.s
.word("continue")?
;
1445 if let Some(label_ident
) = label
.ident
{
1446 self.print_name(label_ident
.node
.name
)?
;
1450 hir
::ExprRet(ref result
) => {
1451 self.s
.word("return")?
;
1455 self.print_expr_maybe_paren(&expr
, parser
::PREC_JUMP
)?
;
1460 hir
::ExprInlineAsm(ref a
, ref outputs
, ref inputs
) => {
1461 self.s
.word("asm!")?
;
1463 self.print_string(&a
.asm
.as_str(), a
.asm_str_style
)?
;
1464 self.word_space(":")?
;
1466 let mut out_idx
= 0;
1467 self.commasep(Inconsistent
, &a
.outputs
, |s
, out
| {
1468 let constraint
= out
.constraint
.as_str();
1469 let mut ch
= constraint
.chars();
1471 Some('
='
) if out
.is_rw
=> {
1472 s
.print_string(&format
!("+{}", ch
.as_str()),
1473 ast
::StrStyle
::Cooked
)?
1475 _
=> s
.print_string(&constraint
, ast
::StrStyle
::Cooked
)?
,
1478 s
.print_expr(&outputs
[out_idx
])?
;
1484 self.word_space(":")?
;
1487 self.commasep(Inconsistent
, &a
.inputs
, |s
, co
| {
1488 s
.print_string(&co
.as_str(), ast
::StrStyle
::Cooked
)?
;
1490 s
.print_expr(&inputs
[in_idx
])?
;
1496 self.word_space(":")?
;
1498 self.commasep(Inconsistent
, &a
.clobbers
, |s
, co
| {
1499 s
.print_string(&co
.as_str(), ast
::StrStyle
::Cooked
)?
;
1503 let mut options
= vec
![];
1505 options
.push("volatile");
1508 options
.push("alignstack");
1510 if a
.dialect
== ast
::AsmDialect
::Intel
{
1511 options
.push("intel");
1514 if !options
.is_empty() {
1516 self.word_space(":")?
;
1517 self.commasep(Inconsistent
, &options
, |s
, &co
| {
1518 s
.print_string(co
, ast
::StrStyle
::Cooked
)?
;
1525 hir
::ExprYield(ref expr
) => {
1526 self.word_space("yield")?
;
1527 self.print_expr_maybe_paren(&expr
, parser
::PREC_JUMP
)?
;
1530 self.ann
.post(self, NodeExpr(expr
))?
;
1534 pub fn print_local_decl(&mut self, loc
: &hir
::Local
) -> io
::Result
<()> {
1535 self.print_pat(&loc
.pat
)?
;
1536 if let Some(ref ty
) = loc
.ty
{
1537 self.word_space(":")?
;
1538 self.print_type(&ty
)?
;
1543 pub fn print_decl(&mut self, decl
: &hir
::Decl
) -> io
::Result
<()> {
1544 self.maybe_print_comment(decl
.span
.lo())?
;
1546 hir
::DeclLocal(ref loc
) => {
1547 self.space_if_not_bol()?
;
1548 self.ibox(indent_unit
)?
;
1549 self.word_nbsp("let")?
;
1551 self.ibox(indent_unit
)?
;
1552 self.print_local_decl(&loc
)?
;
1554 if let Some(ref init
) = loc
.init
{
1556 self.word_space("=")?
;
1557 self.print_expr(&init
)?
;
1561 hir
::DeclItem(item
) => {
1562 self.ann
.nested(self, Nested
::Item(item
))
1567 pub fn print_usize(&mut self, i
: usize) -> io
::Result
<()> {
1568 self.s
.word(&i
.to_string())
1571 pub fn print_name(&mut self, name
: ast
::Name
) -> io
::Result
<()> {
1572 self.s
.word(&name
.as_str())?
;
1573 self.ann
.post(self, NodeName(&name
))
1576 pub fn print_for_decl(&mut self, loc
: &hir
::Local
, coll
: &hir
::Expr
) -> io
::Result
<()> {
1577 self.print_local_decl(loc
)?
;
1579 self.word_space("in")?
;
1580 self.print_expr(coll
)
1583 pub fn print_path(&mut self,
1585 colons_before_params
: bool
)
1587 self.maybe_print_comment(path
.span
.lo())?
;
1589 for (i
, segment
) in path
.segments
.iter().enumerate() {
1593 if segment
.name
!= keywords
::CrateRoot
.name() &&
1594 segment
.name
!= keywords
::DollarCrate
.name() {
1595 self.print_name(segment
.name
)?
;
1596 segment
.with_parameters(|parameters
| {
1597 self.print_path_parameters(parameters
,
1598 segment
.infer_types
,
1599 colons_before_params
)
1607 pub fn print_qpath(&mut self,
1609 colons_before_params
: bool
)
1612 hir
::QPath
::Resolved(None
, ref path
) => {
1613 self.print_path(path
, colons_before_params
)
1615 hir
::QPath
::Resolved(Some(ref qself
), ref path
) => {
1617 self.print_type(qself
)?
;
1619 self.word_space("as")?
;
1621 for (i
, segment
) in path
.segments
[..path
.segments
.len() - 1].iter().enumerate() {
1625 if segment
.name
!= keywords
::CrateRoot
.name() &&
1626 segment
.name
!= keywords
::DollarCrate
.name() {
1627 self.print_name(segment
.name
)?
;
1628 segment
.with_parameters(|parameters
| {
1629 self.print_path_parameters(parameters
,
1630 segment
.infer_types
,
1631 colons_before_params
)
1638 let item_segment
= path
.segments
.last().unwrap();
1639 self.print_name(item_segment
.name
)?
;
1640 item_segment
.with_parameters(|parameters
| {
1641 self.print_path_parameters(parameters
,
1642 item_segment
.infer_types
,
1643 colons_before_params
)
1646 hir
::QPath
::TypeRelative(ref qself
, ref item_segment
) => {
1648 self.print_type(qself
)?
;
1651 self.print_name(item_segment
.name
)?
;
1652 item_segment
.with_parameters(|parameters
| {
1653 self.print_path_parameters(parameters
,
1654 item_segment
.infer_types
,
1655 colons_before_params
)
1661 fn print_path_parameters(&mut self,
1662 parameters
: &hir
::PathParameters
,
1664 colons_before_params
: bool
)
1666 if parameters
.parenthesized
{
1668 self.commasep(Inconsistent
, parameters
.inputs(), |s
, ty
| s
.print_type(&ty
))?
;
1671 self.space_if_not_bol()?
;
1672 self.word_space("->")?
;
1673 self.print_type(¶meters
.bindings
[0].ty
)?
;
1675 let start
= if colons_before_params { "::<" }
else { "<" }
;
1676 let empty
= Cell
::new(true);
1677 let start_or_comma
= |this
: &mut Self| {
1682 this
.word_space(",")
1686 if !parameters
.lifetimes
.iter().all(|lt
| lt
.is_elided()) {
1687 for lifetime
in ¶meters
.lifetimes
{
1688 start_or_comma(self)?
;
1689 self.print_lifetime(lifetime
)?
;
1693 if !parameters
.types
.is_empty() {
1694 start_or_comma(self)?
;
1695 self.commasep(Inconsistent
, ¶meters
.types
, |s
, ty
| s
.print_type(&ty
))?
;
1698 // FIXME(eddyb) This would leak into error messages, e.g.:
1699 // "non-exhaustive patterns: `Some::<..>(_)` not covered".
1700 if infer_types
&& false {
1701 start_or_comma(self)?
;
1705 for binding
in parameters
.bindings
.iter() {
1706 start_or_comma(self)?
;
1707 self.print_name(binding
.name
)?
;
1709 self.word_space("=")?
;
1710 self.print_type(&binding
.ty
)?
;
1721 pub fn print_pat(&mut self, pat
: &hir
::Pat
) -> io
::Result
<()> {
1722 self.maybe_print_comment(pat
.span
.lo())?
;
1723 self.ann
.pre(self, NodePat(pat
))?
;
1724 // Pat isn't normalized, but the beauty of it
1725 // is that it doesn't matter
1727 PatKind
::Wild
=> self.s
.word("_")?
,
1728 PatKind
::Binding(binding_mode
, _
, ref path1
, ref sub
) => {
1729 match binding_mode
{
1730 hir
::BindingAnnotation
::Ref
=> {
1731 self.word_nbsp("ref")?
;
1732 self.print_mutability(hir
::MutImmutable
)?
;
1734 hir
::BindingAnnotation
::RefMut
=> {
1735 self.word_nbsp("ref")?
;
1736 self.print_mutability(hir
::MutMutable
)?
;
1738 hir
::BindingAnnotation
::Unannotated
=> {}
1739 hir
::BindingAnnotation
::Mutable
=> {
1740 self.word_nbsp("mut")?
;
1743 self.print_name(path1
.node
)?
;
1744 if let Some(ref p
) = *sub
{
1746 self.print_pat(&p
)?
;
1749 PatKind
::TupleStruct(ref qpath
, ref elts
, ddpos
) => {
1750 self.print_qpath(qpath
, true)?
;
1752 if let Some(ddpos
) = ddpos
{
1753 self.commasep(Inconsistent
, &elts
[..ddpos
], |s
, p
| s
.print_pat(&p
))?
;
1755 self.word_space(",")?
;
1758 if ddpos
!= elts
.len() {
1760 self.commasep(Inconsistent
, &elts
[ddpos
..], |s
, p
| s
.print_pat(&p
))?
;
1763 self.commasep(Inconsistent
, &elts
[..], |s
, p
| s
.print_pat(&p
))?
;
1767 PatKind
::Path(ref qpath
) => {
1768 self.print_qpath(qpath
, true)?
;
1770 PatKind
::Struct(ref qpath
, ref fields
, etc
) => {
1771 self.print_qpath(qpath
, true)?
;
1773 self.word_space("{")?
;
1774 self.commasep_cmnt(Consistent
,
1777 s
.cbox(indent_unit
)?
;
1778 if !f
.node
.is_shorthand
{
1779 s
.print_name(f
.node
.name
)?
;
1782 s
.print_pat(&f
.node
.pat
)?
;
1785 |f
| f
.node
.pat
.span
)?
;
1787 if !fields
.is_empty() {
1788 self.word_space(",")?
;
1795 PatKind
::Tuple(ref elts
, ddpos
) => {
1797 if let Some(ddpos
) = ddpos
{
1798 self.commasep(Inconsistent
, &elts
[..ddpos
], |s
, p
| s
.print_pat(&p
))?
;
1800 self.word_space(",")?
;
1803 if ddpos
!= elts
.len() {
1805 self.commasep(Inconsistent
, &elts
[ddpos
..], |s
, p
| s
.print_pat(&p
))?
;
1808 self.commasep(Inconsistent
, &elts
[..], |s
, p
| s
.print_pat(&p
))?
;
1809 if elts
.len() == 1 {
1815 PatKind
::Box(ref inner
) => {
1816 self.s
.word("box ")?
;
1817 self.print_pat(&inner
)?
;
1819 PatKind
::Ref(ref inner
, mutbl
) => {
1821 if mutbl
== hir
::MutMutable
{
1822 self.s
.word("mut ")?
;
1824 self.print_pat(&inner
)?
;
1826 PatKind
::Lit(ref e
) => self.print_expr(&e
)?
,
1827 PatKind
::Range(ref begin
, ref end
, ref end_kind
) => {
1828 self.print_expr(&begin
)?
;
1831 RangeEnd
::Included
=> self.s
.word("...")?
,
1832 RangeEnd
::Excluded
=> self.s
.word("..")?
,
1834 self.print_expr(&end
)?
;
1836 PatKind
::Slice(ref before
, ref slice
, ref after
) => {
1838 self.commasep(Inconsistent
, &before
[..], |s
, p
| s
.print_pat(&p
))?
;
1839 if let Some(ref p
) = *slice
{
1840 if !before
.is_empty() {
1841 self.word_space(",")?
;
1843 if p
.node
!= PatKind
::Wild
{
1844 self.print_pat(&p
)?
;
1847 if !after
.is_empty() {
1848 self.word_space(",")?
;
1851 self.commasep(Inconsistent
, &after
[..], |s
, p
| s
.print_pat(&p
))?
;
1855 self.ann
.post(self, NodePat(pat
))
1858 fn print_arm(&mut self, arm
: &hir
::Arm
) -> io
::Result
<()> {
1859 // I have no idea why this check is necessary, but here it
1861 if arm
.attrs
.is_empty() {
1864 self.cbox(indent_unit
)?
;
1866 self.print_outer_attributes(&arm
.attrs
)?
;
1867 let mut first
= true;
1868 for p
in &arm
.pats
{
1873 self.word_space("|")?
;
1875 self.print_pat(&p
)?
;
1878 if let Some(ref e
) = arm
.guard
{
1879 self.word_space("if")?
;
1880 self.print_expr(&e
)?
;
1883 self.word_space("=>")?
;
1885 match arm
.body
.node
{
1886 hir
::ExprBlock(ref blk
) => {
1887 // the block will close the pattern's ibox
1888 self.print_block_unclosed_indent(&blk
, indent_unit
)?
;
1890 // If it is a user-provided unsafe block, print a comma after it
1891 if let hir
::UnsafeBlock(hir
::UserProvided
) = blk
.rules
{
1896 self.end()?
; // close the ibox for the pattern
1897 self.print_expr(&arm
.body
)?
;
1901 self.end() // close enclosing cbox
1904 pub fn print_fn(&mut self,
1906 unsafety
: hir
::Unsafety
,
1907 constness
: hir
::Constness
,
1909 name
: Option
<ast
::Name
>,
1910 generics
: &hir
::Generics
,
1911 vis
: &hir
::Visibility
,
1912 arg_names
: &[Spanned
<ast
::Name
>],
1913 body_id
: Option
<hir
::BodyId
>)
1915 self.print_fn_header_info(unsafety
, constness
, abi
, vis
)?
;
1917 if let Some(name
) = name
{
1919 self.print_name(name
)?
;
1921 self.print_generics(generics
)?
;
1925 // Make sure we aren't supplied *both* `arg_names` and `body_id`.
1926 assert
!(arg_names
.is_empty() || body_id
.is_none());
1927 self.commasep(Inconsistent
, &decl
.inputs
, |s
, ty
| {
1928 s
.ibox(indent_unit
)?
;
1929 if let Some(name
) = arg_names
.get(i
) {
1930 s
.s
.word(&name
.node
.as_str())?
;
1933 } else if let Some(body_id
) = body_id
{
1934 s
.ann
.nested(s
, Nested
::BodyArgPat(body_id
, i
))?
;
1943 self.s
.word(", ...")?
;
1947 self.print_fn_output(decl
)?
;
1948 self.print_where_clause(&generics
.where_clause
)
1951 fn print_closure_args(&mut self, decl
: &hir
::FnDecl
, body_id
: hir
::BodyId
) -> io
::Result
<()> {
1954 self.commasep(Inconsistent
, &decl
.inputs
, |s
, ty
| {
1955 s
.ibox(indent_unit
)?
;
1957 s
.ann
.nested(s
, Nested
::BodyArgPat(body_id
, i
))?
;
1960 if ty
.node
!= hir
::TyInfer
{
1969 if let hir
::DefaultReturn(..) = decl
.output
{
1973 self.space_if_not_bol()?
;
1974 self.word_space("->")?
;
1976 hir
::Return(ref ty
) => {
1977 self.print_type(&ty
)?
;
1978 self.maybe_print_comment(ty
.span
.lo())
1980 hir
::DefaultReturn(..) => unreachable
!(),
1984 pub fn print_capture_clause(&mut self, capture_clause
: hir
::CaptureClause
) -> io
::Result
<()> {
1985 match capture_clause
{
1986 hir
::CaptureByValue
=> self.word_space("move"),
1987 hir
::CaptureByRef
=> Ok(()),
1991 pub fn print_bounds(&mut self, prefix
: &str, bounds
: &[hir
::TyParamBound
]) -> io
::Result
<()> {
1992 if !bounds
.is_empty() {
1993 self.s
.word(prefix
)?
;
1994 let mut first
= true;
1995 for bound
in bounds
{
2000 self.word_space("+")?
;
2004 TraitTyParamBound(ref tref
, TraitBoundModifier
::None
) => {
2005 self.print_poly_trait_ref(tref
)
2007 TraitTyParamBound(ref tref
, TraitBoundModifier
::Maybe
) => {
2009 self.print_poly_trait_ref(tref
)
2011 RegionTyParamBound(ref lt
) => {
2012 self.print_lifetime(lt
)
2022 pub fn print_lifetime(&mut self, lifetime
: &hir
::Lifetime
) -> io
::Result
<()> {
2023 self.print_name(lifetime
.name
.name())
2026 pub fn print_lifetime_def(&mut self, lifetime
: &hir
::LifetimeDef
) -> io
::Result
<()> {
2027 self.print_lifetime(&lifetime
.lifetime
)?
;
2029 for v
in &lifetime
.bounds
{
2031 self.print_lifetime(v
)?
;
2037 pub fn print_generics(&mut self, generics
: &hir
::Generics
) -> io
::Result
<()> {
2038 let total
= generics
.lifetimes
.len() + generics
.ty_params
.len();
2045 let mut ints
= Vec
::new();
2050 self.commasep(Inconsistent
, &ints
[..], |s
, &idx
| {
2051 if idx
< generics
.lifetimes
.len() {
2052 let lifetime
= &generics
.lifetimes
[idx
];
2053 s
.print_lifetime_def(lifetime
)
2055 let idx
= idx
- generics
.lifetimes
.len();
2056 let param
= &generics
.ty_params
[idx
];
2057 s
.print_ty_param(param
)
2065 pub fn print_ty_param(&mut self, param
: &hir
::TyParam
) -> io
::Result
<()> {
2066 self.print_name(param
.name
)?
;
2067 self.print_bounds(":", ¶m
.bounds
)?
;
2068 match param
.default {
2069 Some(ref default) => {
2071 self.word_space("=")?
;
2072 self.print_type(&default)
2078 pub fn print_where_clause(&mut self, where_clause
: &hir
::WhereClause
) -> io
::Result
<()> {
2079 if where_clause
.predicates
.is_empty() {
2084 self.word_space("where")?
;
2086 for (i
, predicate
) in where_clause
.predicates
.iter().enumerate() {
2088 self.word_space(",")?
;
2092 &hir
::WherePredicate
::BoundPredicate(hir
::WhereBoundPredicate
{ref bound_lifetimes
,
2096 self.print_formal_lifetime_list(bound_lifetimes
)?
;
2097 self.print_type(&bounded_ty
)?
;
2098 self.print_bounds(":", bounds
)?
;
2100 &hir
::WherePredicate
::RegionPredicate(hir
::WhereRegionPredicate
{ref lifetime
,
2103 self.print_lifetime(lifetime
)?
;
2106 for (i
, bound
) in bounds
.iter().enumerate() {
2107 self.print_lifetime(bound
)?
;
2114 &hir
::WherePredicate
::EqPredicate(hir
::WhereEqPredicate
{ref lhs_ty
,
2117 self.print_type(lhs_ty
)?
;
2119 self.word_space("=")?
;
2120 self.print_type(rhs_ty
)?
;
2128 pub fn print_mutability(&mut self, mutbl
: hir
::Mutability
) -> io
::Result
<()> {
2130 hir
::MutMutable
=> self.word_nbsp("mut"),
2131 hir
::MutImmutable
=> Ok(()),
2135 pub fn print_mt(&mut self, mt
: &hir
::MutTy
) -> io
::Result
<()> {
2136 self.print_mutability(mt
.mutbl
)?
;
2137 self.print_type(&mt
.ty
)
2140 pub fn print_fn_output(&mut self, decl
: &hir
::FnDecl
) -> io
::Result
<()> {
2141 if let hir
::DefaultReturn(..) = decl
.output
{
2145 self.space_if_not_bol()?
;
2146 self.ibox(indent_unit
)?
;
2147 self.word_space("->")?
;
2149 hir
::DefaultReturn(..) => unreachable
!(),
2150 hir
::Return(ref ty
) => self.print_type(&ty
)?
,
2155 hir
::Return(ref output
) => self.maybe_print_comment(output
.span
.lo()),
2160 pub fn print_ty_fn(&mut self,
2162 unsafety
: hir
::Unsafety
,
2164 name
: Option
<ast
::Name
>,
2165 generics
: &hir
::Generics
,
2166 arg_names
: &[Spanned
<ast
::Name
>])
2168 self.ibox(indent_unit
)?
;
2169 if !generics
.lifetimes
.is_empty() || !generics
.ty_params
.is_empty() {
2170 self.s
.word("for")?
;
2171 self.print_generics(generics
)?
;
2173 let generics
= hir
::Generics
{
2174 lifetimes
: hir
::HirVec
::new(),
2175 ty_params
: hir
::HirVec
::new(),
2176 where_clause
: hir
::WhereClause
{
2177 id
: ast
::DUMMY_NODE_ID
,
2178 predicates
: hir
::HirVec
::new(),
2180 span
: syntax_pos
::DUMMY_SP
,
2184 hir
::Constness
::NotConst
,
2194 pub fn maybe_print_trailing_comment(&mut self,
2195 span
: syntax_pos
::Span
,
2196 next_pos
: Option
<BytePos
>)
2198 let cm
= match self.cm
{
2202 if let Some(ref cmnt
) = self.next_comment() {
2203 if (*cmnt
).style
!= comments
::Trailing
{
2206 let span_line
= cm
.lookup_char_pos(span
.hi());
2207 let comment_line
= cm
.lookup_char_pos((*cmnt
).pos
);
2208 let mut next
= (*cmnt
).pos
+ BytePos(1);
2209 if let Some(p
) = next_pos
{
2212 if span
.hi() < (*cmnt
).pos
&& (*cmnt
).pos
< next
&&
2213 span_line
.line
== comment_line
.line
{
2214 self.print_comment(cmnt
)?
;
2220 pub fn print_remaining_comments(&mut self) -> io
::Result
<()> {
2221 // If there aren't any remaining comments, then we need to manually
2222 // make sure there is a line break at the end.
2223 if self.next_comment().is_none() {
2224 self.s
.hardbreak()?
;
2227 match self.next_comment() {
2229 self.print_comment(cmnt
)?
;
2237 pub fn print_opt_abi_and_extern_if_nondefault(&mut self,
2238 opt_abi
: Option
<Abi
>)
2241 Some(Abi
::Rust
) => Ok(()),
2243 self.word_nbsp("extern")?
;
2244 self.word_nbsp(&abi
.to_string())
2250 pub fn print_extern_opt_abi(&mut self, opt_abi
: Option
<Abi
>) -> io
::Result
<()> {
2253 self.word_nbsp("extern")?
;
2254 self.word_nbsp(&abi
.to_string())
2260 pub fn print_fn_header_info(&mut self,
2261 unsafety
: hir
::Unsafety
,
2262 constness
: hir
::Constness
,
2264 vis
: &hir
::Visibility
)
2266 self.s
.word(&visibility_qualified(vis
, ""))?
;
2267 self.print_unsafety(unsafety
)?
;
2270 hir
::Constness
::NotConst
=> {}
2271 hir
::Constness
::Const
=> self.word_nbsp("const")?
,
2274 if abi
!= Abi
::Rust
{
2275 self.word_nbsp("extern")?
;
2276 self.word_nbsp(&abi
.to_string())?
;
2282 pub fn print_unsafety(&mut self, s
: hir
::Unsafety
) -> io
::Result
<()> {
2284 hir
::Unsafety
::Normal
=> Ok(()),
2285 hir
::Unsafety
::Unsafe
=> self.word_nbsp("unsafe"),
2289 pub fn print_is_auto(&mut self, s
: hir
::IsAuto
) -> io
::Result
<()> {
2291 hir
::IsAuto
::Yes
=> self.word_nbsp("auto"),
2292 hir
::IsAuto
::No
=> Ok(()),
2297 // Dup'ed from parse::classify, but adapted for the HIR.
2298 /// Does this expression require a semicolon to be treated
2299 /// as a statement? The negation of this: 'can this expression
2300 /// be used as a statement without a semicolon' -- is used
2301 /// as an early-bail-out in the parser so that, for instance,
2302 /// if true {...} else {...}
2304 /// isn't parsed as (if true {...} else {...} | x) | 5
2305 fn expr_requires_semi_to_be_stmt(e
: &hir
::Expr
) -> bool
{
2308 hir
::ExprMatch(..) |
2310 hir
::ExprWhile(..) |
2311 hir
::ExprLoop(..) => false,
2316 /// this statement requires a semicolon after it.
2317 /// note that in one case (stmt_semi), we've already
2318 /// seen the semicolon, and thus don't need another.
2319 fn stmt_ends_with_semi(stmt
: &hir
::Stmt_
) -> bool
{
2321 hir
::StmtDecl(ref d
, _
) => {
2323 hir
::DeclLocal(_
) => true,
2324 hir
::DeclItem(_
) => false,
2327 hir
::StmtExpr(ref e
, _
) => {
2328 expr_requires_semi_to_be_stmt(&e
)
2330 hir
::StmtSemi(..) => {
2337 fn expr_precedence(expr
: &hir
::Expr
) -> i8 {
2338 use syntax
::util
::parser
::*;
2341 hir
::ExprClosure(..) => PREC_CLOSURE
,
2343 hir
::ExprBreak(..) |
2344 hir
::ExprAgain(..) |
2346 hir
::ExprYield(..) => PREC_JUMP
,
2348 // Binop-like expr kinds, handled by `AssocOp`.
2349 hir
::ExprBinary(op
, _
, _
) => bin_op_to_assoc_op(op
.node
).precedence() as i8,
2351 hir
::ExprCast(..) => AssocOp
::As
.precedence() as i8,
2352 hir
::ExprType(..) => AssocOp
::Colon
.precedence() as i8,
2354 hir
::ExprAssign(..) |
2355 hir
::ExprAssignOp(..) => AssocOp
::Assign
.precedence() as i8,
2359 hir
::ExprAddrOf(..) |
2360 hir
::ExprUnary(..) => PREC_PREFIX
,
2364 hir
::ExprMethodCall(..) |
2365 hir
::ExprField(..) |
2366 hir
::ExprTupField(..) |
2367 hir
::ExprIndex(..) |
2368 hir
::ExprInlineAsm(..) => PREC_POSTFIX
,
2370 // Never need parens
2371 hir
::ExprArray(..) |
2372 hir
::ExprRepeat(..) |
2377 hir
::ExprWhile(..) |
2379 hir
::ExprMatch(..) |
2380 hir
::ExprBlock(..) |
2381 hir
::ExprStruct(..) => PREC_PAREN
,
2385 fn bin_op_to_assoc_op(op
: hir
::BinOp_
) -> AssocOp
{
2388 BiAdd
=> AssocOp
::Add
,
2389 BiSub
=> AssocOp
::Subtract
,
2390 BiMul
=> AssocOp
::Multiply
,
2391 BiDiv
=> AssocOp
::Divide
,
2392 BiRem
=> AssocOp
::Modulus
,
2394 BiAnd
=> AssocOp
::LAnd
,
2395 BiOr
=> AssocOp
::LOr
,
2397 BiBitXor
=> AssocOp
::BitXor
,
2398 BiBitAnd
=> AssocOp
::BitAnd
,
2399 BiBitOr
=> AssocOp
::BitOr
,
2400 BiShl
=> AssocOp
::ShiftLeft
,
2401 BiShr
=> AssocOp
::ShiftRight
,
2403 BiEq
=> AssocOp
::Equal
,
2404 BiLt
=> AssocOp
::Less
,
2405 BiLe
=> AssocOp
::LessEqual
,
2406 BiNe
=> AssocOp
::NotEqual
,
2407 BiGe
=> AssocOp
::GreaterEqual
,
2408 BiGt
=> AssocOp
::Greater
,
2412 /// Expressions that syntactically contain an "exterior" struct literal i.e. not surrounded by any
2413 /// parens or other delimiters, e.g. `X { y: 1 }`, `X { y: 1 }.method()`, `foo == X { y: 1 }` and
2414 /// `X { y: 1 } == foo` all do, but `(X { y: 1 }) == foo` does not.
2415 fn contains_exterior_struct_lit(value
: &hir
::Expr
) -> bool
{
2417 hir
::ExprStruct(..) => true,
2419 hir
::ExprAssign(ref lhs
, ref rhs
) |
2420 hir
::ExprAssignOp(_
, ref lhs
, ref rhs
) |
2421 hir
::ExprBinary(_
, ref lhs
, ref rhs
) => {
2422 // X { y: 1 } + X { y: 2 }
2423 contains_exterior_struct_lit(&lhs
) || contains_exterior_struct_lit(&rhs
)
2425 hir
::ExprUnary(_
, ref x
) |
2426 hir
::ExprCast(ref x
, _
) |
2427 hir
::ExprType(ref x
, _
) |
2428 hir
::ExprField(ref x
, _
) |
2429 hir
::ExprTupField(ref x
, _
) |
2430 hir
::ExprIndex(ref x
, _
) => {
2431 // &X { y: 1 }, X { y: 1 }.y
2432 contains_exterior_struct_lit(&x
)
2435 hir
::ExprMethodCall(.., ref exprs
) => {
2436 // X { y: 1 }.bar(...)
2437 contains_exterior_struct_lit(&exprs
[0])