1 use crate::pp
::Breaks
::{Consistent, Inconsistent}
;
2 use crate::pp
::{self, Breaks}
;
6 use rustc_ast
::token
::{self, BinOpToken, CommentKind, DelimToken, Nonterminal, Token, TokenKind}
;
7 use rustc_ast
::tokenstream
::{TokenStream, TokenTree}
;
8 use rustc_ast
::util
::classify
;
9 use rustc_ast
::util
::comments
::{gather_comments, Comment, CommentStyle}
;
10 use rustc_ast
::util
::parser
::{self, AssocOp, Fixity}
;
11 use rustc_ast
::{self as ast, BlockCheckMode, PatKind, RangeEnd, RangeSyntax}
;
12 use rustc_ast
::{GenericArg, MacArgs, ModKind}
;
13 use rustc_ast
::{GenericBound, SelfKind, TraitBoundModifier}
;
14 use rustc_ast
::{InlineAsmOperand, InlineAsmRegOrRegClass}
;
15 use rustc_ast
::{InlineAsmOptions, InlineAsmTemplatePiece}
;
16 use rustc_span
::edition
::Edition
;
17 use rustc_span
::source_map
::{SourceMap, Spanned}
;
18 use rustc_span
::symbol
::{kw, sym, Ident, IdentPrinter, Symbol}
;
19 use rustc_span
::{BytePos, FileName, Span}
;
23 pub enum MacHeader
<'a
> {
25 Keyword(&'
static str),
28 pub enum AnnNode
<'a
> {
31 Block(&'a ast
::Block
),
36 Crate(&'a ast
::Crate
),
40 fn pre(&self, _state
: &mut State
<'_
>, _node
: AnnNode
<'_
>) {}
41 fn post(&self, _state
: &mut State
<'_
>, _node
: AnnNode
<'_
>) {}
44 #[derive(Copy, Clone)]
47 impl PpAnn
for NoAnn {}
49 pub struct Comments
<'a
> {
51 comments
: Vec
<Comment
>,
55 impl<'a
> Comments
<'a
> {
56 pub fn new(sm
: &'a SourceMap
, filename
: FileName
, input
: String
) -> Comments
<'a
> {
57 let comments
= gather_comments(sm
, filename
, input
);
58 Comments { sm, comments, current: 0 }
61 pub fn next(&self) -> Option
<Comment
> {
62 self.comments
.get(self.current
).cloned()
65 pub fn trailing_comment(
67 span
: rustc_span
::Span
,
68 next_pos
: Option
<BytePos
>,
69 ) -> Option
<Comment
> {
70 if let Some(cmnt
) = self.next() {
71 if cmnt
.style
!= CommentStyle
::Trailing
{
74 let span_line
= self.sm
.lookup_char_pos(span
.hi());
75 let comment_line
= self.sm
.lookup_char_pos(cmnt
.pos
);
76 let next
= next_pos
.unwrap_or_else(|| cmnt
.pos
+ BytePos(1));
77 if span
.hi() < cmnt
.pos
&& cmnt
.pos
< next
&& span_line
.line
== comment_line
.line
{
86 pub struct State
<'a
> {
88 comments
: Option
<Comments
<'a
>>,
89 ann
: &'
a (dyn PpAnn
+ 'a
),
92 crate const INDENT_UNIT
: usize = 4;
94 /// Requires you to pass an input filename and reader so that
95 /// it can scan the input text for comments to copy forward.
96 pub fn print_crate
<'a
>(
106 State { s: pp::mk_printer(), comments: Some(Comments::new(sm, filename, input)), ann }
;
108 if is_expanded
&& !krate
.attrs
.iter().any(|attr
| attr
.has_name(sym
::no_core
)) {
109 // We need to print `#![no_std]` (and its feature gate) so that
110 // compiling pretty-printed source won't inject libstd again.
111 // However, we don't want these attributes in the AST because
112 // of the feature gate, so we fake them up here.
114 // `#![feature(prelude_import)]`
115 let pi_nested
= attr
::mk_nested_word_item(Ident
::with_dummy_span(sym
::prelude_import
));
116 let list
= attr
::mk_list_item(Ident
::with_dummy_span(sym
::feature
), vec
![pi_nested
]);
117 let fake_attr
= attr
::mk_attr_inner(list
);
118 s
.print_attribute(&fake_attr
);
120 // Currently, in Rust 2018 we don't have `extern crate std;` at the crate
121 // root, so this is not needed, and actually breaks things.
122 if edition
== Edition
::Edition2015
{
124 let no_std_meta
= attr
::mk_word_item(Ident
::with_dummy_span(sym
::no_std
));
125 let fake_attr
= attr
::mk_attr_inner(no_std_meta
);
126 s
.print_attribute(&fake_attr
);
130 s
.print_inner_attributes(&krate
.attrs
);
131 for item
in &krate
.items
{
134 s
.print_remaining_comments();
135 s
.ann
.post(&mut s
, AnnNode
::Crate(krate
));
139 /// This makes printed token streams look slightly nicer,
140 /// and also addresses some specific regressions described in #63896 and #73345.
141 fn tt_prepend_space(tt
: &TokenTree
, prev
: &TokenTree
) -> bool
{
142 if let TokenTree
::Token(token
) = prev
{
143 if matches
!(token
.kind
, token
::Dot
| token
::Dollar
) {
146 if let token
::DocComment(comment_kind
, ..) = token
.kind
{
147 return comment_kind
!= CommentKind
::Line
;
151 TokenTree
::Token(token
) => !matches
!(token
.kind
, token
::Comma
| token
::Not
| token
::Dot
),
152 TokenTree
::Delimited(_
, DelimToken
::Paren
, _
) => {
153 !matches
!(prev
, TokenTree
::Token(Token { kind: token::Ident(..), .. }
))
155 TokenTree
::Delimited(_
, DelimToken
::Bracket
, _
) => {
156 !matches
!(prev
, TokenTree
::Token(Token { kind: token::Pound, .. }
))
158 TokenTree
::Delimited(..) => true,
162 fn binop_to_string(op
: BinOpToken
) -> &'
static str {
168 token
::Percent
=> "%",
177 fn doc_comment_to_string(
178 comment_kind
: CommentKind
,
179 attr_style
: ast
::AttrStyle
,
182 match (comment_kind
, attr_style
) {
183 (CommentKind
::Line
, ast
::AttrStyle
::Outer
) => format
!("///{}", data
),
184 (CommentKind
::Line
, ast
::AttrStyle
::Inner
) => format
!("//!{}", data
),
185 (CommentKind
::Block
, ast
::AttrStyle
::Outer
) => format
!("/**{}*/", data
),
186 (CommentKind
::Block
, ast
::AttrStyle
::Inner
) => format
!("/*!{}*/", data
),
190 pub fn literal_to_string(lit
: token
::Lit
) -> String
{
191 let token
::Lit { kind, symbol, suffix }
= lit
;
192 let mut out
= match kind
{
193 token
::Byte
=> format
!("b'{}'", symbol
),
194 token
::Char
=> format
!("'{}'", symbol
),
195 token
::Str
=> format
!("\"{}\"", symbol
),
196 token
::StrRaw(n
) => {
197 format
!("r{delim}\"{string}\"{delim}", delim
= "#".repeat(n
as usize), string
= symbol
)
199 token
::ByteStr
=> format
!("b\"{}\"", symbol
),
200 token
::ByteStrRaw(n
) => {
201 format
!("br{delim}\"{string}\"{delim}", delim
= "#".repeat(n
as usize), string
= symbol
)
203 token
::Integer
| token
::Float
| token
::Bool
| token
::Err
=> symbol
.to_string(),
206 if let Some(suffix
) = suffix
{
207 out
.push_str(&suffix
.as_str())
213 fn visibility_qualified(vis
: &ast
::Visibility
, s
: &str) -> String
{
214 format
!("{}{}", State
::new().to_string(|s
| s
.print_visibility(vis
)), s
)
217 impl std
::ops
::Deref
for State
<'_
> {
218 type Target
= pp
::Printer
;
219 fn deref(&self) -> &Self::Target
{
224 impl std
::ops
::DerefMut
for State
<'_
> {
225 fn deref_mut(&mut self) -> &mut Self::Target
{
230 pub trait PrintState
<'a
>: std
::ops
::Deref
<Target
= pp
::Printer
> + std
::ops
::DerefMut
{
231 fn comments(&mut self) -> &mut Option
<Comments
<'a
>>;
232 fn print_ident(&mut self, ident
: Ident
);
233 fn print_generic_args(&mut self, args
: &ast
::GenericArgs
, colons_before_params
: bool
);
243 F
: FnMut(&mut Self, &T
),
246 if let Some((first
, rest
)) = elts
.split_first() {
252 self.word_space(sep
);
259 fn commasep
<T
, F
>(&mut self, b
: Breaks
, elts
: &[T
], op
: F
)
261 F
: FnMut(&mut Self, &T
),
263 self.strsep(",", false, b
, elts
, op
)
266 fn maybe_print_comment(&mut self, pos
: BytePos
) {
267 while let Some(ref cmnt
) = self.next_comment() {
269 self.print_comment(cmnt
);
276 fn print_comment(&mut self, cmnt
: &Comment
) {
278 CommentStyle
::Mixed
=> {
279 if !self.is_beginning_of_line() {
282 if let Some((last
, lines
)) = cmnt
.lines
.split_last() {
286 self.word(line
.clone());
290 self.word(last
.clone());
297 CommentStyle
::Isolated
=> {
298 self.hardbreak_if_not_bol();
299 for line
in &cmnt
.lines
{
300 // Don't print empty lines because they will end up as trailing
302 if !line
.is_empty() {
303 self.word(line
.clone());
308 CommentStyle
::Trailing
=> {
309 if !self.is_beginning_of_line() {
312 if cmnt
.lines
.len() == 1 {
313 self.word(cmnt
.lines
[0].clone());
317 for line
in &cmnt
.lines
{
318 if !line
.is_empty() {
319 self.word(line
.clone());
326 CommentStyle
::BlankLine
=> {
327 // We need to do at least one, possibly two hardbreaks.
328 let twice
= match self.last_token() {
329 pp
::Token
::String(s
) => ";" == s
,
330 pp
::Token
::Begin(_
) => true,
331 pp
::Token
::End
=> true,
340 if let Some(cmnts
) = self.comments() {
345 fn next_comment(&mut self) -> Option
<Comment
> {
346 self.comments().as_mut().and_then(|c
| c
.next())
349 fn print_literal(&mut self, lit
: &ast
::Lit
) {
350 self.maybe_print_comment(lit
.span
.lo());
351 self.word(lit
.token
.to_string())
354 fn print_string(&mut self, st
: &str, style
: ast
::StrStyle
) {
355 let st
= match style
{
356 ast
::StrStyle
::Cooked
=> (format
!("\"{}\"", st
.escape_debug())),
357 ast
::StrStyle
::Raw(n
) => {
358 format
!("r{delim}\"{string}\"{delim}", delim
= "#".repeat(n
as usize), string
= st
)
364 fn print_symbol(&mut self, sym
: Symbol
, style
: ast
::StrStyle
) {
365 self.print_string(&sym
.as_str(), style
);
368 fn print_inner_attributes(&mut self, attrs
: &[ast
::Attribute
]) {
369 self.print_either_attributes(attrs
, ast
::AttrStyle
::Inner
, false, true)
372 fn print_inner_attributes_no_trailing_hardbreak(&mut self, attrs
: &[ast
::Attribute
]) {
373 self.print_either_attributes(attrs
, ast
::AttrStyle
::Inner
, false, false)
376 fn print_outer_attributes(&mut self, attrs
: &[ast
::Attribute
]) {
377 self.print_either_attributes(attrs
, ast
::AttrStyle
::Outer
, false, true)
380 fn print_inner_attributes_inline(&mut self, attrs
: &[ast
::Attribute
]) {
381 self.print_either_attributes(attrs
, ast
::AttrStyle
::Inner
, true, true)
384 fn print_outer_attributes_inline(&mut self, attrs
: &[ast
::Attribute
]) {
385 self.print_either_attributes(attrs
, ast
::AttrStyle
::Outer
, true, true)
388 fn print_either_attributes(
390 attrs
: &[ast
::Attribute
],
391 kind
: ast
::AttrStyle
,
393 trailing_hardbreak
: bool
,
397 if attr
.style
== kind
{
398 self.print_attribute_inline(attr
, is_inline
);
405 if count
> 0 && trailing_hardbreak
&& !is_inline
{
406 self.hardbreak_if_not_bol();
410 fn print_attribute(&mut self, attr
: &ast
::Attribute
) {
411 self.print_attribute_inline(attr
, false)
414 fn print_attribute_inline(&mut self, attr
: &ast
::Attribute
, is_inline
: bool
) {
416 self.hardbreak_if_not_bol();
418 self.maybe_print_comment(attr
.span
.lo());
420 ast
::AttrKind
::Normal(ref item
, _
) => {
422 ast
::AttrStyle
::Inner
=> self.word("#!["),
423 ast
::AttrStyle
::Outer
=> self.word("#["),
425 self.print_attr_item(&item
, attr
.span
);
428 ast
::AttrKind
::DocComment(comment_kind
, data
) => {
429 self.word(doc_comment_to_string(comment_kind
, attr
.style
, data
));
435 fn print_attr_item(&mut self, item
: &ast
::AttrItem
, span
: Span
) {
438 MacArgs
::Delimited(_
, delim
, tokens
) => self.print_mac_common(
439 Some(MacHeader
::Path(&item
.path
)),
447 MacArgs
::Empty
| MacArgs
::Eq(..) => {
448 self.print_path(&item
.path
, false, 0);
449 if let MacArgs
::Eq(_
, token
) = &item
.args
{
451 self.word_space("=");
452 let token_str
= self.token_to_string_ext(token
, true);
453 self.word(token_str
);
460 fn print_meta_list_item(&mut self, item
: &ast
::NestedMetaItem
) {
462 ast
::NestedMetaItem
::MetaItem(ref mi
) => self.print_meta_item(mi
),
463 ast
::NestedMetaItem
::Literal(ref lit
) => self.print_literal(lit
),
467 fn print_meta_item(&mut self, item
: &ast
::MetaItem
) {
468 self.ibox(INDENT_UNIT
);
470 ast
::MetaItemKind
::Word
=> self.print_path(&item
.path
, false, 0),
471 ast
::MetaItemKind
::NameValue(ref value
) => {
472 self.print_path(&item
.path
, false, 0);
474 self.word_space("=");
475 self.print_literal(value
);
477 ast
::MetaItemKind
::List(ref items
) => {
478 self.print_path(&item
.path
, false, 0);
480 self.commasep(Consistent
, &items
[..], |s
, i
| s
.print_meta_list_item(i
));
487 /// This doesn't deserve to be called "pretty" printing, but it should be
488 /// meaning-preserving. A quick hack that might help would be to look at the
489 /// spans embedded in the TTs to decide where to put spaces and newlines.
490 /// But it'd be better to parse these according to the grammar of the
491 /// appropriate macro, transcribe back into the grammar we just parsed from,
492 /// and then pretty-print the resulting AST nodes (so, e.g., we print
493 /// expression arguments as expressions). It can be done! I think.
494 fn print_tt(&mut self, tt
: &TokenTree
, convert_dollar_crate
: bool
) {
496 TokenTree
::Token(token
) => {
497 let token_str
= self.token_to_string_ext(&token
, convert_dollar_crate
);
498 self.word(token_str
);
499 if let token
::DocComment(..) = token
.kind
{
503 TokenTree
::Delimited(dspan
, delim
, tts
) => {
504 self.print_mac_common(
510 convert_dollar_crate
,
517 fn print_tts(&mut self, tts
: &TokenStream
, convert_dollar_crate
: bool
) {
518 let mut iter
= tts
.trees().peekable();
519 while let Some(tt
) = iter
.next() {
520 self.print_tt(&tt
, convert_dollar_crate
);
521 if let Some(next
) = iter
.peek() {
522 if tt_prepend_space(next
, &tt
) {
531 header
: Option
<MacHeader
<'_
>>,
533 ident
: Option
<Ident
>,
536 convert_dollar_crate
: bool
,
539 if delim
== DelimToken
::Brace
{
540 self.cbox(INDENT_UNIT
);
543 Some(MacHeader
::Path(path
)) => self.print_path(path
, false, 0),
544 Some(MacHeader
::Keyword(kw
)) => self.word(kw
),
550 if let Some(ident
) = ident
{
552 self.print_ident(ident
);
555 DelimToken
::Brace
=> {
556 if header
.is_some() || has_bang
|| ident
.is_some() {
565 let token_str
= self.token_kind_to_string(&token
::OpenDelim(delim
));
570 self.print_tts(tts
, convert_dollar_crate
);
573 DelimToken
::Brace
=> self.bclose(span
),
575 let token_str
= self.token_kind_to_string(&token
::CloseDelim(delim
));
581 fn print_path(&mut self, path
: &ast
::Path
, colons_before_params
: bool
, depth
: usize) {
582 self.maybe_print_comment(path
.span
.lo());
584 for (i
, segment
) in path
.segments
[..path
.segments
.len() - depth
].iter().enumerate() {
588 self.print_path_segment(segment
, colons_before_params
);
592 fn print_path_segment(&mut self, segment
: &ast
::PathSegment
, colons_before_params
: bool
) {
593 if segment
.ident
.name
!= kw
::PathRoot
{
594 self.print_ident(segment
.ident
);
595 if let Some(ref args
) = segment
.args
{
596 self.print_generic_args(args
, colons_before_params
);
601 fn head
<S
: Into
<Cow
<'
static, str>>>(&mut self, w
: S
) {
603 // Outer-box is consistent.
604 self.cbox(INDENT_UNIT
);
605 // Head-box is inconsistent.
606 self.ibox(w
.len() + 1);
607 // Keyword that starts the head.
613 fn bopen(&mut self) {
615 self.end(); // Close the head-box.
618 fn bclose_maybe_open(&mut self, span
: rustc_span
::Span
, close_box
: bool
) {
619 self.maybe_print_comment(span
.hi());
620 self.break_offset_if_not_bol(1, -(INDENT_UNIT
as isize));
623 self.end(); // Close the outer-box.
627 fn bclose(&mut self, span
: rustc_span
::Span
) {
628 self.bclose_maybe_open(span
, true)
631 fn break_offset_if_not_bol(&mut self, n
: usize, off
: isize) {
632 if !self.is_beginning_of_line() {
633 self.break_offset(n
, off
)
634 } else if off
!= 0 && self.last_token().is_hardbreak_tok() {
635 // We do something pretty sketchy here: tuck the nonzero
636 // offset-adjustment we were going to deposit along with the
637 // break into the previous hardbreak.
638 self.replace_last_token(pp
::Printer
::hardbreak_tok_offset(off
));
642 fn nonterminal_to_string(&self, nt
: &Nonterminal
) -> String
{
644 token
::NtExpr(ref e
) => self.expr_to_string(e
),
645 token
::NtMeta(ref e
) => self.attr_item_to_string(e
),
646 token
::NtTy(ref e
) => self.ty_to_string(e
),
647 token
::NtPath(ref e
) => self.path_to_string(e
),
648 token
::NtItem(ref e
) => self.item_to_string(e
),
649 token
::NtBlock(ref e
) => self.block_to_string(e
),
650 token
::NtStmt(ref e
) => self.stmt_to_string(e
),
651 token
::NtPat(ref e
) => self.pat_to_string(e
),
652 token
::NtIdent(e
, is_raw
) => IdentPrinter
::for_ast_ident(e
, is_raw
).to_string(),
653 token
::NtLifetime(e
) => e
.to_string(),
654 token
::NtLiteral(ref e
) => self.expr_to_string(e
),
655 token
::NtTT(ref tree
) => self.tt_to_string(tree
),
656 token
::NtVis(ref e
) => self.vis_to_string(e
),
660 /// Print the token kind precisely, without converting `$crate` into its respective crate name.
661 fn token_kind_to_string(&self, tok
: &TokenKind
) -> String
{
662 self.token_kind_to_string_ext(tok
, None
)
665 fn token_kind_to_string_ext(
668 convert_dollar_crate
: Option
<Span
>,
671 token
::Eq
=> "=".to_string(),
672 token
::Lt
=> "<".to_string(),
673 token
::Le
=> "<=".to_string(),
674 token
::EqEq
=> "==".to_string(),
675 token
::Ne
=> "!=".to_string(),
676 token
::Ge
=> ">=".to_string(),
677 token
::Gt
=> ">".to_string(),
678 token
::Not
=> "!".to_string(),
679 token
::Tilde
=> "~".to_string(),
680 token
::OrOr
=> "||".to_string(),
681 token
::AndAnd
=> "&&".to_string(),
682 token
::BinOp(op
) => binop_to_string(op
).to_string(),
683 token
::BinOpEq(op
) => format
!("{}=", binop_to_string(op
)),
685 /* Structural symbols */
686 token
::At
=> "@".to_string(),
687 token
::Dot
=> ".".to_string(),
688 token
::DotDot
=> "..".to_string(),
689 token
::DotDotDot
=> "...".to_string(),
690 token
::DotDotEq
=> "..=".to_string(),
691 token
::Comma
=> ",".to_string(),
692 token
::Semi
=> ";".to_string(),
693 token
::Colon
=> ":".to_string(),
694 token
::ModSep
=> "::".to_string(),
695 token
::RArrow
=> "->".to_string(),
696 token
::LArrow
=> "<-".to_string(),
697 token
::FatArrow
=> "=>".to_string(),
698 token
::OpenDelim(token
::Paren
) => "(".to_string(),
699 token
::CloseDelim(token
::Paren
) => ")".to_string(),
700 token
::OpenDelim(token
::Bracket
) => "[".to_string(),
701 token
::CloseDelim(token
::Bracket
) => "]".to_string(),
702 token
::OpenDelim(token
::Brace
) => "{".to_string(),
703 token
::CloseDelim(token
::Brace
) => "}".to_string(),
704 token
::OpenDelim(token
::NoDelim
) | token
::CloseDelim(token
::NoDelim
) => "".to_string(),
705 token
::Pound
=> "#".to_string(),
706 token
::Dollar
=> "$".to_string(),
707 token
::Question
=> "?".to_string(),
708 token
::SingleQuote
=> "'".to_string(),
711 token
::Literal(lit
) => literal_to_string(lit
),
713 /* Name components */
714 token
::Ident(s
, is_raw
) => {
715 IdentPrinter
::new(s
, is_raw
, convert_dollar_crate
).to_string()
717 token
::Lifetime(s
) => s
.to_string(),
720 token
::DocComment(comment_kind
, attr_style
, data
) => {
721 doc_comment_to_string(comment_kind
, attr_style
, data
)
723 token
::Eof
=> "<eof>".to_string(),
725 token
::Interpolated(ref nt
) => self.nonterminal_to_string(nt
),
729 /// Print the token precisely, without converting `$crate` into its respective crate name.
730 fn token_to_string(&self, token
: &Token
) -> String
{
731 self.token_to_string_ext(token
, false)
734 fn token_to_string_ext(&self, token
: &Token
, convert_dollar_crate
: bool
) -> String
{
735 let convert_dollar_crate
= convert_dollar_crate
.then_some(token
.span
);
736 self.token_kind_to_string_ext(&token
.kind
, convert_dollar_crate
)
739 fn ty_to_string(&self, ty
: &ast
::Ty
) -> String
{
740 self.to_string(|s
| s
.print_type(ty
))
743 fn bounds_to_string(&self, bounds
: &[ast
::GenericBound
]) -> String
{
744 self.to_string(|s
| s
.print_type_bounds("", bounds
))
747 fn pat_to_string(&self, pat
: &ast
::Pat
) -> String
{
748 self.to_string(|s
| s
.print_pat(pat
))
751 fn expr_to_string(&self, e
: &ast
::Expr
) -> String
{
752 self.to_string(|s
| s
.print_expr(e
))
755 fn tt_to_string(&self, tt
: &TokenTree
) -> String
{
756 self.to_string(|s
| s
.print_tt(tt
, false))
759 fn tts_to_string(&self, tokens
: &TokenStream
) -> String
{
760 self.to_string(|s
| s
.print_tts(tokens
, false))
763 fn stmt_to_string(&self, stmt
: &ast
::Stmt
) -> String
{
764 self.to_string(|s
| s
.print_stmt(stmt
))
767 fn item_to_string(&self, i
: &ast
::Item
) -> String
{
768 self.to_string(|s
| s
.print_item(i
))
771 fn generic_params_to_string(&self, generic_params
: &[ast
::GenericParam
]) -> String
{
772 self.to_string(|s
| s
.print_generic_params(generic_params
))
775 fn path_to_string(&self, p
: &ast
::Path
) -> String
{
776 self.to_string(|s
| s
.print_path(p
, false, 0))
779 fn path_segment_to_string(&self, p
: &ast
::PathSegment
) -> String
{
780 self.to_string(|s
| s
.print_path_segment(p
, false))
783 fn vis_to_string(&self, v
: &ast
::Visibility
) -> String
{
784 self.to_string(|s
| s
.print_visibility(v
))
787 fn block_to_string(&self, blk
: &ast
::Block
) -> String
{
789 // Containing cbox, will be closed by `print_block` at `}`.
791 // Head-ibox, will be closed by `print_block` after `{`.
797 fn meta_list_item_to_string(&self, li
: &ast
::NestedMetaItem
) -> String
{
798 self.to_string(|s
| s
.print_meta_list_item(li
))
801 fn attr_item_to_string(&self, ai
: &ast
::AttrItem
) -> String
{
802 self.to_string(|s
| s
.print_attr_item(ai
, ai
.path
.span
))
805 fn attribute_to_string(&self, attr
: &ast
::Attribute
) -> String
{
806 self.to_string(|s
| s
.print_attribute(attr
))
809 fn param_to_string(&self, arg
: &ast
::Param
) -> String
{
810 self.to_string(|s
| s
.print_param(arg
, false))
813 fn to_string(&self, f
: impl FnOnce(&mut State
<'_
>)) -> String
{
814 let mut printer
= State
::new();
820 impl<'a
> PrintState
<'a
> for State
<'a
> {
821 fn comments(&mut self) -> &mut Option
<Comments
<'a
>> {
825 fn print_ident(&mut self, ident
: Ident
) {
826 self.s
.word(IdentPrinter
::for_ast_ident(ident
, ident
.is_raw_guess()).to_string());
827 self.ann
.post(self, AnnNode
::Ident(&ident
))
830 fn print_generic_args(&mut self, args
: &ast
::GenericArgs
, colons_before_params
: bool
) {
831 if colons_before_params
{
836 ast
::GenericArgs
::AngleBracketed(ref data
) => {
838 self.commasep(Inconsistent
, &data
.args
, |s
, arg
| match arg
{
839 ast
::AngleBracketedArg
::Arg(a
) => s
.print_generic_arg(a
),
840 ast
::AngleBracketedArg
::Constraint(c
) => s
.print_assoc_constraint(c
),
845 ast
::GenericArgs
::Parenthesized(ref data
) => {
847 self.commasep(Inconsistent
, &data
.inputs
, |s
, ty
| s
.print_type(ty
));
849 self.print_fn_ret_ty(&data
.output
);
856 pub fn new() -> State
<'a
> {
857 State { s: pp::mk_printer(), comments: None, ann: &NoAnn }
860 // Synthesizes a comment that was not textually present in the original source
862 pub fn synth_comment(&mut self, text
: String
) {
870 crate fn commasep_cmnt
<T
, F
, G
>(&mut self, b
: Breaks
, elts
: &[T
], mut op
: F
, mut get_span
: G
)
872 F
: FnMut(&mut State
<'_
>, &T
),
873 G
: FnMut(&T
) -> rustc_span
::Span
,
876 let len
= elts
.len();
879 self.maybe_print_comment(get_span(elt
).hi());
884 self.maybe_print_trailing_comment(get_span(elt
), Some(get_span(&elts
[i
]).hi()));
885 self.space_if_not_bol();
891 crate fn commasep_exprs(&mut self, b
: Breaks
, exprs
: &[P
<ast
::Expr
>]) {
892 self.commasep_cmnt(b
, exprs
, |s
, e
| s
.print_expr(e
), |e
| e
.span
)
895 crate fn print_foreign_mod(&mut self, nmod
: &ast
::ForeignMod
, attrs
: &[ast
::Attribute
]) {
896 self.print_inner_attributes(attrs
);
897 for item
in &nmod
.items
{
898 self.print_foreign_item(item
);
902 pub fn print_opt_lifetime(&mut self, lifetime
: &Option
<ast
::Lifetime
>) {
903 if let Some(lt
) = *lifetime
{
904 self.print_lifetime(lt
);
909 pub fn print_assoc_constraint(&mut self, constraint
: &ast
::AssocTyConstraint
) {
910 self.print_ident(constraint
.ident
);
911 constraint
.gen_args
.as_ref().map(|args
| self.print_generic_args(args
, false));
913 match &constraint
.kind
{
914 ast
::AssocTyConstraintKind
::Equality { ty }
=> {
915 self.word_space("=");
918 ast
::AssocTyConstraintKind
::Bound { bounds }
=> {
919 self.print_type_bounds(":", &*bounds
);
924 pub fn print_generic_arg(&mut self, generic_arg
: &GenericArg
) {
926 GenericArg
::Lifetime(lt
) => self.print_lifetime(*lt
),
927 GenericArg
::Type(ty
) => self.print_type(ty
),
928 GenericArg
::Const(ct
) => self.print_expr(&ct
.value
),
932 pub fn print_type(&mut self, ty
: &ast
::Ty
) {
933 self.maybe_print_comment(ty
.span
.lo());
936 ast
::TyKind
::Slice(ref ty
) => {
941 ast
::TyKind
::Ptr(ref mt
) => {
943 self.print_mt(mt
, true);
945 ast
::TyKind
::Rptr(ref lifetime
, ref mt
) => {
947 self.print_opt_lifetime(lifetime
);
948 self.print_mt(mt
, false);
950 ast
::TyKind
::Never
=> {
953 ast
::TyKind
::Tup(ref elts
) => {
955 self.commasep(Inconsistent
, &elts
[..], |s
, ty
| s
.print_type(ty
));
961 ast
::TyKind
::AnonymousStruct(ref fields
, ..) => {
963 self.print_record_struct_body(&fields
, ty
.span
);
965 ast
::TyKind
::AnonymousUnion(ref fields
, ..) => {
967 self.print_record_struct_body(&fields
, ty
.span
);
969 ast
::TyKind
::Paren(ref typ
) => {
971 self.print_type(typ
);
974 ast
::TyKind
::BareFn(ref f
) => {
975 self.print_ty_fn(f
.ext
, f
.unsafety
, &f
.decl
, None
, &f
.generic_params
);
977 ast
::TyKind
::Path(None
, ref path
) => {
978 self.print_path(path
, false, 0);
980 ast
::TyKind
::Path(Some(ref qself
), ref path
) => self.print_qpath(path
, qself
, false),
981 ast
::TyKind
::TraitObject(ref bounds
, syntax
) => {
982 let prefix
= if syntax
== ast
::TraitObjectSyntax
::Dyn { "dyn" }
else { "" }
;
983 self.print_type_bounds(prefix
, &bounds
[..]);
985 ast
::TyKind
::ImplTrait(_
, ref bounds
) => {
986 self.print_type_bounds("impl", &bounds
[..]);
988 ast
::TyKind
::Array(ref ty
, ref length
) => {
992 self.print_expr(&length
.value
);
995 ast
::TyKind
::Typeof(ref e
) => {
996 self.s
.word("typeof(");
997 self.print_expr(&e
.value
);
1000 ast
::TyKind
::Infer
=> {
1003 ast
::TyKind
::Err
=> {
1005 self.s
.word("/*ERROR*/");
1008 ast
::TyKind
::ImplicitSelf
=> {
1009 self.s
.word("Self");
1011 ast
::TyKind
::MacCall(ref m
) => {
1014 ast
::TyKind
::CVarArgs
=> {
1021 crate fn print_foreign_item(&mut self, item
: &ast
::ForeignItem
) {
1022 let ast
::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ }
= *item
;
1023 self.ann
.pre(self, AnnNode
::SubItem(id
));
1024 self.hardbreak_if_not_bol();
1025 self.maybe_print_comment(span
.lo());
1026 self.print_outer_attributes(attrs
);
1028 ast
::ForeignItemKind
::Fn(box ast
::FnKind(def
, sig
, gen
, body
)) => {
1029 self.print_fn_full(sig
, ident
, gen
, vis
, *def
, body
.as_deref(), attrs
);
1031 ast
::ForeignItemKind
::Static(ty
, mutbl
, body
) => {
1032 let def
= ast
::Defaultness
::Final
;
1033 self.print_item_const(ident
, Some(*mutbl
), ty
, body
.as_deref(), vis
, def
);
1035 ast
::ForeignItemKind
::TyAlias(box ast
::TyAliasKind(def
, generics
, bounds
, ty
)) => {
1036 self.print_associated_type(ident
, generics
, bounds
, ty
.as_deref(), vis
, *def
);
1038 ast
::ForeignItemKind
::MacCall(m
) => {
1040 if m
.args
.need_semicolon() {
1045 self.ann
.post(self, AnnNode
::SubItem(id
))
1048 fn print_item_const(
1051 mutbl
: Option
<ast
::Mutability
>,
1053 body
: Option
<&ast
::Expr
>,
1054 vis
: &ast
::Visibility
,
1055 defaultness
: ast
::Defaultness
,
1058 self.print_visibility(vis
);
1059 self.print_defaultness(defaultness
);
1060 let leading
= match mutbl
{
1062 Some(ast
::Mutability
::Not
) => "static",
1063 Some(ast
::Mutability
::Mut
) => "static mut",
1065 self.word_space(leading
);
1066 self.print_ident(ident
);
1067 self.word_space(":");
1068 self.print_type(ty
);
1070 self.end(); // end the head-ibox
1071 if let Some(body
) = body
{
1072 self.word_space("=");
1073 self.print_expr(body
);
1076 self.end(); // end the outer cbox
1079 fn print_associated_type(
1082 generics
: &ast
::Generics
,
1083 bounds
: &ast
::GenericBounds
,
1084 ty
: Option
<&ast
::Ty
>,
1085 vis
: &ast
::Visibility
,
1086 defaultness
: ast
::Defaultness
,
1089 self.print_visibility(vis
);
1090 self.print_defaultness(defaultness
);
1091 self.word_space("type");
1092 self.print_ident(ident
);
1093 self.print_generic_params(&generics
.params
);
1094 self.print_type_bounds(":", bounds
);
1095 self.print_where_clause(&generics
.where_clause
);
1096 if let Some(ty
) = ty
{
1098 self.word_space("=");
1099 self.print_type(ty
);
1102 self.end(); // end inner head-block
1103 self.end(); // end outer head-block
1106 /// Pretty-prints an item.
1107 crate fn print_item(&mut self, item
: &ast
::Item
) {
1108 self.hardbreak_if_not_bol();
1109 self.maybe_print_comment(item
.span
.lo());
1110 self.print_outer_attributes(&item
.attrs
);
1111 self.ann
.pre(self, AnnNode
::Item(item
));
1113 ast
::ItemKind
::ExternCrate(orig_name
) => {
1114 self.head(visibility_qualified(&item
.vis
, "extern crate"));
1115 if let Some(orig_name
) = orig_name
{
1116 self.print_name(orig_name
);
1121 self.print_ident(item
.ident
);
1123 self.end(); // end inner head-block
1124 self.end(); // end outer head-block
1126 ast
::ItemKind
::Use(ref tree
) => {
1127 self.head(visibility_qualified(&item
.vis
, "use"));
1128 self.print_use_tree(tree
);
1130 self.end(); // end inner head-block
1131 self.end(); // end outer head-block
1133 ast
::ItemKind
::Static(ref ty
, mutbl
, ref body
) => {
1134 let def
= ast
::Defaultness
::Final
;
1135 self.print_item_const(item
.ident
, Some(mutbl
), ty
, body
.as_deref(), &item
.vis
, def
);
1137 ast
::ItemKind
::Const(def
, ref ty
, ref body
) => {
1138 self.print_item_const(item
.ident
, None
, ty
, body
.as_deref(), &item
.vis
, def
);
1140 ast
::ItemKind
::Fn(box ast
::FnKind(def
, ref sig
, ref gen
, ref body
)) => {
1141 let body
= body
.as_deref();
1142 self.print_fn_full(sig
, item
.ident
, gen
, &item
.vis
, def
, body
, &item
.attrs
);
1144 ast
::ItemKind
::Mod(unsafety
, ref mod_kind
) => {
1145 self.head(self.to_string(|s
| {
1146 s
.print_visibility(&item
.vis
);
1147 s
.print_unsafety(unsafety
);
1150 self.print_ident(item
.ident
);
1153 ModKind
::Loaded(items
, ..) => {
1156 self.print_inner_attributes(&item
.attrs
);
1158 self.print_item(item
);
1160 self.bclose(item
.span
);
1162 ModKind
::Unloaded
=> {
1164 self.end(); // end inner head-block
1165 self.end(); // end outer head-block
1169 ast
::ItemKind
::ForeignMod(ref nmod
) => {
1170 self.head(self.to_string(|s
| {
1171 s
.print_unsafety(nmod
.unsafety
);
1174 if let Some(abi
) = nmod
.abi
{
1175 self.print_literal(&abi
.as_lit());
1179 self.print_foreign_mod(nmod
, &item
.attrs
);
1180 self.bclose(item
.span
);
1182 ast
::ItemKind
::GlobalAsm(ref asm
) => {
1183 self.head(visibility_qualified(&item
.vis
, "global_asm!"));
1184 self.print_inline_asm(asm
);
1187 ast
::ItemKind
::TyAlias(box ast
::TyAliasKind(def
, ref generics
, ref bounds
, ref ty
)) => {
1188 let ty
= ty
.as_deref();
1189 self.print_associated_type(item
.ident
, generics
, bounds
, ty
, &item
.vis
, def
);
1191 ast
::ItemKind
::Enum(ref enum_definition
, ref params
) => {
1192 self.print_enum_def(enum_definition
, params
, item
.ident
, item
.span
, &item
.vis
);
1194 ast
::ItemKind
::Struct(ref struct_def
, ref generics
) => {
1195 self.head(visibility_qualified(&item
.vis
, "struct"));
1196 self.print_struct(struct_def
, generics
, item
.ident
, item
.span
, true);
1198 ast
::ItemKind
::Union(ref struct_def
, ref generics
) => {
1199 self.head(visibility_qualified(&item
.vis
, "union"));
1200 self.print_struct(struct_def
, generics
, item
.ident
, item
.span
, true);
1202 ast
::ItemKind
::Impl(box ast
::ImplKind
{
1213 self.print_visibility(&item
.vis
);
1214 self.print_defaultness(defaultness
);
1215 self.print_unsafety(unsafety
);
1216 self.word_nbsp("impl");
1217 self.print_constness(constness
);
1219 if !generics
.params
.is_empty() {
1220 self.print_generic_params(&generics
.params
);
1224 if let ast
::ImplPolarity
::Negative(_
) = polarity
{
1228 if let Some(ref t
) = *of_trait
{
1229 self.print_trait_ref(t
);
1231 self.word_space("for");
1234 self.print_type(self_ty
);
1235 self.print_where_clause(&generics
.where_clause
);
1239 self.print_inner_attributes(&item
.attrs
);
1240 for impl_item
in items
{
1241 self.print_assoc_item(impl_item
);
1243 self.bclose(item
.span
);
1245 ast
::ItemKind
::Trait(box ast
::TraitKind(
1253 self.print_visibility(&item
.vis
);
1254 self.print_unsafety(unsafety
);
1255 self.print_is_auto(is_auto
);
1256 self.word_nbsp("trait");
1257 self.print_ident(item
.ident
);
1258 self.print_generic_params(&generics
.params
);
1259 let mut real_bounds
= Vec
::with_capacity(bounds
.len());
1260 for b
in bounds
.iter() {
1261 if let GenericBound
::Trait(ref ptr
, ast
::TraitBoundModifier
::Maybe
) = *b
{
1263 self.word_space("for ?");
1264 self.print_trait_ref(&ptr
.trait_ref
);
1266 real_bounds
.push(b
.clone());
1269 self.print_type_bounds(":", &real_bounds
[..]);
1270 self.print_where_clause(&generics
.where_clause
);
1273 self.print_inner_attributes(&item
.attrs
);
1274 for trait_item
in trait_items
{
1275 self.print_assoc_item(trait_item
);
1277 self.bclose(item
.span
);
1279 ast
::ItemKind
::TraitAlias(ref generics
, ref bounds
) => {
1281 self.print_visibility(&item
.vis
);
1282 self.word_nbsp("trait");
1283 self.print_ident(item
.ident
);
1284 self.print_generic_params(&generics
.params
);
1285 let mut real_bounds
= Vec
::with_capacity(bounds
.len());
1286 // FIXME(durka) this seems to be some quite outdated syntax
1287 for b
in bounds
.iter() {
1288 if let GenericBound
::Trait(ref ptr
, ast
::TraitBoundModifier
::Maybe
) = *b
{
1290 self.word_space("for ?");
1291 self.print_trait_ref(&ptr
.trait_ref
);
1293 real_bounds
.push(b
.clone());
1297 self.print_type_bounds("=", &real_bounds
[..]);
1298 self.print_where_clause(&generics
.where_clause
);
1301 ast
::ItemKind
::MacCall(ref mac
) => {
1302 self.print_mac(mac
);
1303 if mac
.args
.need_semicolon() {
1307 ast
::ItemKind
::MacroDef(ref macro_def
) => {
1308 let (kw
, has_bang
) = if macro_def
.macro_rules
{
1309 ("macro_rules", true)
1311 self.print_visibility(&item
.vis
);
1314 self.print_mac_common(
1315 Some(MacHeader
::Keyword(kw
)),
1318 macro_def
.body
.delim(),
1319 ¯o_def
.body
.inner_tokens(),
1323 if macro_def
.body
.need_semicolon() {
1328 self.ann
.post(self, AnnNode
::Item(item
))
1331 fn print_trait_ref(&mut self, t
: &ast
::TraitRef
) {
1332 self.print_path(&t
.path
, false, 0)
1335 fn print_formal_generic_params(&mut self, generic_params
: &[ast
::GenericParam
]) {
1336 if !generic_params
.is_empty() {
1338 self.print_generic_params(generic_params
);
1343 fn print_poly_trait_ref(&mut self, t
: &ast
::PolyTraitRef
) {
1344 self.print_formal_generic_params(&t
.bound_generic_params
);
1345 self.print_trait_ref(&t
.trait_ref
)
1348 crate fn print_enum_def(
1350 enum_definition
: &ast
::EnumDef
,
1351 generics
: &ast
::Generics
,
1353 span
: rustc_span
::Span
,
1354 visibility
: &ast
::Visibility
,
1356 self.head(visibility_qualified(visibility
, "enum"));
1357 self.print_ident(ident
);
1358 self.print_generic_params(&generics
.params
);
1359 self.print_where_clause(&generics
.where_clause
);
1361 self.print_variants(&enum_definition
.variants
, span
)
1364 crate fn print_variants(&mut self, variants
: &[ast
::Variant
], span
: rustc_span
::Span
) {
1367 self.space_if_not_bol();
1368 self.maybe_print_comment(v
.span
.lo());
1369 self.print_outer_attributes(&v
.attrs
);
1370 self.ibox(INDENT_UNIT
);
1371 self.print_variant(v
);
1374 self.maybe_print_trailing_comment(v
.span
, None
);
1379 crate fn print_visibility(&mut self, vis
: &ast
::Visibility
) {
1381 ast
::VisibilityKind
::Public
=> self.word_nbsp("pub"),
1382 ast
::VisibilityKind
::Crate(sugar
) => match sugar
{
1383 ast
::CrateSugar
::PubCrate
=> self.word_nbsp("pub(crate)"),
1384 ast
::CrateSugar
::JustCrate
=> self.word_nbsp("crate"),
1386 ast
::VisibilityKind
::Restricted { ref path, .. }
=> {
1387 let path
= self.to_string(|s
| s
.print_path(path
, false, 0));
1388 if path
== "self" || path
== "super" {
1389 self.word_nbsp(format
!("pub({})", path
))
1391 self.word_nbsp(format
!("pub(in {})", path
))
1394 ast
::VisibilityKind
::Inherited
=> {}
1398 crate fn print_defaultness(&mut self, defaultness
: ast
::Defaultness
) {
1399 if let ast
::Defaultness
::Default(_
) = defaultness
{
1400 self.word_nbsp("default");
1404 crate fn print_record_struct_body(&mut self, fields
: &[ast
::FieldDef
], span
: rustc_span
::Span
) {
1406 self.hardbreak_if_not_bol();
1408 for field
in fields
{
1409 self.hardbreak_if_not_bol();
1410 self.maybe_print_comment(field
.span
.lo());
1411 self.print_outer_attributes(&field
.attrs
);
1412 self.print_visibility(&field
.vis
);
1413 self.print_ident(field
.ident
.unwrap());
1414 self.word_nbsp(":");
1415 self.print_type(&field
.ty
);
1422 crate fn print_struct(
1424 struct_def
: &ast
::VariantData
,
1425 generics
: &ast
::Generics
,
1427 span
: rustc_span
::Span
,
1428 print_finalizer
: bool
,
1430 self.print_ident(ident
);
1431 self.print_generic_params(&generics
.params
);
1433 ast
::VariantData
::Tuple(..) | ast
::VariantData
::Unit(..) => {
1434 if let ast
::VariantData
::Tuple(..) = struct_def
{
1436 self.commasep(Inconsistent
, struct_def
.fields(), |s
, field
| {
1437 s
.maybe_print_comment(field
.span
.lo());
1438 s
.print_outer_attributes(&field
.attrs
);
1439 s
.print_visibility(&field
.vis
);
1440 s
.print_type(&field
.ty
)
1444 self.print_where_clause(&generics
.where_clause
);
1445 if print_finalizer
{
1449 self.end(); // Close the outer-box.
1451 ast
::VariantData
::Struct(ref fields
, ..) => {
1452 self.print_where_clause(&generics
.where_clause
);
1454 self.print_record_struct_body(fields
, span
);
1459 crate fn print_variant(&mut self, v
: &ast
::Variant
) {
1461 self.print_visibility(&v
.vis
);
1462 let generics
= ast
::Generics
::default();
1463 self.print_struct(&v
.data
, &generics
, v
.ident
, v
.span
, false);
1464 if let Some(ref d
) = v
.disr_expr
{
1466 self.word_space("=");
1467 self.print_expr(&d
.value
)
1471 crate fn print_assoc_item(&mut self, item
: &ast
::AssocItem
) {
1472 let ast
::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ }
= *item
;
1473 self.ann
.pre(self, AnnNode
::SubItem(id
));
1474 self.hardbreak_if_not_bol();
1475 self.maybe_print_comment(span
.lo());
1476 self.print_outer_attributes(attrs
);
1478 ast
::AssocItemKind
::Fn(box ast
::FnKind(def
, sig
, gen
, body
)) => {
1479 self.print_fn_full(sig
, ident
, gen
, vis
, *def
, body
.as_deref(), attrs
);
1481 ast
::AssocItemKind
::Const(def
, ty
, body
) => {
1482 self.print_item_const(ident
, None
, ty
, body
.as_deref(), vis
, *def
);
1484 ast
::AssocItemKind
::TyAlias(box ast
::TyAliasKind(def
, generics
, bounds
, ty
)) => {
1485 self.print_associated_type(ident
, generics
, bounds
, ty
.as_deref(), vis
, *def
);
1487 ast
::AssocItemKind
::MacCall(m
) => {
1489 if m
.args
.need_semicolon() {
1494 self.ann
.post(self, AnnNode
::SubItem(id
))
1497 crate fn print_stmt(&mut self, st
: &ast
::Stmt
) {
1498 self.maybe_print_comment(st
.span
.lo());
1500 ast
::StmtKind
::Local(ref loc
) => {
1501 self.print_outer_attributes(&loc
.attrs
);
1502 self.space_if_not_bol();
1503 self.ibox(INDENT_UNIT
);
1504 self.word_nbsp("let");
1506 self.ibox(INDENT_UNIT
);
1507 self.print_local_decl(loc
);
1509 if let Some(ref init
) = loc
.init
{
1511 self.word_space("=");
1512 self.print_expr(init
);
1517 ast
::StmtKind
::Item(ref item
) => self.print_item(item
),
1518 ast
::StmtKind
::Expr(ref expr
) => {
1519 self.space_if_not_bol();
1520 self.print_expr_outer_attr_style(expr
, false);
1521 if classify
::expr_requires_semi_to_be_stmt(expr
) {
1525 ast
::StmtKind
::Semi(ref expr
) => {
1526 self.space_if_not_bol();
1527 self.print_expr_outer_attr_style(expr
, false);
1530 ast
::StmtKind
::Empty
=> {
1531 self.space_if_not_bol();
1534 ast
::StmtKind
::MacCall(ref mac
) => {
1535 self.space_if_not_bol();
1536 self.print_outer_attributes(&mac
.attrs
);
1537 self.print_mac(&mac
.mac
);
1538 if mac
.style
== ast
::MacStmtStyle
::Semicolon
{
1543 self.maybe_print_trailing_comment(st
.span
, None
)
1546 crate fn print_block(&mut self, blk
: &ast
::Block
) {
1547 self.print_block_with_attrs(blk
, &[])
1550 crate fn print_block_unclosed_indent(&mut self, blk
: &ast
::Block
) {
1551 self.print_block_maybe_unclosed(blk
, &[], false)
1554 crate fn print_block_with_attrs(&mut self, blk
: &ast
::Block
, attrs
: &[ast
::Attribute
]) {
1555 self.print_block_maybe_unclosed(blk
, attrs
, true)
1558 crate fn print_block_maybe_unclosed(
1561 attrs
: &[ast
::Attribute
],
1565 BlockCheckMode
::Unsafe(..) => self.word_space("unsafe"),
1566 BlockCheckMode
::Default
=> (),
1568 self.maybe_print_comment(blk
.span
.lo());
1569 self.ann
.pre(self, AnnNode
::Block(blk
));
1572 self.print_inner_attributes(attrs
);
1574 for (i
, st
) in blk
.stmts
.iter().enumerate() {
1576 ast
::StmtKind
::Expr(ref expr
) if i
== blk
.stmts
.len() - 1 => {
1577 self.maybe_print_comment(st
.span
.lo());
1578 self.space_if_not_bol();
1579 self.print_expr_outer_attr_style(expr
, false);
1580 self.maybe_print_trailing_comment(expr
.span
, Some(blk
.span
.hi()));
1582 _
=> self.print_stmt(st
),
1586 self.bclose_maybe_open(blk
.span
, close_box
);
1587 self.ann
.post(self, AnnNode
::Block(blk
))
1590 /// Print a `let pat = scrutinee` expression.
1591 crate fn print_let(&mut self, pat
: &ast
::Pat
, scrutinee
: &ast
::Expr
) {
1592 self.s
.word("let ");
1594 self.print_pat(pat
);
1597 self.word_space("=");
1598 self.print_expr_cond_paren(
1600 Self::cond_needs_par(scrutinee
)
1601 || parser
::needs_par_as_let_scrutinee(scrutinee
.precedence().order()),
1605 fn print_else(&mut self, els
: Option
<&ast
::Expr
>) {
1606 if let Some(_else
) = els
{
1608 // Another `else if` block.
1609 ast
::ExprKind
::If(ref i
, ref then
, ref e
) => {
1610 self.cbox(INDENT_UNIT
- 1);
1612 self.s
.word(" else if ");
1613 self.print_expr_as_cond(i
);
1615 self.print_block(then
);
1616 self.print_else(e
.as_deref())
1618 // Final `else` block.
1619 ast
::ExprKind
::Block(ref b
, _
) => {
1620 self.cbox(INDENT_UNIT
- 1);
1622 self.s
.word(" else ");
1625 // Constraints would be great here!
1627 panic
!("print_if saw if with weird alternative");
1633 crate fn print_if(&mut self, test
: &ast
::Expr
, blk
: &ast
::Block
, elseopt
: Option
<&ast
::Expr
>) {
1636 self.print_expr_as_cond(test
);
1639 self.print_block(blk
);
1640 self.print_else(elseopt
)
1643 crate fn print_mac(&mut self, m
: &ast
::MacCall
) {
1644 self.print_mac_common(
1645 Some(MacHeader
::Path(&m
.path
)),
1649 &m
.args
.inner_tokens(),
1655 fn print_call_post(&mut self, args
: &[P
<ast
::Expr
>]) {
1657 self.commasep_exprs(Inconsistent
, args
);
1661 crate fn print_expr_maybe_paren(&mut self, expr
: &ast
::Expr
, prec
: i8) {
1662 self.print_expr_cond_paren(expr
, expr
.precedence().order() < prec
)
1665 /// Prints an expr using syntax that's acceptable in a condition position, such as the `cond` in
1666 /// `if cond { ... }`.
1667 crate fn print_expr_as_cond(&mut self, expr
: &ast
::Expr
) {
1668 self.print_expr_cond_paren(expr
, Self::cond_needs_par(expr
))
1671 /// Does `expr` need parenthesis when printed in a condition position?
1672 fn cond_needs_par(expr
: &ast
::Expr
) -> bool
{
1674 // These cases need parens due to the parse error observed in #26461: `if return {}`
1675 // parses as the erroneous construct `if (return {})`, not `if (return) {}`.
1676 ast
::ExprKind
::Closure(..) | ast
::ExprKind
::Ret(..) | ast
::ExprKind
::Break(..) => true,
1678 _
=> parser
::contains_exterior_struct_lit(expr
),
1682 /// Prints `expr` or `(expr)` when `needs_par` holds.
1683 fn print_expr_cond_paren(&mut self, expr
: &ast
::Expr
, needs_par
: bool
) {
1687 self.print_expr(expr
);
1693 fn print_expr_vec(&mut self, exprs
: &[P
<ast
::Expr
>]) {
1694 self.ibox(INDENT_UNIT
);
1696 self.commasep_exprs(Inconsistent
, exprs
);
1701 fn print_expr_anon_const(&mut self, expr
: &ast
::AnonConst
) {
1702 self.ibox(INDENT_UNIT
);
1703 self.s
.word("const");
1704 self.print_expr(&expr
.value
);
1708 fn print_expr_repeat(&mut self, element
: &ast
::Expr
, count
: &ast
::AnonConst
) {
1709 self.ibox(INDENT_UNIT
);
1711 self.print_expr(element
);
1712 self.word_space(";");
1713 self.print_expr(&count
.value
);
1718 fn print_expr_struct(
1720 qself
: &Option
<ast
::QSelf
>,
1722 fields
: &[ast
::ExprField
],
1723 rest
: &ast
::StructRest
,
1725 if let Some(qself
) = qself
{
1726 self.print_qpath(path
, qself
, true);
1728 self.print_path(path
, true, 0);
1735 s
.print_outer_attributes(&field
.attrs
);
1736 s
.ibox(INDENT_UNIT
);
1737 if !field
.is_shorthand
{
1738 s
.print_ident(field
.ident
);
1741 s
.print_expr(&field
.expr
);
1747 ast
::StructRest
::Base(_
) | ast
::StructRest
::Rest(_
) => {
1748 self.ibox(INDENT_UNIT
);
1749 if !fields
.is_empty() {
1754 if let ast
::StructRest
::Base(ref expr
) = *rest
{
1755 self.print_expr(expr
);
1759 ast
::StructRest
::None
if !fields
.is_empty() => self.s
.word(","),
1765 fn print_expr_tup(&mut self, exprs
: &[P
<ast
::Expr
>]) {
1767 self.commasep_exprs(Inconsistent
, exprs
);
1768 if exprs
.len() == 1 {
1774 fn print_expr_call(&mut self, func
: &ast
::Expr
, args
: &[P
<ast
::Expr
>]) {
1775 let prec
= match func
.kind
{
1776 ast
::ExprKind
::Field(..) => parser
::PREC_FORCE_PAREN
,
1777 _
=> parser
::PREC_POSTFIX
,
1780 self.print_expr_maybe_paren(func
, prec
);
1781 self.print_call_post(args
)
1784 fn print_expr_method_call(&mut self, segment
: &ast
::PathSegment
, args
: &[P
<ast
::Expr
>]) {
1785 let base_args
= &args
[1..];
1786 self.print_expr_maybe_paren(&args
[0], parser
::PREC_POSTFIX
);
1788 self.print_ident(segment
.ident
);
1789 if let Some(ref args
) = segment
.args
{
1790 self.print_generic_args(args
, true);
1792 self.print_call_post(base_args
)
1795 fn print_expr_binary(&mut self, op
: ast
::BinOp
, lhs
: &ast
::Expr
, rhs
: &ast
::Expr
) {
1796 let assoc_op
= AssocOp
::from_ast_binop(op
.node
);
1797 let prec
= assoc_op
.precedence() as i8;
1798 let fixity
= assoc_op
.fixity();
1800 let (left_prec
, right_prec
) = match fixity
{
1801 Fixity
::Left
=> (prec
, prec
+ 1),
1802 Fixity
::Right
=> (prec
+ 1, prec
),
1803 Fixity
::None
=> (prec
+ 1, prec
+ 1),
1806 let left_prec
= match (&lhs
.kind
, op
.node
) {
1807 // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
1808 // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
1809 // of `(x as i32) < ...`. We need to convince it _not_ to do that.
1810 (&ast
::ExprKind
::Cast { .. }
, ast
::BinOpKind
::Lt
| ast
::BinOpKind
::Shl
) => {
1811 parser
::PREC_FORCE_PAREN
1813 // We are given `(let _ = a) OP b`.
1815 // - When `OP <= LAnd` we should print `let _ = a OP b` to avoid redundant parens
1816 // as the parser will interpret this as `(let _ = a) OP b`.
1818 // - Otherwise, e.g. when we have `(let a = b) < c` in AST,
1819 // parens are required since the parser would interpret `let a = b < c` as
1820 // `let a = (b < c)`. To achieve this, we force parens.
1821 (&ast
::ExprKind
::Let { .. }
, _
) if !parser
::needs_par_as_let_scrutinee(prec
) => {
1822 parser
::PREC_FORCE_PAREN
1827 self.print_expr_maybe_paren(lhs
, left_prec
);
1829 self.word_space(op
.node
.to_string());
1830 self.print_expr_maybe_paren(rhs
, right_prec
)
1833 fn print_expr_unary(&mut self, op
: ast
::UnOp
, expr
: &ast
::Expr
) {
1834 self.s
.word(ast
::UnOp
::to_string(op
));
1835 self.print_expr_maybe_paren(expr
, parser
::PREC_PREFIX
)
1838 fn print_expr_addr_of(
1840 kind
: ast
::BorrowKind
,
1841 mutability
: ast
::Mutability
,
1846 ast
::BorrowKind
::Ref
=> self.print_mutability(mutability
, false),
1847 ast
::BorrowKind
::Raw
=> {
1848 self.word_nbsp("raw");
1849 self.print_mutability(mutability
, true);
1852 self.print_expr_maybe_paren(expr
, parser
::PREC_PREFIX
)
1855 pub fn print_expr(&mut self, expr
: &ast
::Expr
) {
1856 self.print_expr_outer_attr_style(expr
, true)
1859 fn print_expr_outer_attr_style(&mut self, expr
: &ast
::Expr
, is_inline
: bool
) {
1860 self.maybe_print_comment(expr
.span
.lo());
1862 let attrs
= &expr
.attrs
;
1864 self.print_outer_attributes_inline(attrs
);
1866 self.print_outer_attributes(attrs
);
1869 self.ibox(INDENT_UNIT
);
1870 self.ann
.pre(self, AnnNode
::Expr(expr
));
1872 ast
::ExprKind
::Box(ref expr
) => {
1873 self.word_space("box");
1874 self.print_expr_maybe_paren(expr
, parser
::PREC_PREFIX
);
1876 ast
::ExprKind
::Array(ref exprs
) => {
1877 self.print_expr_vec(exprs
);
1879 ast
::ExprKind
::ConstBlock(ref anon_const
) => {
1880 self.print_expr_anon_const(anon_const
);
1882 ast
::ExprKind
::Repeat(ref element
, ref count
) => {
1883 self.print_expr_repeat(element
, count
);
1885 ast
::ExprKind
::Struct(ref se
) => {
1886 self.print_expr_struct(&se
.qself
, &se
.path
, &se
.fields
, &se
.rest
);
1888 ast
::ExprKind
::Tup(ref exprs
) => {
1889 self.print_expr_tup(exprs
);
1891 ast
::ExprKind
::Call(ref func
, ref args
) => {
1892 self.print_expr_call(func
, &args
[..]);
1894 ast
::ExprKind
::MethodCall(ref segment
, ref args
, _
) => {
1895 self.print_expr_method_call(segment
, &args
[..]);
1897 ast
::ExprKind
::Binary(op
, ref lhs
, ref rhs
) => {
1898 self.print_expr_binary(op
, lhs
, rhs
);
1900 ast
::ExprKind
::Unary(op
, ref expr
) => {
1901 self.print_expr_unary(op
, expr
);
1903 ast
::ExprKind
::AddrOf(k
, m
, ref expr
) => {
1904 self.print_expr_addr_of(k
, m
, expr
);
1906 ast
::ExprKind
::Lit(ref lit
) => {
1907 self.print_literal(lit
);
1909 ast
::ExprKind
::Cast(ref expr
, ref ty
) => {
1910 let prec
= AssocOp
::As
.precedence() as i8;
1911 self.print_expr_maybe_paren(expr
, prec
);
1913 self.word_space("as");
1914 self.print_type(ty
);
1916 ast
::ExprKind
::Type(ref expr
, ref ty
) => {
1917 let prec
= AssocOp
::Colon
.precedence() as i8;
1918 self.print_expr_maybe_paren(expr
, prec
);
1919 self.word_space(":");
1920 self.print_type(ty
);
1922 ast
::ExprKind
::Let(ref pat
, ref scrutinee
) => {
1923 self.print_let(pat
, scrutinee
);
1925 ast
::ExprKind
::If(ref test
, ref blk
, ref elseopt
) => {
1926 self.print_if(test
, blk
, elseopt
.as_deref())
1928 ast
::ExprKind
::While(ref test
, ref blk
, opt_label
) => {
1929 if let Some(label
) = opt_label
{
1930 self.print_ident(label
.ident
);
1931 self.word_space(":");
1934 self.print_expr_as_cond(test
);
1936 self.print_block_with_attrs(blk
, attrs
);
1938 ast
::ExprKind
::ForLoop(ref pat
, ref iter
, ref blk
, opt_label
) => {
1939 if let Some(label
) = opt_label
{
1940 self.print_ident(label
.ident
);
1941 self.word_space(":");
1944 self.print_pat(pat
);
1946 self.word_space("in");
1947 self.print_expr_as_cond(iter
);
1949 self.print_block_with_attrs(blk
, attrs
);
1951 ast
::ExprKind
::Loop(ref blk
, opt_label
) => {
1952 if let Some(label
) = opt_label
{
1953 self.print_ident(label
.ident
);
1954 self.word_space(":");
1957 self.print_block_with_attrs(blk
, attrs
);
1959 ast
::ExprKind
::Match(ref expr
, ref arms
) => {
1960 self.cbox(INDENT_UNIT
);
1961 self.ibox(INDENT_UNIT
);
1962 self.word_nbsp("match");
1963 self.print_expr_as_cond(expr
);
1966 self.print_inner_attributes_no_trailing_hardbreak(attrs
);
1968 self.print_arm(arm
);
1970 self.bclose(expr
.span
);
1972 ast
::ExprKind
::Closure(
1980 self.print_movability(movability
);
1981 self.print_asyncness(asyncness
);
1982 self.print_capture_clause(capture_clause
);
1984 self.print_fn_params_and_ret(decl
, true);
1986 self.print_expr(body
);
1987 self.end(); // need to close a box
1989 // a box will be closed by print_expr, but we didn't want an overall
1990 // wrapper so we closed the corresponding opening. so create an
1991 // empty box to satisfy the close.
1994 ast
::ExprKind
::Block(ref blk
, opt_label
) => {
1995 if let Some(label
) = opt_label
{
1996 self.print_ident(label
.ident
);
1997 self.word_space(":");
1999 // containing cbox, will be closed by print-block at }
2000 self.cbox(INDENT_UNIT
);
2001 // head-box, will be closed by print-block after {
2003 self.print_block_with_attrs(blk
, attrs
);
2005 ast
::ExprKind
::Async(capture_clause
, _
, ref blk
) => {
2006 self.word_nbsp("async");
2007 self.print_capture_clause(capture_clause
);
2009 // cbox/ibox in analogy to the `ExprKind::Block` arm above
2010 self.cbox(INDENT_UNIT
);
2012 self.print_block_with_attrs(blk
, attrs
);
2014 ast
::ExprKind
::Await(ref expr
) => {
2015 self.print_expr_maybe_paren(expr
, parser
::PREC_POSTFIX
);
2016 self.s
.word(".await");
2018 ast
::ExprKind
::Assign(ref lhs
, ref rhs
, _
) => {
2019 let prec
= AssocOp
::Assign
.precedence() as i8;
2020 self.print_expr_maybe_paren(lhs
, prec
+ 1);
2022 self.word_space("=");
2023 self.print_expr_maybe_paren(rhs
, prec
);
2025 ast
::ExprKind
::AssignOp(op
, ref lhs
, ref rhs
) => {
2026 let prec
= AssocOp
::Assign
.precedence() as i8;
2027 self.print_expr_maybe_paren(lhs
, prec
+ 1);
2029 self.s
.word(op
.node
.to_string());
2030 self.word_space("=");
2031 self.print_expr_maybe_paren(rhs
, prec
);
2033 ast
::ExprKind
::Field(ref expr
, ident
) => {
2034 self.print_expr_maybe_paren(expr
, parser
::PREC_POSTFIX
);
2036 self.print_ident(ident
);
2038 ast
::ExprKind
::Index(ref expr
, ref index
) => {
2039 self.print_expr_maybe_paren(expr
, parser
::PREC_POSTFIX
);
2041 self.print_expr(index
);
2044 ast
::ExprKind
::Range(ref start
, ref end
, limits
) => {
2045 // Special case for `Range`. `AssocOp` claims that `Range` has higher precedence
2046 // than `Assign`, but `x .. x = x` gives a parse error instead of `x .. (x = x)`.
2047 // Here we use a fake precedence value so that any child with lower precedence than
2048 // a "normal" binop gets parenthesized. (`LOr` is the lowest-precedence binop.)
2049 let fake_prec
= AssocOp
::LOr
.precedence() as i8;
2050 if let Some(ref e
) = *start
{
2051 self.print_expr_maybe_paren(e
, fake_prec
);
2053 if limits
== ast
::RangeLimits
::HalfOpen
{
2058 if let Some(ref e
) = *end
{
2059 self.print_expr_maybe_paren(e
, fake_prec
);
2062 ast
::ExprKind
::Underscore
=> self.s
.word("_"),
2063 ast
::ExprKind
::Path(None
, ref path
) => self.print_path(path
, true, 0),
2064 ast
::ExprKind
::Path(Some(ref qself
), ref path
) => self.print_qpath(path
, qself
, true),
2065 ast
::ExprKind
::Break(opt_label
, ref opt_expr
) => {
2066 self.s
.word("break");
2068 if let Some(label
) = opt_label
{
2069 self.print_ident(label
.ident
);
2072 if let Some(ref expr
) = *opt_expr
{
2073 self.print_expr_maybe_paren(expr
, parser
::PREC_JUMP
);
2077 ast
::ExprKind
::Continue(opt_label
) => {
2078 self.s
.word("continue");
2080 if let Some(label
) = opt_label
{
2081 self.print_ident(label
.ident
);
2085 ast
::ExprKind
::Ret(ref result
) => {
2086 self.s
.word("return");
2087 if let Some(ref expr
) = *result
{
2089 self.print_expr_maybe_paren(expr
, parser
::PREC_JUMP
);
2092 ast
::ExprKind
::InlineAsm(ref a
) => {
2094 self.print_inline_asm(a
);
2096 ast
::ExprKind
::LlvmInlineAsm(ref a
) => {
2097 self.s
.word("llvm_asm!");
2099 self.print_symbol(a
.asm
, a
.asm_str_style
);
2100 self.word_space(":");
2102 self.commasep(Inconsistent
, &a
.outputs
, |s
, out
| {
2103 let constraint
= out
.constraint
.as_str();
2104 let mut ch
= constraint
.chars();
2106 Some('
='
) if out
.is_rw
=> {
2107 s
.print_string(&format
!("+{}", ch
.as_str()), ast
::StrStyle
::Cooked
)
2109 _
=> s
.print_string(&constraint
, ast
::StrStyle
::Cooked
),
2112 s
.print_expr(&out
.expr
);
2116 self.word_space(":");
2118 self.commasep(Inconsistent
, &a
.inputs
, |s
, &(co
, ref o
)| {
2119 s
.print_symbol(co
, ast
::StrStyle
::Cooked
);
2125 self.word_space(":");
2127 self.commasep(Inconsistent
, &a
.clobbers
, |s
, &co
| {
2128 s
.print_symbol(co
, ast
::StrStyle
::Cooked
);
2131 let mut options
= vec
![];
2133 options
.push("volatile");
2136 options
.push("alignstack");
2138 if a
.dialect
== ast
::LlvmAsmDialect
::Intel
{
2139 options
.push("intel");
2142 if !options
.is_empty() {
2144 self.word_space(":");
2145 self.commasep(Inconsistent
, &options
, |s
, &co
| {
2146 s
.print_string(co
, ast
::StrStyle
::Cooked
);
2152 ast
::ExprKind
::MacCall(ref m
) => self.print_mac(m
),
2153 ast
::ExprKind
::Paren(ref e
) => {
2158 ast
::ExprKind
::Yield(ref e
) => {
2159 self.s
.word("yield");
2161 if let Some(ref expr
) = *e
{
2163 self.print_expr_maybe_paren(expr
, parser
::PREC_JUMP
);
2166 ast
::ExprKind
::Try(ref e
) => {
2167 self.print_expr_maybe_paren(e
, parser
::PREC_POSTFIX
);
2170 ast
::ExprKind
::TryBlock(ref blk
) => {
2173 self.print_block_with_attrs(blk
, attrs
)
2175 ast
::ExprKind
::Err
=> {
2177 self.s
.word("/*ERROR*/");
2181 self.ann
.post(self, AnnNode
::Expr(expr
));
2185 fn print_inline_asm(&mut self, asm
: &ast
::InlineAsm
) {
2188 Operand(&'a InlineAsmOperand
),
2189 Options(InlineAsmOptions
),
2192 let mut args
= vec
![];
2193 args
.push(AsmArg
::Template(InlineAsmTemplatePiece
::to_string(&asm
.template
)));
2194 args
.extend(asm
.operands
.iter().map(|(o
, _
)| AsmArg
::Operand(o
)));
2195 if !asm
.options
.is_empty() {
2196 args
.push(AsmArg
::Options(asm
.options
));
2200 self.commasep(Consistent
, &args
, |s
, arg
| match arg
{
2201 AsmArg
::Template(template
) => s
.print_string(&template
, ast
::StrStyle
::Cooked
),
2202 AsmArg
::Operand(op
) => {
2203 let print_reg_or_class
= |s
: &mut Self, r
: &InlineAsmRegOrRegClass
| match r
{
2204 InlineAsmRegOrRegClass
::Reg(r
) => s
.print_symbol(*r
, ast
::StrStyle
::Cooked
),
2205 InlineAsmRegOrRegClass
::RegClass(r
) => s
.word(r
.to_string()),
2208 InlineAsmOperand
::In { reg, expr }
=> {
2211 print_reg_or_class(s
, reg
);
2216 InlineAsmOperand
::Out { reg, late, expr }
=> {
2217 s
.word(if *late { "lateout" }
else { "out" }
);
2219 print_reg_or_class(s
, reg
);
2223 Some(expr
) => s
.print_expr(expr
),
2224 None
=> s
.word("_"),
2227 InlineAsmOperand
::InOut { reg, late, expr }
=> {
2228 s
.word(if *late { "inlateout" }
else { "inout" }
);
2230 print_reg_or_class(s
, reg
);
2235 InlineAsmOperand
::SplitInOut { reg, late, in_expr, out_expr }
=> {
2236 s
.word(if *late { "inlateout" }
else { "inout" }
);
2238 print_reg_or_class(s
, reg
);
2241 s
.print_expr(in_expr
);
2245 Some(out_expr
) => s
.print_expr(out_expr
),
2246 None
=> s
.word("_"),
2249 InlineAsmOperand
::Const { anon_const }
=> {
2252 s
.print_expr(&anon_const
.value
);
2254 InlineAsmOperand
::Sym { expr }
=> {
2261 AsmArg
::Options(opts
) => {
2264 let mut options
= vec
![];
2265 if opts
.contains(InlineAsmOptions
::PURE
) {
2266 options
.push("pure");
2268 if opts
.contains(InlineAsmOptions
::NOMEM
) {
2269 options
.push("nomem");
2271 if opts
.contains(InlineAsmOptions
::READONLY
) {
2272 options
.push("readonly");
2274 if opts
.contains(InlineAsmOptions
::PRESERVES_FLAGS
) {
2275 options
.push("preserves_flags");
2277 if opts
.contains(InlineAsmOptions
::NORETURN
) {
2278 options
.push("noreturn");
2280 if opts
.contains(InlineAsmOptions
::NOSTACK
) {
2281 options
.push("nostack");
2283 if opts
.contains(InlineAsmOptions
::ATT_SYNTAX
) {
2284 options
.push("att_syntax");
2286 if opts
.contains(InlineAsmOptions
::RAW
) {
2287 options
.push("raw");
2289 s
.commasep(Inconsistent
, &options
, |s
, &opt
| {
2298 crate fn print_local_decl(&mut self, loc
: &ast
::Local
) {
2299 self.print_pat(&loc
.pat
);
2300 if let Some(ref ty
) = loc
.ty
{
2301 self.word_space(":");
2302 self.print_type(ty
);
2306 crate fn print_name(&mut self, name
: Symbol
) {
2307 self.s
.word(name
.to_string());
2308 self.ann
.post(self, AnnNode
::Name(&name
))
2311 fn print_qpath(&mut self, path
: &ast
::Path
, qself
: &ast
::QSelf
, colons_before_params
: bool
) {
2313 self.print_type(&qself
.ty
);
2314 if qself
.position
> 0 {
2316 self.word_space("as");
2317 let depth
= path
.segments
.len() - qself
.position
;
2318 self.print_path(path
, false, depth
);
2321 for item_segment
in &path
.segments
[qself
.position
..] {
2323 self.print_ident(item_segment
.ident
);
2324 if let Some(ref args
) = item_segment
.args
{
2325 self.print_generic_args(args
, colons_before_params
)
2330 crate fn print_pat(&mut self, pat
: &ast
::Pat
) {
2331 self.maybe_print_comment(pat
.span
.lo());
2332 self.ann
.pre(self, AnnNode
::Pat(pat
));
2333 /* Pat isn't normalized, but the beauty of it
2334 is that it doesn't matter */
2336 PatKind
::Wild
=> self.s
.word("_"),
2337 PatKind
::Ident(binding_mode
, ident
, ref sub
) => {
2338 match binding_mode
{
2339 ast
::BindingMode
::ByRef(mutbl
) => {
2340 self.word_nbsp("ref");
2341 self.print_mutability(mutbl
, false);
2343 ast
::BindingMode
::ByValue(ast
::Mutability
::Not
) => {}
2344 ast
::BindingMode
::ByValue(ast
::Mutability
::Mut
) => {
2345 self.word_nbsp("mut");
2348 self.print_ident(ident
);
2349 if let Some(ref p
) = *sub
{
2351 self.s
.word_space("@");
2355 PatKind
::TupleStruct(ref qself
, ref path
, ref elts
) => {
2356 if let Some(qself
) = qself
{
2357 self.print_qpath(path
, qself
, true);
2359 self.print_path(path
, true, 0);
2362 self.commasep(Inconsistent
, &elts
[..], |s
, p
| s
.print_pat(p
));
2365 PatKind
::Or(ref pats
) => {
2366 self.strsep("|", true, Inconsistent
, &pats
[..], |s
, p
| s
.print_pat(p
));
2368 PatKind
::Path(None
, ref path
) => {
2369 self.print_path(path
, true, 0);
2371 PatKind
::Path(Some(ref qself
), ref path
) => {
2372 self.print_qpath(path
, qself
, false);
2374 PatKind
::Struct(ref qself
, ref path
, ref fields
, etc
) => {
2375 if let Some(qself
) = qself
{
2376 self.print_qpath(path
, qself
, true);
2378 self.print_path(path
, true, 0);
2381 self.word_space("{");
2386 s
.cbox(INDENT_UNIT
);
2387 if !f
.is_shorthand
{
2388 s
.print_ident(f
.ident
);
2391 s
.print_pat(&f
.pat
);
2397 if !fields
.is_empty() {
2398 self.word_space(",");
2405 PatKind
::Tuple(ref elts
) => {
2407 self.commasep(Inconsistent
, &elts
[..], |s
, p
| s
.print_pat(p
));
2408 if elts
.len() == 1 {
2413 PatKind
::Box(ref inner
) => {
2414 self.s
.word("box ");
2415 self.print_pat(inner
);
2417 PatKind
::Ref(ref inner
, mutbl
) => {
2419 if mutbl
== ast
::Mutability
::Mut
{
2420 self.s
.word("mut ");
2422 if let PatKind
::Ident(ast
::BindingMode
::ByValue(ast
::Mutability
::Mut
), ..) =
2426 self.print_pat(inner
);
2429 self.print_pat(inner
);
2432 PatKind
::Lit(ref e
) => self.print_expr(&**e
),
2433 PatKind
::Range(ref begin
, ref end
, Spanned { node: ref end_kind, .. }
) => {
2434 if let Some(e
) = begin
{
2439 RangeEnd
::Included(RangeSyntax
::DotDotDot
) => self.s
.word("..."),
2440 RangeEnd
::Included(RangeSyntax
::DotDotEq
) => self.s
.word("..="),
2441 RangeEnd
::Excluded
=> self.s
.word(".."),
2443 if let Some(e
) = end
{
2447 PatKind
::Slice(ref elts
) => {
2449 self.commasep(Inconsistent
, &elts
[..], |s
, p
| s
.print_pat(p
));
2452 PatKind
::Rest
=> self.s
.word(".."),
2453 PatKind
::Paren(ref inner
) => {
2455 self.print_pat(inner
);
2458 PatKind
::MacCall(ref m
) => self.print_mac(m
),
2460 self.ann
.post(self, AnnNode
::Pat(pat
))
2463 fn print_arm(&mut self, arm
: &ast
::Arm
) {
2464 // Note, I have no idea why this check is necessary, but here it is.
2465 if arm
.attrs
.is_empty() {
2468 self.cbox(INDENT_UNIT
);
2470 self.maybe_print_comment(arm
.pat
.span
.lo());
2471 self.print_outer_attributes(&arm
.attrs
);
2472 self.print_pat(&arm
.pat
);
2474 if let Some(ref e
) = arm
.guard
{
2475 self.word_space("if");
2479 self.word_space("=>");
2481 match arm
.body
.kind
{
2482 ast
::ExprKind
::Block(ref blk
, opt_label
) => {
2483 if let Some(label
) = opt_label
{
2484 self.print_ident(label
.ident
);
2485 self.word_space(":");
2488 // The block will close the pattern's ibox.
2489 self.print_block_unclosed_indent(blk
);
2491 // If it is a user-provided unsafe block, print a comma after it.
2492 if let BlockCheckMode
::Unsafe(ast
::UserProvided
) = blk
.rules
{
2497 self.end(); // Close the ibox for the pattern.
2498 self.print_expr(&arm
.body
);
2502 self.end(); // Close enclosing cbox.
2505 fn print_explicit_self(&mut self, explicit_self
: &ast
::ExplicitSelf
) {
2506 match explicit_self
.node
{
2507 SelfKind
::Value(m
) => {
2508 self.print_mutability(m
, false);
2511 SelfKind
::Region(ref lt
, m
) => {
2513 self.print_opt_lifetime(lt
);
2514 self.print_mutability(m
, false);
2517 SelfKind
::Explicit(ref typ
, m
) => {
2518 self.print_mutability(m
, false);
2519 self.s
.word("self");
2520 self.word_space(":");
2521 self.print_type(typ
)
2530 generics
: &ast
::Generics
,
2531 vis
: &ast
::Visibility
,
2532 defaultness
: ast
::Defaultness
,
2533 body
: Option
<&ast
::Block
>,
2534 attrs
: &[ast
::Attribute
],
2539 self.print_visibility(vis
);
2540 self.print_defaultness(defaultness
);
2541 self.print_fn(&sig
.decl
, sig
.header
, Some(name
), generics
);
2542 if let Some(body
) = body
{
2544 self.print_block_with_attrs(body
, attrs
);
2553 header
: ast
::FnHeader
,
2554 name
: Option
<Ident
>,
2555 generics
: &ast
::Generics
,
2557 self.print_fn_header_info(header
);
2558 if let Some(name
) = name
{
2560 self.print_ident(name
);
2562 self.print_generic_params(&generics
.params
);
2563 self.print_fn_params_and_ret(decl
, false);
2564 self.print_where_clause(&generics
.where_clause
)
2567 crate fn print_fn_params_and_ret(&mut self, decl
: &ast
::FnDecl
, is_closure
: bool
) {
2568 let (open
, close
) = if is_closure { ("|", "|") }
else { ("(", ")") }
;
2570 self.commasep(Inconsistent
, &decl
.inputs
, |s
, param
| s
.print_param(param
, is_closure
));
2572 self.print_fn_ret_ty(&decl
.output
)
2575 crate fn print_movability(&mut self, movability
: ast
::Movability
) {
2577 ast
::Movability
::Static
=> self.word_space("static"),
2578 ast
::Movability
::Movable
=> {}
2582 crate fn print_asyncness(&mut self, asyncness
: ast
::Async
) {
2583 if asyncness
.is_async() {
2584 self.word_nbsp("async");
2588 crate fn print_capture_clause(&mut self, capture_clause
: ast
::CaptureBy
) {
2589 match capture_clause
{
2590 ast
::CaptureBy
::Value
=> self.word_space("move"),
2591 ast
::CaptureBy
::Ref
=> {}
2595 pub fn print_type_bounds(&mut self, prefix
: &'
static str, bounds
: &[ast
::GenericBound
]) {
2596 if !bounds
.is_empty() {
2597 self.s
.word(prefix
);
2598 let mut first
= true;
2599 for bound
in bounds
{
2600 if !(first
&& prefix
.is_empty()) {
2606 self.word_space("+");
2610 GenericBound
::Trait(tref
, modifier
) => {
2611 if modifier
== &TraitBoundModifier
::Maybe
{
2614 self.print_poly_trait_ref(tref
);
2616 GenericBound
::Outlives(lt
) => self.print_lifetime(*lt
),
2622 crate fn print_lifetime(&mut self, lifetime
: ast
::Lifetime
) {
2623 self.print_name(lifetime
.ident
.name
)
2626 crate fn print_lifetime_bounds(
2628 lifetime
: ast
::Lifetime
,
2629 bounds
: &ast
::GenericBounds
,
2631 self.print_lifetime(lifetime
);
2632 if !bounds
.is_empty() {
2634 for (i
, bound
) in bounds
.iter().enumerate() {
2639 ast
::GenericBound
::Outlives(lt
) => self.print_lifetime(*lt
),
2646 crate fn print_generic_params(&mut self, generic_params
: &[ast
::GenericParam
]) {
2647 if generic_params
.is_empty() {
2653 self.commasep(Inconsistent
, &generic_params
, |s
, param
| {
2654 s
.print_outer_attributes_inline(¶m
.attrs
);
2657 ast
::GenericParamKind
::Lifetime
=> {
2658 let lt
= ast
::Lifetime { id: param.id, ident: param.ident }
;
2659 s
.print_lifetime_bounds(lt
, ¶m
.bounds
)
2661 ast
::GenericParamKind
::Type { ref default }
=> {
2662 s
.print_ident(param
.ident
);
2663 s
.print_type_bounds(":", ¶m
.bounds
);
2664 if let Some(ref default) = default {
2667 s
.print_type(default)
2670 ast
::GenericParamKind
::Const { ref ty, kw_span: _, ref default }
=> {
2671 s
.word_space("const");
2672 s
.print_ident(param
.ident
);
2676 s
.print_type_bounds(":", ¶m
.bounds
);
2677 if let Some(ref default) = default {
2680 s
.print_expr(&default.value
);
2689 crate fn print_where_clause(&mut self, where_clause
: &ast
::WhereClause
) {
2690 if where_clause
.predicates
.is_empty() && !where_clause
.has_where_token
{
2695 self.word_space("where");
2697 for (i
, predicate
) in where_clause
.predicates
.iter().enumerate() {
2699 self.word_space(",");
2703 ast
::WherePredicate
::BoundPredicate(ast
::WhereBoundPredicate
{
2704 ref bound_generic_params
,
2709 self.print_formal_generic_params(bound_generic_params
);
2710 self.print_type(bounded_ty
);
2711 self.print_type_bounds(":", bounds
);
2713 ast
::WherePredicate
::RegionPredicate(ast
::WhereRegionPredicate
{
2718 self.print_lifetime_bounds(*lifetime
, bounds
);
2720 ast
::WherePredicate
::EqPredicate(ast
::WhereEqPredicate
{
2725 self.print_type(lhs_ty
);
2727 self.word_space("=");
2728 self.print_type(rhs_ty
);
2734 crate fn print_use_tree(&mut self, tree
: &ast
::UseTree
) {
2736 ast
::UseTreeKind
::Simple(rename
, ..) => {
2737 self.print_path(&tree
.prefix
, false, 0);
2738 if let Some(rename
) = rename
{
2740 self.word_space("as");
2741 self.print_ident(rename
);
2744 ast
::UseTreeKind
::Glob
=> {
2745 if !tree
.prefix
.segments
.is_empty() {
2746 self.print_path(&tree
.prefix
, false, 0);
2751 ast
::UseTreeKind
::Nested(ref items
) => {
2752 if tree
.prefix
.segments
.is_empty() {
2755 self.print_path(&tree
.prefix
, false, 0);
2758 self.commasep(Inconsistent
, &items
[..], |this
, &(ref tree
, _
)| {
2759 this
.print_use_tree(tree
)
2766 pub fn print_mutability(&mut self, mutbl
: ast
::Mutability
, print_const
: bool
) {
2768 ast
::Mutability
::Mut
=> self.word_nbsp("mut"),
2769 ast
::Mutability
::Not
=> {
2771 self.word_nbsp("const");
2777 crate fn print_mt(&mut self, mt
: &ast
::MutTy
, print_const
: bool
) {
2778 self.print_mutability(mt
.mutbl
, print_const
);
2779 self.print_type(&mt
.ty
)
2782 crate fn print_param(&mut self, input
: &ast
::Param
, is_closure
: bool
) {
2783 self.ibox(INDENT_UNIT
);
2785 self.print_outer_attributes_inline(&input
.attrs
);
2787 match input
.ty
.kind
{
2788 ast
::TyKind
::Infer
if is_closure
=> self.print_pat(&input
.pat
),
2790 if let Some(eself
) = input
.to_self() {
2791 self.print_explicit_self(&eself
);
2793 let invalid
= if let PatKind
::Ident(_
, ident
, _
) = input
.pat
.kind
{
2794 ident
.name
== kw
::Empty
2799 self.print_pat(&input
.pat
);
2803 self.print_type(&input
.ty
);
2810 crate fn print_fn_ret_ty(&mut self, fn_ret_ty
: &ast
::FnRetTy
) {
2811 if let ast
::FnRetTy
::Ty(ty
) = fn_ret_ty
{
2812 self.space_if_not_bol();
2813 self.ibox(INDENT_UNIT
);
2814 self.word_space("->");
2815 self.print_type(ty
);
2817 self.maybe_print_comment(ty
.span
.lo());
2821 crate fn print_ty_fn(
2824 unsafety
: ast
::Unsafe
,
2826 name
: Option
<Ident
>,
2827 generic_params
: &[ast
::GenericParam
],
2829 self.ibox(INDENT_UNIT
);
2830 if !generic_params
.is_empty() {
2832 self.print_generic_params(generic_params
);
2834 let generics
= ast
::Generics
{
2836 where_clause
: ast
::WhereClause
{
2837 has_where_token
: false,
2838 predicates
: Vec
::new(),
2839 span
: rustc_span
::DUMMY_SP
,
2841 span
: rustc_span
::DUMMY_SP
,
2843 let header
= ast
::FnHeader { unsafety, ext, ..ast::FnHeader::default() }
;
2844 self.print_fn(decl
, header
, name
, &generics
);
2848 crate fn maybe_print_trailing_comment(
2850 span
: rustc_span
::Span
,
2851 next_pos
: Option
<BytePos
>,
2853 if let Some(cmnts
) = self.comments() {
2854 if let Some(cmnt
) = cmnts
.trailing_comment(span
, next_pos
) {
2855 self.print_comment(&cmnt
);
2860 crate fn print_remaining_comments(&mut self) {
2861 // If there aren't any remaining comments, then we need to manually
2862 // make sure there is a line break at the end.
2863 if self.next_comment().is_none() {
2866 while let Some(ref cmnt
) = self.next_comment() {
2867 self.print_comment(cmnt
);
2871 crate fn print_fn_header_info(&mut self, header
: ast
::FnHeader
) {
2872 self.print_constness(header
.constness
);
2873 self.print_asyncness(header
.asyncness
);
2874 self.print_unsafety(header
.unsafety
);
2877 ast
::Extern
::None
=> {}
2878 ast
::Extern
::Implicit
=> {
2879 self.word_nbsp("extern");
2881 ast
::Extern
::Explicit(abi
) => {
2882 self.word_nbsp("extern");
2883 self.print_literal(&abi
.as_lit());
2891 crate fn print_unsafety(&mut self, s
: ast
::Unsafe
) {
2893 ast
::Unsafe
::No
=> {}
2894 ast
::Unsafe
::Yes(_
) => self.word_nbsp("unsafe"),
2898 crate fn print_constness(&mut self, s
: ast
::Const
) {
2900 ast
::Const
::No
=> {}
2901 ast
::Const
::Yes(_
) => self.word_nbsp("const"),
2905 crate fn print_is_auto(&mut self, s
: ast
::IsAuto
) {
2907 ast
::IsAuto
::Yes
=> self.word_nbsp("auto"),
2908 ast
::IsAuto
::No
=> {}