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 let token
::DocComment(comment_kind
, ..) = token
.kind
{
144 return comment_kind
!= CommentKind
::Line
;
148 TokenTree
::Token(token
) => token
.kind
!= token
::Comma
,
149 TokenTree
::Delimited(_
, DelimToken
::Paren
, _
) => {
150 !matches
!(prev
, TokenTree
::Token(Token { kind: token::Ident(..), .. }
))
152 TokenTree
::Delimited(_
, DelimToken
::Bracket
, _
) => {
153 !matches
!(prev
, TokenTree
::Token(Token { kind: token::Pound, .. }
))
155 TokenTree
::Delimited(..) => true,
159 fn binop_to_string(op
: BinOpToken
) -> &'
static str {
165 token
::Percent
=> "%",
174 fn doc_comment_to_string(
175 comment_kind
: CommentKind
,
176 attr_style
: ast
::AttrStyle
,
179 match (comment_kind
, attr_style
) {
180 (CommentKind
::Line
, ast
::AttrStyle
::Outer
) => format
!("///{}", data
),
181 (CommentKind
::Line
, ast
::AttrStyle
::Inner
) => format
!("//!{}", data
),
182 (CommentKind
::Block
, ast
::AttrStyle
::Outer
) => format
!("/**{}*/", data
),
183 (CommentKind
::Block
, ast
::AttrStyle
::Inner
) => format
!("/*!{}*/", data
),
187 pub fn literal_to_string(lit
: token
::Lit
) -> String
{
188 let token
::Lit { kind, symbol, suffix }
= lit
;
189 let mut out
= match kind
{
190 token
::Byte
=> format
!("b'{}'", symbol
),
191 token
::Char
=> format
!("'{}'", symbol
),
192 token
::Str
=> format
!("\"{}\"", symbol
),
193 token
::StrRaw(n
) => {
194 format
!("r{delim}\"{string}\"{delim}", delim
= "#".repeat(n
as usize), string
= symbol
)
196 token
::ByteStr
=> format
!("b\"{}\"", symbol
),
197 token
::ByteStrRaw(n
) => {
198 format
!("br{delim}\"{string}\"{delim}", delim
= "#".repeat(n
as usize), string
= symbol
)
200 token
::Integer
| token
::Float
| token
::Bool
| token
::Err
=> symbol
.to_string(),
203 if let Some(suffix
) = suffix
{
204 out
.push_str(&suffix
.as_str())
210 fn visibility_qualified(vis
: &ast
::Visibility
, s
: &str) -> String
{
211 format
!("{}{}", State
::new().to_string(|s
| s
.print_visibility(vis
)), s
)
214 impl std
::ops
::Deref
for State
<'_
> {
215 type Target
= pp
::Printer
;
216 fn deref(&self) -> &Self::Target
{
221 impl std
::ops
::DerefMut
for State
<'_
> {
222 fn deref_mut(&mut self) -> &mut Self::Target
{
227 pub trait PrintState
<'a
>: std
::ops
::Deref
<Target
= pp
::Printer
> + std
::ops
::DerefMut
{
228 fn comments(&mut self) -> &mut Option
<Comments
<'a
>>;
229 fn print_ident(&mut self, ident
: Ident
);
230 fn print_generic_args(&mut self, args
: &ast
::GenericArgs
, colons_before_params
: bool
);
240 F
: FnMut(&mut Self, &T
),
243 if let Some((first
, rest
)) = elts
.split_first() {
249 self.word_space(sep
);
256 fn commasep
<T
, F
>(&mut self, b
: Breaks
, elts
: &[T
], op
: F
)
258 F
: FnMut(&mut Self, &T
),
260 self.strsep(",", false, b
, elts
, op
)
263 fn maybe_print_comment(&mut self, pos
: BytePos
) {
264 while let Some(ref cmnt
) = self.next_comment() {
266 self.print_comment(cmnt
);
273 fn print_comment(&mut self, cmnt
: &Comment
) {
275 CommentStyle
::Mixed
=> {
276 if !self.is_beginning_of_line() {
279 if let Some((last
, lines
)) = cmnt
.lines
.split_last() {
283 self.word(line
.clone());
287 self.word(last
.clone());
294 CommentStyle
::Isolated
=> {
295 self.hardbreak_if_not_bol();
296 for line
in &cmnt
.lines
{
297 // Don't print empty lines because they will end up as trailing
299 if !line
.is_empty() {
300 self.word(line
.clone());
305 CommentStyle
::Trailing
=> {
306 if !self.is_beginning_of_line() {
309 if cmnt
.lines
.len() == 1 {
310 self.word(cmnt
.lines
[0].clone());
314 for line
in &cmnt
.lines
{
315 if !line
.is_empty() {
316 self.word(line
.clone());
323 CommentStyle
::BlankLine
=> {
324 // We need to do at least one, possibly two hardbreaks.
325 let twice
= match self.last_token() {
326 pp
::Token
::String(s
) => ";" == s
,
327 pp
::Token
::Begin(_
) => true,
328 pp
::Token
::End
=> true,
337 if let Some(cmnts
) = self.comments() {
342 fn next_comment(&mut self) -> Option
<Comment
> {
343 self.comments().as_mut().and_then(|c
| c
.next())
346 fn print_literal(&mut self, lit
: &ast
::Lit
) {
347 self.maybe_print_comment(lit
.span
.lo());
348 self.word(lit
.token
.to_string())
351 fn print_string(&mut self, st
: &str, style
: ast
::StrStyle
) {
352 let st
= match style
{
353 ast
::StrStyle
::Cooked
=> (format
!("\"{}\"", st
.escape_debug())),
354 ast
::StrStyle
::Raw(n
) => {
355 format
!("r{delim}\"{string}\"{delim}", delim
= "#".repeat(n
as usize), string
= st
)
361 fn print_symbol(&mut self, sym
: Symbol
, style
: ast
::StrStyle
) {
362 self.print_string(&sym
.as_str(), style
);
365 fn print_inner_attributes(&mut self, attrs
: &[ast
::Attribute
]) {
366 self.print_either_attributes(attrs
, ast
::AttrStyle
::Inner
, false, true)
369 fn print_inner_attributes_no_trailing_hardbreak(&mut self, attrs
: &[ast
::Attribute
]) {
370 self.print_either_attributes(attrs
, ast
::AttrStyle
::Inner
, false, false)
373 fn print_outer_attributes(&mut self, attrs
: &[ast
::Attribute
]) {
374 self.print_either_attributes(attrs
, ast
::AttrStyle
::Outer
, false, true)
377 fn print_inner_attributes_inline(&mut self, attrs
: &[ast
::Attribute
]) {
378 self.print_either_attributes(attrs
, ast
::AttrStyle
::Inner
, true, true)
381 fn print_outer_attributes_inline(&mut self, attrs
: &[ast
::Attribute
]) {
382 self.print_either_attributes(attrs
, ast
::AttrStyle
::Outer
, true, true)
385 fn print_either_attributes(
387 attrs
: &[ast
::Attribute
],
388 kind
: ast
::AttrStyle
,
390 trailing_hardbreak
: bool
,
394 if attr
.style
== kind
{
395 self.print_attribute_inline(attr
, is_inline
);
402 if count
> 0 && trailing_hardbreak
&& !is_inline
{
403 self.hardbreak_if_not_bol();
407 fn print_attribute(&mut self, attr
: &ast
::Attribute
) {
408 self.print_attribute_inline(attr
, false)
411 fn print_attribute_inline(&mut self, attr
: &ast
::Attribute
, is_inline
: bool
) {
413 self.hardbreak_if_not_bol();
415 self.maybe_print_comment(attr
.span
.lo());
417 ast
::AttrKind
::Normal(ref item
, _
) => {
419 ast
::AttrStyle
::Inner
=> self.word("#!["),
420 ast
::AttrStyle
::Outer
=> self.word("#["),
422 self.print_attr_item(&item
, attr
.span
);
425 ast
::AttrKind
::DocComment(comment_kind
, data
) => {
426 self.word(doc_comment_to_string(comment_kind
, attr
.style
, data
));
432 fn print_attr_item(&mut self, item
: &ast
::AttrItem
, span
: Span
) {
435 MacArgs
::Delimited(_
, delim
, tokens
) => self.print_mac_common(
436 Some(MacHeader
::Path(&item
.path
)),
444 MacArgs
::Empty
| MacArgs
::Eq(..) => {
445 self.print_path(&item
.path
, false, 0);
446 if let MacArgs
::Eq(_
, token
) = &item
.args
{
448 self.word_space("=");
449 let token_str
= self.token_to_string_ext(token
, true);
450 self.word(token_str
);
457 fn print_meta_list_item(&mut self, item
: &ast
::NestedMetaItem
) {
459 ast
::NestedMetaItem
::MetaItem(ref mi
) => self.print_meta_item(mi
),
460 ast
::NestedMetaItem
::Literal(ref lit
) => self.print_literal(lit
),
464 fn print_meta_item(&mut self, item
: &ast
::MetaItem
) {
465 self.ibox(INDENT_UNIT
);
467 ast
::MetaItemKind
::Word
=> self.print_path(&item
.path
, false, 0),
468 ast
::MetaItemKind
::NameValue(ref value
) => {
469 self.print_path(&item
.path
, false, 0);
471 self.word_space("=");
472 self.print_literal(value
);
474 ast
::MetaItemKind
::List(ref items
) => {
475 self.print_path(&item
.path
, false, 0);
477 self.commasep(Consistent
, &items
[..], |s
, i
| s
.print_meta_list_item(i
));
484 /// This doesn't deserve to be called "pretty" printing, but it should be
485 /// meaning-preserving. A quick hack that might help would be to look at the
486 /// spans embedded in the TTs to decide where to put spaces and newlines.
487 /// But it'd be better to parse these according to the grammar of the
488 /// appropriate macro, transcribe back into the grammar we just parsed from,
489 /// and then pretty-print the resulting AST nodes (so, e.g., we print
490 /// expression arguments as expressions). It can be done! I think.
491 fn print_tt(&mut self, tt
: &TokenTree
, convert_dollar_crate
: bool
) {
493 TokenTree
::Token(token
) => {
494 let token_str
= self.token_to_string_ext(&token
, convert_dollar_crate
);
495 self.word(token_str
);
496 if let token
::DocComment(..) = token
.kind
{
500 TokenTree
::Delimited(dspan
, delim
, tts
) => {
501 self.print_mac_common(
507 convert_dollar_crate
,
514 fn print_tts(&mut self, tts
: &TokenStream
, convert_dollar_crate
: bool
) {
515 let mut iter
= tts
.trees().peekable();
516 while let Some(tt
) = iter
.next() {
517 self.print_tt(&tt
, convert_dollar_crate
);
518 if let Some(next
) = iter
.peek() {
519 if tt_prepend_space(next
, &tt
) {
528 header
: Option
<MacHeader
<'_
>>,
530 ident
: Option
<Ident
>,
533 convert_dollar_crate
: bool
,
536 if delim
== DelimToken
::Brace
{
537 self.cbox(INDENT_UNIT
);
540 Some(MacHeader
::Path(path
)) => self.print_path(path
, false, 0),
541 Some(MacHeader
::Keyword(kw
)) => self.word(kw
),
547 if let Some(ident
) = ident
{
549 self.print_ident(ident
);
552 DelimToken
::Brace
=> {
553 if header
.is_some() || has_bang
|| ident
.is_some() {
562 let token_str
= self.token_kind_to_string(&token
::OpenDelim(delim
));
567 self.print_tts(tts
, convert_dollar_crate
);
570 DelimToken
::Brace
=> self.bclose(span
),
572 let token_str
= self.token_kind_to_string(&token
::CloseDelim(delim
));
578 fn print_path(&mut self, path
: &ast
::Path
, colons_before_params
: bool
, depth
: usize) {
579 self.maybe_print_comment(path
.span
.lo());
581 for (i
, segment
) in path
.segments
[..path
.segments
.len() - depth
].iter().enumerate() {
585 self.print_path_segment(segment
, colons_before_params
);
589 fn print_path_segment(&mut self, segment
: &ast
::PathSegment
, colons_before_params
: bool
) {
590 if segment
.ident
.name
!= kw
::PathRoot
{
591 self.print_ident(segment
.ident
);
592 if let Some(ref args
) = segment
.args
{
593 self.print_generic_args(args
, colons_before_params
);
598 fn head
<S
: Into
<Cow
<'
static, str>>>(&mut self, w
: S
) {
600 // Outer-box is consistent.
601 self.cbox(INDENT_UNIT
);
602 // Head-box is inconsistent.
603 self.ibox(w
.len() + 1);
604 // Keyword that starts the head.
610 fn bopen(&mut self) {
612 self.end(); // Close the head-box.
615 fn bclose_maybe_open(&mut self, span
: rustc_span
::Span
, close_box
: bool
) {
616 self.maybe_print_comment(span
.hi());
617 self.break_offset_if_not_bol(1, -(INDENT_UNIT
as isize));
620 self.end(); // Close the outer-box.
624 fn bclose(&mut self, span
: rustc_span
::Span
) {
625 self.bclose_maybe_open(span
, true)
628 fn break_offset_if_not_bol(&mut self, n
: usize, off
: isize) {
629 if !self.is_beginning_of_line() {
630 self.break_offset(n
, off
)
631 } else if off
!= 0 && self.last_token().is_hardbreak_tok() {
632 // We do something pretty sketchy here: tuck the nonzero
633 // offset-adjustment we were going to deposit along with the
634 // break into the previous hardbreak.
635 self.replace_last_token(pp
::Printer
::hardbreak_tok_offset(off
));
639 fn nonterminal_to_string(&self, nt
: &Nonterminal
) -> String
{
641 token
::NtExpr(ref e
) => self.expr_to_string(e
),
642 token
::NtMeta(ref e
) => self.attr_item_to_string(e
),
643 token
::NtTy(ref e
) => self.ty_to_string(e
),
644 token
::NtPath(ref e
) => self.path_to_string(e
),
645 token
::NtItem(ref e
) => self.item_to_string(e
),
646 token
::NtBlock(ref e
) => self.block_to_string(e
),
647 token
::NtStmt(ref e
) => self.stmt_to_string(e
),
648 token
::NtPat(ref e
) => self.pat_to_string(e
),
649 token
::NtIdent(e
, is_raw
) => IdentPrinter
::for_ast_ident(e
, is_raw
).to_string(),
650 token
::NtLifetime(e
) => e
.to_string(),
651 token
::NtLiteral(ref e
) => self.expr_to_string(e
),
652 token
::NtTT(ref tree
) => self.tt_to_string(tree
),
653 token
::NtVis(ref e
) => self.vis_to_string(e
),
657 /// Print the token kind precisely, without converting `$crate` into its respective crate name.
658 fn token_kind_to_string(&self, tok
: &TokenKind
) -> String
{
659 self.token_kind_to_string_ext(tok
, None
)
662 fn token_kind_to_string_ext(
665 convert_dollar_crate
: Option
<Span
>,
668 token
::Eq
=> "=".to_string(),
669 token
::Lt
=> "<".to_string(),
670 token
::Le
=> "<=".to_string(),
671 token
::EqEq
=> "==".to_string(),
672 token
::Ne
=> "!=".to_string(),
673 token
::Ge
=> ">=".to_string(),
674 token
::Gt
=> ">".to_string(),
675 token
::Not
=> "!".to_string(),
676 token
::Tilde
=> "~".to_string(),
677 token
::OrOr
=> "||".to_string(),
678 token
::AndAnd
=> "&&".to_string(),
679 token
::BinOp(op
) => binop_to_string(op
).to_string(),
680 token
::BinOpEq(op
) => format
!("{}=", binop_to_string(op
)),
682 /* Structural symbols */
683 token
::At
=> "@".to_string(),
684 token
::Dot
=> ".".to_string(),
685 token
::DotDot
=> "..".to_string(),
686 token
::DotDotDot
=> "...".to_string(),
687 token
::DotDotEq
=> "..=".to_string(),
688 token
::Comma
=> ",".to_string(),
689 token
::Semi
=> ";".to_string(),
690 token
::Colon
=> ":".to_string(),
691 token
::ModSep
=> "::".to_string(),
692 token
::RArrow
=> "->".to_string(),
693 token
::LArrow
=> "<-".to_string(),
694 token
::FatArrow
=> "=>".to_string(),
695 token
::OpenDelim(token
::Paren
) => "(".to_string(),
696 token
::CloseDelim(token
::Paren
) => ")".to_string(),
697 token
::OpenDelim(token
::Bracket
) => "[".to_string(),
698 token
::CloseDelim(token
::Bracket
) => "]".to_string(),
699 token
::OpenDelim(token
::Brace
) => "{".to_string(),
700 token
::CloseDelim(token
::Brace
) => "}".to_string(),
701 token
::OpenDelim(token
::NoDelim
) | token
::CloseDelim(token
::NoDelim
) => "".to_string(),
702 token
::Pound
=> "#".to_string(),
703 token
::Dollar
=> "$".to_string(),
704 token
::Question
=> "?".to_string(),
705 token
::SingleQuote
=> "'".to_string(),
708 token
::Literal(lit
) => literal_to_string(lit
),
710 /* Name components */
711 token
::Ident(s
, is_raw
) => {
712 IdentPrinter
::new(s
, is_raw
, convert_dollar_crate
).to_string()
714 token
::Lifetime(s
) => s
.to_string(),
717 token
::DocComment(comment_kind
, attr_style
, data
) => {
718 doc_comment_to_string(comment_kind
, attr_style
, data
)
720 token
::Eof
=> "<eof>".to_string(),
722 token
::Interpolated(ref nt
) => self.nonterminal_to_string(nt
),
726 /// Print the token precisely, without converting `$crate` into its respective crate name.
727 fn token_to_string(&self, token
: &Token
) -> String
{
728 self.token_to_string_ext(token
, false)
731 fn token_to_string_ext(&self, token
: &Token
, convert_dollar_crate
: bool
) -> String
{
732 let convert_dollar_crate
= convert_dollar_crate
.then_some(token
.span
);
733 self.token_kind_to_string_ext(&token
.kind
, convert_dollar_crate
)
736 fn ty_to_string(&self, ty
: &ast
::Ty
) -> String
{
737 self.to_string(|s
| s
.print_type(ty
))
740 fn bounds_to_string(&self, bounds
: &[ast
::GenericBound
]) -> String
{
741 self.to_string(|s
| s
.print_type_bounds("", bounds
))
744 fn pat_to_string(&self, pat
: &ast
::Pat
) -> String
{
745 self.to_string(|s
| s
.print_pat(pat
))
748 fn expr_to_string(&self, e
: &ast
::Expr
) -> String
{
749 self.to_string(|s
| s
.print_expr(e
))
752 fn tt_to_string(&self, tt
: &TokenTree
) -> String
{
753 self.to_string(|s
| s
.print_tt(tt
, false))
756 fn tts_to_string(&self, tokens
: &TokenStream
) -> String
{
757 self.to_string(|s
| s
.print_tts(tokens
, false))
760 fn stmt_to_string(&self, stmt
: &ast
::Stmt
) -> String
{
761 self.to_string(|s
| s
.print_stmt(stmt
))
764 fn item_to_string(&self, i
: &ast
::Item
) -> String
{
765 self.to_string(|s
| s
.print_item(i
))
768 fn generic_params_to_string(&self, generic_params
: &[ast
::GenericParam
]) -> String
{
769 self.to_string(|s
| s
.print_generic_params(generic_params
))
772 fn path_to_string(&self, p
: &ast
::Path
) -> String
{
773 self.to_string(|s
| s
.print_path(p
, false, 0))
776 fn path_segment_to_string(&self, p
: &ast
::PathSegment
) -> String
{
777 self.to_string(|s
| s
.print_path_segment(p
, false))
780 fn vis_to_string(&self, v
: &ast
::Visibility
) -> String
{
781 self.to_string(|s
| s
.print_visibility(v
))
784 fn block_to_string(&self, blk
: &ast
::Block
) -> String
{
786 // Containing cbox, will be closed by `print_block` at `}`.
788 // Head-ibox, will be closed by `print_block` after `{`.
794 fn meta_list_item_to_string(&self, li
: &ast
::NestedMetaItem
) -> String
{
795 self.to_string(|s
| s
.print_meta_list_item(li
))
798 fn attr_item_to_string(&self, ai
: &ast
::AttrItem
) -> String
{
799 self.to_string(|s
| s
.print_attr_item(ai
, ai
.path
.span
))
802 fn attribute_to_string(&self, attr
: &ast
::Attribute
) -> String
{
803 self.to_string(|s
| s
.print_attribute(attr
))
806 fn param_to_string(&self, arg
: &ast
::Param
) -> String
{
807 self.to_string(|s
| s
.print_param(arg
, false))
810 fn to_string(&self, f
: impl FnOnce(&mut State
<'_
>)) -> String
{
811 let mut printer
= State
::new();
817 impl<'a
> PrintState
<'a
> for State
<'a
> {
818 fn comments(&mut self) -> &mut Option
<Comments
<'a
>> {
822 fn print_ident(&mut self, ident
: Ident
) {
823 self.s
.word(IdentPrinter
::for_ast_ident(ident
, ident
.is_raw_guess()).to_string());
824 self.ann
.post(self, AnnNode
::Ident(&ident
))
827 fn print_generic_args(&mut self, args
: &ast
::GenericArgs
, colons_before_params
: bool
) {
828 if colons_before_params
{
833 ast
::GenericArgs
::AngleBracketed(ref data
) => {
835 self.commasep(Inconsistent
, &data
.args
, |s
, arg
| match arg
{
836 ast
::AngleBracketedArg
::Arg(a
) => s
.print_generic_arg(a
),
837 ast
::AngleBracketedArg
::Constraint(c
) => s
.print_assoc_constraint(c
),
842 ast
::GenericArgs
::Parenthesized(ref data
) => {
844 self.commasep(Inconsistent
, &data
.inputs
, |s
, ty
| s
.print_type(ty
));
846 self.print_fn_ret_ty(&data
.output
);
853 pub fn new() -> State
<'a
> {
854 State { s: pp::mk_printer(), comments: None, ann: &NoAnn }
857 // Synthesizes a comment that was not textually present in the original source
859 pub fn synth_comment(&mut self, text
: String
) {
867 crate fn commasep_cmnt
<T
, F
, G
>(&mut self, b
: Breaks
, elts
: &[T
], mut op
: F
, mut get_span
: G
)
869 F
: FnMut(&mut State
<'_
>, &T
),
870 G
: FnMut(&T
) -> rustc_span
::Span
,
873 let len
= elts
.len();
876 self.maybe_print_comment(get_span(elt
).hi());
881 self.maybe_print_trailing_comment(get_span(elt
), Some(get_span(&elts
[i
]).hi()));
882 self.space_if_not_bol();
888 crate fn commasep_exprs(&mut self, b
: Breaks
, exprs
: &[P
<ast
::Expr
>]) {
889 self.commasep_cmnt(b
, exprs
, |s
, e
| s
.print_expr(e
), |e
| e
.span
)
892 crate fn print_foreign_mod(&mut self, nmod
: &ast
::ForeignMod
, attrs
: &[ast
::Attribute
]) {
893 self.print_inner_attributes(attrs
);
894 for item
in &nmod
.items
{
895 self.print_foreign_item(item
);
899 pub fn print_opt_lifetime(&mut self, lifetime
: &Option
<ast
::Lifetime
>) {
900 if let Some(lt
) = *lifetime
{
901 self.print_lifetime(lt
);
906 pub fn print_assoc_constraint(&mut self, constraint
: &ast
::AssocTyConstraint
) {
907 self.print_ident(constraint
.ident
);
908 constraint
.gen_args
.as_ref().map(|args
| self.print_generic_args(args
, false));
910 match &constraint
.kind
{
911 ast
::AssocTyConstraintKind
::Equality { ty }
=> {
912 self.word_space("=");
915 ast
::AssocTyConstraintKind
::Bound { bounds }
=> {
916 self.print_type_bounds(":", &*bounds
);
921 pub fn print_generic_arg(&mut self, generic_arg
: &GenericArg
) {
923 GenericArg
::Lifetime(lt
) => self.print_lifetime(*lt
),
924 GenericArg
::Type(ty
) => self.print_type(ty
),
925 GenericArg
::Const(ct
) => self.print_expr(&ct
.value
),
929 pub fn print_type(&mut self, ty
: &ast
::Ty
) {
930 self.maybe_print_comment(ty
.span
.lo());
933 ast
::TyKind
::Slice(ref ty
) => {
938 ast
::TyKind
::Ptr(ref mt
) => {
940 self.print_mt(mt
, true);
942 ast
::TyKind
::Rptr(ref lifetime
, ref mt
) => {
944 self.print_opt_lifetime(lifetime
);
945 self.print_mt(mt
, false);
947 ast
::TyKind
::Never
=> {
950 ast
::TyKind
::Tup(ref elts
) => {
952 self.commasep(Inconsistent
, &elts
[..], |s
, ty
| s
.print_type(ty
));
958 ast
::TyKind
::Paren(ref typ
) => {
960 self.print_type(typ
);
963 ast
::TyKind
::BareFn(ref f
) => {
964 self.print_ty_fn(f
.ext
, f
.unsafety
, &f
.decl
, None
, &f
.generic_params
);
966 ast
::TyKind
::Path(None
, ref path
) => {
967 self.print_path(path
, false, 0);
969 ast
::TyKind
::Path(Some(ref qself
), ref path
) => self.print_qpath(path
, qself
, false),
970 ast
::TyKind
::TraitObject(ref bounds
, syntax
) => {
971 let prefix
= if syntax
== ast
::TraitObjectSyntax
::Dyn { "dyn" }
else { "" }
;
972 self.print_type_bounds(prefix
, &bounds
[..]);
974 ast
::TyKind
::ImplTrait(_
, ref bounds
) => {
975 self.print_type_bounds("impl", &bounds
[..]);
977 ast
::TyKind
::Array(ref ty
, ref length
) => {
981 self.print_expr(&length
.value
);
984 ast
::TyKind
::Typeof(ref e
) => {
985 self.s
.word("typeof(");
986 self.print_expr(&e
.value
);
989 ast
::TyKind
::Infer
=> {
992 ast
::TyKind
::Err
=> {
994 self.s
.word("/*ERROR*/");
997 ast
::TyKind
::ImplicitSelf
=> {
1000 ast
::TyKind
::MacCall(ref m
) => {
1003 ast
::TyKind
::CVarArgs
=> {
1010 crate fn print_foreign_item(&mut self, item
: &ast
::ForeignItem
) {
1011 let ast
::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ }
= *item
;
1012 self.ann
.pre(self, AnnNode
::SubItem(id
));
1013 self.hardbreak_if_not_bol();
1014 self.maybe_print_comment(span
.lo());
1015 self.print_outer_attributes(attrs
);
1017 ast
::ForeignItemKind
::Fn(box ast
::FnKind(def
, sig
, gen
, body
)) => {
1018 self.print_fn_full(sig
, ident
, gen
, vis
, *def
, body
.as_deref(), attrs
);
1020 ast
::ForeignItemKind
::Static(ty
, mutbl
, body
) => {
1021 let def
= ast
::Defaultness
::Final
;
1022 self.print_item_const(ident
, Some(*mutbl
), ty
, body
.as_deref(), vis
, def
);
1024 ast
::ForeignItemKind
::TyAlias(box ast
::TyAliasKind(def
, generics
, bounds
, ty
)) => {
1025 self.print_associated_type(ident
, generics
, bounds
, ty
.as_deref(), vis
, *def
);
1027 ast
::ForeignItemKind
::MacCall(m
) => {
1029 if m
.args
.need_semicolon() {
1034 self.ann
.post(self, AnnNode
::SubItem(id
))
1037 fn print_item_const(
1040 mutbl
: Option
<ast
::Mutability
>,
1042 body
: Option
<&ast
::Expr
>,
1043 vis
: &ast
::Visibility
,
1044 defaultness
: ast
::Defaultness
,
1047 self.print_visibility(vis
);
1048 self.print_defaultness(defaultness
);
1049 let leading
= match mutbl
{
1051 Some(ast
::Mutability
::Not
) => "static",
1052 Some(ast
::Mutability
::Mut
) => "static mut",
1054 self.word_space(leading
);
1055 self.print_ident(ident
);
1056 self.word_space(":");
1057 self.print_type(ty
);
1059 self.end(); // end the head-ibox
1060 if let Some(body
) = body
{
1061 self.word_space("=");
1062 self.print_expr(body
);
1065 self.end(); // end the outer cbox
1068 fn print_associated_type(
1071 generics
: &ast
::Generics
,
1072 bounds
: &ast
::GenericBounds
,
1073 ty
: Option
<&ast
::Ty
>,
1074 vis
: &ast
::Visibility
,
1075 defaultness
: ast
::Defaultness
,
1078 self.print_visibility(vis
);
1079 self.print_defaultness(defaultness
);
1080 self.word_space("type");
1081 self.print_ident(ident
);
1082 self.print_generic_params(&generics
.params
);
1083 self.print_type_bounds(":", bounds
);
1084 self.print_where_clause(&generics
.where_clause
);
1085 if let Some(ty
) = ty
{
1087 self.word_space("=");
1088 self.print_type(ty
);
1091 self.end(); // end inner head-block
1092 self.end(); // end outer head-block
1095 /// Pretty-prints an item.
1096 crate fn print_item(&mut self, item
: &ast
::Item
) {
1097 self.hardbreak_if_not_bol();
1098 self.maybe_print_comment(item
.span
.lo());
1099 self.print_outer_attributes(&item
.attrs
);
1100 self.ann
.pre(self, AnnNode
::Item(item
));
1102 ast
::ItemKind
::ExternCrate(orig_name
) => {
1103 self.head(visibility_qualified(&item
.vis
, "extern crate"));
1104 if let Some(orig_name
) = orig_name
{
1105 self.print_name(orig_name
);
1110 self.print_ident(item
.ident
);
1112 self.end(); // end inner head-block
1113 self.end(); // end outer head-block
1115 ast
::ItemKind
::Use(ref tree
) => {
1116 self.head(visibility_qualified(&item
.vis
, "use"));
1117 self.print_use_tree(tree
);
1119 self.end(); // end inner head-block
1120 self.end(); // end outer head-block
1122 ast
::ItemKind
::Static(ref ty
, mutbl
, ref body
) => {
1123 let def
= ast
::Defaultness
::Final
;
1124 self.print_item_const(item
.ident
, Some(mutbl
), ty
, body
.as_deref(), &item
.vis
, def
);
1126 ast
::ItemKind
::Const(def
, ref ty
, ref body
) => {
1127 self.print_item_const(item
.ident
, None
, ty
, body
.as_deref(), &item
.vis
, def
);
1129 ast
::ItemKind
::Fn(box ast
::FnKind(def
, ref sig
, ref gen
, ref body
)) => {
1130 let body
= body
.as_deref();
1131 self.print_fn_full(sig
, item
.ident
, gen
, &item
.vis
, def
, body
, &item
.attrs
);
1133 ast
::ItemKind
::Mod(unsafety
, ref mod_kind
) => {
1134 self.head(self.to_string(|s
| {
1135 s
.print_visibility(&item
.vis
);
1136 s
.print_unsafety(unsafety
);
1139 self.print_ident(item
.ident
);
1142 ModKind
::Loaded(items
, ..) => {
1145 self.print_inner_attributes(&item
.attrs
);
1147 self.print_item(item
);
1149 self.bclose(item
.span
);
1151 ModKind
::Unloaded
=> {
1153 self.end(); // end inner head-block
1154 self.end(); // end outer head-block
1158 ast
::ItemKind
::ForeignMod(ref nmod
) => {
1159 self.head(self.to_string(|s
| {
1160 s
.print_unsafety(nmod
.unsafety
);
1163 if let Some(abi
) = nmod
.abi
{
1164 self.print_literal(&abi
.as_lit());
1168 self.print_foreign_mod(nmod
, &item
.attrs
);
1169 self.bclose(item
.span
);
1171 ast
::ItemKind
::GlobalAsm(ref ga
) => {
1172 self.head(visibility_qualified(&item
.vis
, "global_asm!"));
1173 self.s
.word(ga
.asm
.to_string());
1176 ast
::ItemKind
::TyAlias(box ast
::TyAliasKind(def
, ref generics
, ref bounds
, ref ty
)) => {
1177 let ty
= ty
.as_deref();
1178 self.print_associated_type(item
.ident
, generics
, bounds
, ty
, &item
.vis
, def
);
1180 ast
::ItemKind
::Enum(ref enum_definition
, ref params
) => {
1181 self.print_enum_def(enum_definition
, params
, item
.ident
, item
.span
, &item
.vis
);
1183 ast
::ItemKind
::Struct(ref struct_def
, ref generics
) => {
1184 self.head(visibility_qualified(&item
.vis
, "struct"));
1185 self.print_struct(struct_def
, generics
, item
.ident
, item
.span
, true);
1187 ast
::ItemKind
::Union(ref struct_def
, ref generics
) => {
1188 self.head(visibility_qualified(&item
.vis
, "union"));
1189 self.print_struct(struct_def
, generics
, item
.ident
, item
.span
, true);
1191 ast
::ItemKind
::Impl(box ast
::ImplKind
{
1202 self.print_visibility(&item
.vis
);
1203 self.print_defaultness(defaultness
);
1204 self.print_unsafety(unsafety
);
1205 self.word_nbsp("impl");
1206 self.print_constness(constness
);
1208 if !generics
.params
.is_empty() {
1209 self.print_generic_params(&generics
.params
);
1213 if let ast
::ImplPolarity
::Negative(_
) = polarity
{
1217 if let Some(ref t
) = *of_trait
{
1218 self.print_trait_ref(t
);
1220 self.word_space("for");
1223 self.print_type(self_ty
);
1224 self.print_where_clause(&generics
.where_clause
);
1228 self.print_inner_attributes(&item
.attrs
);
1229 for impl_item
in items
{
1230 self.print_assoc_item(impl_item
);
1232 self.bclose(item
.span
);
1234 ast
::ItemKind
::Trait(box ast
::TraitKind(
1242 self.print_visibility(&item
.vis
);
1243 self.print_unsafety(unsafety
);
1244 self.print_is_auto(is_auto
);
1245 self.word_nbsp("trait");
1246 self.print_ident(item
.ident
);
1247 self.print_generic_params(&generics
.params
);
1248 let mut real_bounds
= Vec
::with_capacity(bounds
.len());
1249 for b
in bounds
.iter() {
1250 if let GenericBound
::Trait(ref ptr
, ast
::TraitBoundModifier
::Maybe
) = *b
{
1252 self.word_space("for ?");
1253 self.print_trait_ref(&ptr
.trait_ref
);
1255 real_bounds
.push(b
.clone());
1258 self.print_type_bounds(":", &real_bounds
[..]);
1259 self.print_where_clause(&generics
.where_clause
);
1262 self.print_inner_attributes(&item
.attrs
);
1263 for trait_item
in trait_items
{
1264 self.print_assoc_item(trait_item
);
1266 self.bclose(item
.span
);
1268 ast
::ItemKind
::TraitAlias(ref generics
, ref bounds
) => {
1270 self.print_visibility(&item
.vis
);
1271 self.word_nbsp("trait");
1272 self.print_ident(item
.ident
);
1273 self.print_generic_params(&generics
.params
);
1274 let mut real_bounds
= Vec
::with_capacity(bounds
.len());
1275 // FIXME(durka) this seems to be some quite outdated syntax
1276 for b
in bounds
.iter() {
1277 if let GenericBound
::Trait(ref ptr
, ast
::TraitBoundModifier
::Maybe
) = *b
{
1279 self.word_space("for ?");
1280 self.print_trait_ref(&ptr
.trait_ref
);
1282 real_bounds
.push(b
.clone());
1286 self.print_type_bounds("=", &real_bounds
[..]);
1287 self.print_where_clause(&generics
.where_clause
);
1290 ast
::ItemKind
::MacCall(ref mac
) => {
1291 self.print_mac(mac
);
1292 if mac
.args
.need_semicolon() {
1296 ast
::ItemKind
::MacroDef(ref macro_def
) => {
1297 let (kw
, has_bang
) = if macro_def
.macro_rules
{
1298 ("macro_rules", true)
1300 self.print_visibility(&item
.vis
);
1303 self.print_mac_common(
1304 Some(MacHeader
::Keyword(kw
)),
1307 macro_def
.body
.delim(),
1308 ¯o_def
.body
.inner_tokens(),
1312 if macro_def
.body
.need_semicolon() {
1317 self.ann
.post(self, AnnNode
::Item(item
))
1320 fn print_trait_ref(&mut self, t
: &ast
::TraitRef
) {
1321 self.print_path(&t
.path
, false, 0)
1324 fn print_formal_generic_params(&mut self, generic_params
: &[ast
::GenericParam
]) {
1325 if !generic_params
.is_empty() {
1327 self.print_generic_params(generic_params
);
1332 fn print_poly_trait_ref(&mut self, t
: &ast
::PolyTraitRef
) {
1333 self.print_formal_generic_params(&t
.bound_generic_params
);
1334 self.print_trait_ref(&t
.trait_ref
)
1337 crate fn print_enum_def(
1339 enum_definition
: &ast
::EnumDef
,
1340 generics
: &ast
::Generics
,
1342 span
: rustc_span
::Span
,
1343 visibility
: &ast
::Visibility
,
1345 self.head(visibility_qualified(visibility
, "enum"));
1346 self.print_ident(ident
);
1347 self.print_generic_params(&generics
.params
);
1348 self.print_where_clause(&generics
.where_clause
);
1350 self.print_variants(&enum_definition
.variants
, span
)
1353 crate fn print_variants(&mut self, variants
: &[ast
::Variant
], span
: rustc_span
::Span
) {
1356 self.space_if_not_bol();
1357 self.maybe_print_comment(v
.span
.lo());
1358 self.print_outer_attributes(&v
.attrs
);
1359 self.ibox(INDENT_UNIT
);
1360 self.print_variant(v
);
1363 self.maybe_print_trailing_comment(v
.span
, None
);
1368 crate fn print_visibility(&mut self, vis
: &ast
::Visibility
) {
1370 ast
::VisibilityKind
::Public
=> self.word_nbsp("pub"),
1371 ast
::VisibilityKind
::Crate(sugar
) => match sugar
{
1372 ast
::CrateSugar
::PubCrate
=> self.word_nbsp("pub(crate)"),
1373 ast
::CrateSugar
::JustCrate
=> self.word_nbsp("crate"),
1375 ast
::VisibilityKind
::Restricted { ref path, .. }
=> {
1376 let path
= self.to_string(|s
| s
.print_path(path
, false, 0));
1377 if path
== "self" || path
== "super" {
1378 self.word_nbsp(format
!("pub({})", path
))
1380 self.word_nbsp(format
!("pub(in {})", path
))
1383 ast
::VisibilityKind
::Inherited
=> {}
1387 crate fn print_defaultness(&mut self, defaultness
: ast
::Defaultness
) {
1388 if let ast
::Defaultness
::Default(_
) = defaultness
{
1389 self.word_nbsp("default");
1393 crate fn print_struct(
1395 struct_def
: &ast
::VariantData
,
1396 generics
: &ast
::Generics
,
1398 span
: rustc_span
::Span
,
1399 print_finalizer
: bool
,
1401 self.print_ident(ident
);
1402 self.print_generic_params(&generics
.params
);
1404 ast
::VariantData
::Tuple(..) | ast
::VariantData
::Unit(..) => {
1405 if let ast
::VariantData
::Tuple(..) = struct_def
{
1407 self.commasep(Inconsistent
, struct_def
.fields(), |s
, field
| {
1408 s
.maybe_print_comment(field
.span
.lo());
1409 s
.print_outer_attributes(&field
.attrs
);
1410 s
.print_visibility(&field
.vis
);
1411 s
.print_type(&field
.ty
)
1415 self.print_where_clause(&generics
.where_clause
);
1416 if print_finalizer
{
1420 self.end(); // Close the outer-box.
1422 ast
::VariantData
::Struct(..) => {
1423 self.print_where_clause(&generics
.where_clause
);
1426 self.hardbreak_if_not_bol();
1428 for field
in struct_def
.fields() {
1429 self.hardbreak_if_not_bol();
1430 self.maybe_print_comment(field
.span
.lo());
1431 self.print_outer_attributes(&field
.attrs
);
1432 self.print_visibility(&field
.vis
);
1433 self.print_ident(field
.ident
.unwrap());
1434 self.word_nbsp(":");
1435 self.print_type(&field
.ty
);
1444 crate fn print_variant(&mut self, v
: &ast
::Variant
) {
1446 self.print_visibility(&v
.vis
);
1447 let generics
= ast
::Generics
::default();
1448 self.print_struct(&v
.data
, &generics
, v
.ident
, v
.span
, false);
1449 if let Some(ref d
) = v
.disr_expr
{
1451 self.word_space("=");
1452 self.print_expr(&d
.value
)
1456 crate fn print_assoc_item(&mut self, item
: &ast
::AssocItem
) {
1457 let ast
::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ }
= *item
;
1458 self.ann
.pre(self, AnnNode
::SubItem(id
));
1459 self.hardbreak_if_not_bol();
1460 self.maybe_print_comment(span
.lo());
1461 self.print_outer_attributes(attrs
);
1463 ast
::AssocItemKind
::Fn(box ast
::FnKind(def
, sig
, gen
, body
)) => {
1464 self.print_fn_full(sig
, ident
, gen
, vis
, *def
, body
.as_deref(), attrs
);
1466 ast
::AssocItemKind
::Const(def
, ty
, body
) => {
1467 self.print_item_const(ident
, None
, ty
, body
.as_deref(), vis
, *def
);
1469 ast
::AssocItemKind
::TyAlias(box ast
::TyAliasKind(def
, generics
, bounds
, ty
)) => {
1470 self.print_associated_type(ident
, generics
, bounds
, ty
.as_deref(), vis
, *def
);
1472 ast
::AssocItemKind
::MacCall(m
) => {
1474 if m
.args
.need_semicolon() {
1479 self.ann
.post(self, AnnNode
::SubItem(id
))
1482 crate fn print_stmt(&mut self, st
: &ast
::Stmt
) {
1483 self.maybe_print_comment(st
.span
.lo());
1485 ast
::StmtKind
::Local(ref loc
) => {
1486 self.print_outer_attributes(&loc
.attrs
);
1487 self.space_if_not_bol();
1488 self.ibox(INDENT_UNIT
);
1489 self.word_nbsp("let");
1491 self.ibox(INDENT_UNIT
);
1492 self.print_local_decl(loc
);
1494 if let Some(ref init
) = loc
.init
{
1496 self.word_space("=");
1497 self.print_expr(init
);
1502 ast
::StmtKind
::Item(ref item
) => self.print_item(item
),
1503 ast
::StmtKind
::Expr(ref expr
) => {
1504 self.space_if_not_bol();
1505 self.print_expr_outer_attr_style(expr
, false);
1506 if classify
::expr_requires_semi_to_be_stmt(expr
) {
1510 ast
::StmtKind
::Semi(ref expr
) => {
1511 self.space_if_not_bol();
1512 self.print_expr_outer_attr_style(expr
, false);
1515 ast
::StmtKind
::Empty
=> {
1516 self.space_if_not_bol();
1519 ast
::StmtKind
::MacCall(ref mac
) => {
1520 self.space_if_not_bol();
1521 self.print_outer_attributes(&mac
.attrs
);
1522 self.print_mac(&mac
.mac
);
1523 if mac
.style
== ast
::MacStmtStyle
::Semicolon
{
1528 self.maybe_print_trailing_comment(st
.span
, None
)
1531 crate fn print_block(&mut self, blk
: &ast
::Block
) {
1532 self.print_block_with_attrs(blk
, &[])
1535 crate fn print_block_unclosed_indent(&mut self, blk
: &ast
::Block
) {
1536 self.print_block_maybe_unclosed(blk
, &[], false)
1539 crate fn print_block_with_attrs(&mut self, blk
: &ast
::Block
, attrs
: &[ast
::Attribute
]) {
1540 self.print_block_maybe_unclosed(blk
, attrs
, true)
1543 crate fn print_block_maybe_unclosed(
1546 attrs
: &[ast
::Attribute
],
1550 BlockCheckMode
::Unsafe(..) => self.word_space("unsafe"),
1551 BlockCheckMode
::Default
=> (),
1553 self.maybe_print_comment(blk
.span
.lo());
1554 self.ann
.pre(self, AnnNode
::Block(blk
));
1557 self.print_inner_attributes(attrs
);
1559 for (i
, st
) in blk
.stmts
.iter().enumerate() {
1561 ast
::StmtKind
::Expr(ref expr
) if i
== blk
.stmts
.len() - 1 => {
1562 self.maybe_print_comment(st
.span
.lo());
1563 self.space_if_not_bol();
1564 self.print_expr_outer_attr_style(expr
, false);
1565 self.maybe_print_trailing_comment(expr
.span
, Some(blk
.span
.hi()));
1567 _
=> self.print_stmt(st
),
1571 self.bclose_maybe_open(blk
.span
, close_box
);
1572 self.ann
.post(self, AnnNode
::Block(blk
))
1575 /// Print a `let pat = scrutinee` expression.
1576 crate fn print_let(&mut self, pat
: &ast
::Pat
, scrutinee
: &ast
::Expr
) {
1577 self.s
.word("let ");
1579 self.print_pat(pat
);
1582 self.word_space("=");
1583 self.print_expr_cond_paren(
1585 Self::cond_needs_par(scrutinee
)
1586 || parser
::needs_par_as_let_scrutinee(scrutinee
.precedence().order()),
1590 fn print_else(&mut self, els
: Option
<&ast
::Expr
>) {
1591 if let Some(_else
) = els
{
1593 // Another `else if` block.
1594 ast
::ExprKind
::If(ref i
, ref then
, ref e
) => {
1595 self.cbox(INDENT_UNIT
- 1);
1597 self.s
.word(" else if ");
1598 self.print_expr_as_cond(i
);
1600 self.print_block(then
);
1601 self.print_else(e
.as_deref())
1603 // Final `else` block.
1604 ast
::ExprKind
::Block(ref b
, _
) => {
1605 self.cbox(INDENT_UNIT
- 1);
1607 self.s
.word(" else ");
1610 // Constraints would be great here!
1612 panic
!("print_if saw if with weird alternative");
1618 crate fn print_if(&mut self, test
: &ast
::Expr
, blk
: &ast
::Block
, elseopt
: Option
<&ast
::Expr
>) {
1621 self.print_expr_as_cond(test
);
1624 self.print_block(blk
);
1625 self.print_else(elseopt
)
1628 crate fn print_mac(&mut self, m
: &ast
::MacCall
) {
1629 self.print_mac_common(
1630 Some(MacHeader
::Path(&m
.path
)),
1634 &m
.args
.inner_tokens(),
1640 fn print_call_post(&mut self, args
: &[P
<ast
::Expr
>]) {
1642 self.commasep_exprs(Inconsistent
, args
);
1646 crate fn print_expr_maybe_paren(&mut self, expr
: &ast
::Expr
, prec
: i8) {
1647 self.print_expr_cond_paren(expr
, expr
.precedence().order() < prec
)
1650 /// Prints an expr using syntax that's acceptable in a condition position, such as the `cond` in
1651 /// `if cond { ... }`.
1652 crate fn print_expr_as_cond(&mut self, expr
: &ast
::Expr
) {
1653 self.print_expr_cond_paren(expr
, Self::cond_needs_par(expr
))
1656 /// Does `expr` need parenthesis when printed in a condition position?
1657 fn cond_needs_par(expr
: &ast
::Expr
) -> bool
{
1659 // These cases need parens due to the parse error observed in #26461: `if return {}`
1660 // parses as the erroneous construct `if (return {})`, not `if (return) {}`.
1661 ast
::ExprKind
::Closure(..) | ast
::ExprKind
::Ret(..) | ast
::ExprKind
::Break(..) => true,
1663 _
=> parser
::contains_exterior_struct_lit(expr
),
1667 /// Prints `expr` or `(expr)` when `needs_par` holds.
1668 fn print_expr_cond_paren(&mut self, expr
: &ast
::Expr
, needs_par
: bool
) {
1672 self.print_expr(expr
);
1678 fn print_expr_vec(&mut self, exprs
: &[P
<ast
::Expr
>], attrs
: &[ast
::Attribute
]) {
1679 self.ibox(INDENT_UNIT
);
1681 self.print_inner_attributes_inline(attrs
);
1682 self.commasep_exprs(Inconsistent
, exprs
);
1687 fn print_expr_anon_const(&mut self, expr
: &ast
::AnonConst
, attrs
: &[ast
::Attribute
]) {
1688 self.ibox(INDENT_UNIT
);
1689 self.s
.word("const");
1690 self.print_inner_attributes_inline(attrs
);
1691 self.print_expr(&expr
.value
);
1695 fn print_expr_repeat(
1697 element
: &ast
::Expr
,
1698 count
: &ast
::AnonConst
,
1699 attrs
: &[ast
::Attribute
],
1701 self.ibox(INDENT_UNIT
);
1703 self.print_inner_attributes_inline(attrs
);
1704 self.print_expr(element
);
1705 self.word_space(";");
1706 self.print_expr(&count
.value
);
1711 fn print_expr_struct(
1714 fields
: &[ast
::ExprField
],
1715 rest
: &ast
::StructRest
,
1716 attrs
: &[ast
::Attribute
],
1718 self.print_path(path
, true, 0);
1720 self.print_inner_attributes_inline(attrs
);
1725 s
.print_outer_attributes(&field
.attrs
);
1726 s
.ibox(INDENT_UNIT
);
1727 if !field
.is_shorthand
{
1728 s
.print_ident(field
.ident
);
1731 s
.print_expr(&field
.expr
);
1737 ast
::StructRest
::Base(_
) | ast
::StructRest
::Rest(_
) => {
1738 self.ibox(INDENT_UNIT
);
1739 if !fields
.is_empty() {
1744 if let ast
::StructRest
::Base(ref expr
) = *rest
{
1745 self.print_expr(expr
);
1749 ast
::StructRest
::None
if !fields
.is_empty() => self.s
.word(","),
1755 fn print_expr_tup(&mut self, exprs
: &[P
<ast
::Expr
>], attrs
: &[ast
::Attribute
]) {
1757 self.print_inner_attributes_inline(attrs
);
1758 self.commasep_exprs(Inconsistent
, exprs
);
1759 if exprs
.len() == 1 {
1765 fn print_expr_call(&mut self, func
: &ast
::Expr
, args
: &[P
<ast
::Expr
>]) {
1766 let prec
= match func
.kind
{
1767 ast
::ExprKind
::Field(..) => parser
::PREC_FORCE_PAREN
,
1768 _
=> parser
::PREC_POSTFIX
,
1771 self.print_expr_maybe_paren(func
, prec
);
1772 self.print_call_post(args
)
1775 fn print_expr_method_call(&mut self, segment
: &ast
::PathSegment
, args
: &[P
<ast
::Expr
>]) {
1776 let base_args
= &args
[1..];
1777 self.print_expr_maybe_paren(&args
[0], parser
::PREC_POSTFIX
);
1779 self.print_ident(segment
.ident
);
1780 if let Some(ref args
) = segment
.args
{
1781 self.print_generic_args(args
, true);
1783 self.print_call_post(base_args
)
1786 fn print_expr_binary(&mut self, op
: ast
::BinOp
, lhs
: &ast
::Expr
, rhs
: &ast
::Expr
) {
1787 let assoc_op
= AssocOp
::from_ast_binop(op
.node
);
1788 let prec
= assoc_op
.precedence() as i8;
1789 let fixity
= assoc_op
.fixity();
1791 let (left_prec
, right_prec
) = match fixity
{
1792 Fixity
::Left
=> (prec
, prec
+ 1),
1793 Fixity
::Right
=> (prec
+ 1, prec
),
1794 Fixity
::None
=> (prec
+ 1, prec
+ 1),
1797 let left_prec
= match (&lhs
.kind
, op
.node
) {
1798 // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
1799 // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
1800 // of `(x as i32) < ...`. We need to convince it _not_ to do that.
1801 (&ast
::ExprKind
::Cast { .. }
, ast
::BinOpKind
::Lt
| ast
::BinOpKind
::Shl
) => {
1802 parser
::PREC_FORCE_PAREN
1804 // We are given `(let _ = a) OP b`.
1806 // - When `OP <= LAnd` we should print `let _ = a OP b` to avoid redundant parens
1807 // as the parser will interpret this as `(let _ = a) OP b`.
1809 // - Otherwise, e.g. when we have `(let a = b) < c` in AST,
1810 // parens are required since the parser would interpret `let a = b < c` as
1811 // `let a = (b < c)`. To achieve this, we force parens.
1812 (&ast
::ExprKind
::Let { .. }
, _
) if !parser
::needs_par_as_let_scrutinee(prec
) => {
1813 parser
::PREC_FORCE_PAREN
1818 self.print_expr_maybe_paren(lhs
, left_prec
);
1820 self.word_space(op
.node
.to_string());
1821 self.print_expr_maybe_paren(rhs
, right_prec
)
1824 fn print_expr_unary(&mut self, op
: ast
::UnOp
, expr
: &ast
::Expr
) {
1825 self.s
.word(ast
::UnOp
::to_string(op
));
1826 self.print_expr_maybe_paren(expr
, parser
::PREC_PREFIX
)
1829 fn print_expr_addr_of(
1831 kind
: ast
::BorrowKind
,
1832 mutability
: ast
::Mutability
,
1837 ast
::BorrowKind
::Ref
=> self.print_mutability(mutability
, false),
1838 ast
::BorrowKind
::Raw
=> {
1839 self.word_nbsp("raw");
1840 self.print_mutability(mutability
, true);
1843 self.print_expr_maybe_paren(expr
, parser
::PREC_PREFIX
)
1846 pub fn print_expr(&mut self, expr
: &ast
::Expr
) {
1847 self.print_expr_outer_attr_style(expr
, true)
1850 fn print_expr_outer_attr_style(&mut self, expr
: &ast
::Expr
, is_inline
: bool
) {
1851 self.maybe_print_comment(expr
.span
.lo());
1853 let attrs
= &expr
.attrs
;
1855 self.print_outer_attributes_inline(attrs
);
1857 self.print_outer_attributes(attrs
);
1860 self.ibox(INDENT_UNIT
);
1861 self.ann
.pre(self, AnnNode
::Expr(expr
));
1863 ast
::ExprKind
::Box(ref expr
) => {
1864 self.word_space("box");
1865 self.print_expr_maybe_paren(expr
, parser
::PREC_PREFIX
);
1867 ast
::ExprKind
::Array(ref exprs
) => {
1868 self.print_expr_vec(&exprs
[..], attrs
);
1870 ast
::ExprKind
::ConstBlock(ref anon_const
) => {
1871 self.print_expr_anon_const(anon_const
, attrs
);
1873 ast
::ExprKind
::Repeat(ref element
, ref count
) => {
1874 self.print_expr_repeat(element
, count
, attrs
);
1876 ast
::ExprKind
::Struct(ref se
) => {
1877 self.print_expr_struct(&se
.path
, &se
.fields
, &se
.rest
, attrs
);
1879 ast
::ExprKind
::Tup(ref exprs
) => {
1880 self.print_expr_tup(&exprs
[..], attrs
);
1882 ast
::ExprKind
::Call(ref func
, ref args
) => {
1883 self.print_expr_call(func
, &args
[..]);
1885 ast
::ExprKind
::MethodCall(ref segment
, ref args
, _
) => {
1886 self.print_expr_method_call(segment
, &args
[..]);
1888 ast
::ExprKind
::Binary(op
, ref lhs
, ref rhs
) => {
1889 self.print_expr_binary(op
, lhs
, rhs
);
1891 ast
::ExprKind
::Unary(op
, ref expr
) => {
1892 self.print_expr_unary(op
, expr
);
1894 ast
::ExprKind
::AddrOf(k
, m
, ref expr
) => {
1895 self.print_expr_addr_of(k
, m
, expr
);
1897 ast
::ExprKind
::Lit(ref lit
) => {
1898 self.print_literal(lit
);
1900 ast
::ExprKind
::Cast(ref expr
, ref ty
) => {
1901 let prec
= AssocOp
::As
.precedence() as i8;
1902 self.print_expr_maybe_paren(expr
, prec
);
1904 self.word_space("as");
1905 self.print_type(ty
);
1907 ast
::ExprKind
::Type(ref expr
, ref ty
) => {
1908 let prec
= AssocOp
::Colon
.precedence() as i8;
1909 self.print_expr_maybe_paren(expr
, prec
);
1910 self.word_space(":");
1911 self.print_type(ty
);
1913 ast
::ExprKind
::Let(ref pat
, ref scrutinee
) => {
1914 self.print_let(pat
, scrutinee
);
1916 ast
::ExprKind
::If(ref test
, ref blk
, ref elseopt
) => {
1917 self.print_if(test
, blk
, elseopt
.as_deref())
1919 ast
::ExprKind
::While(ref test
, ref blk
, opt_label
) => {
1920 if let Some(label
) = opt_label
{
1921 self.print_ident(label
.ident
);
1922 self.word_space(":");
1925 self.print_expr_as_cond(test
);
1927 self.print_block_with_attrs(blk
, attrs
);
1929 ast
::ExprKind
::ForLoop(ref pat
, ref iter
, ref blk
, opt_label
) => {
1930 if let Some(label
) = opt_label
{
1931 self.print_ident(label
.ident
);
1932 self.word_space(":");
1935 self.print_pat(pat
);
1937 self.word_space("in");
1938 self.print_expr_as_cond(iter
);
1940 self.print_block_with_attrs(blk
, attrs
);
1942 ast
::ExprKind
::Loop(ref blk
, opt_label
) => {
1943 if let Some(label
) = opt_label
{
1944 self.print_ident(label
.ident
);
1945 self.word_space(":");
1949 self.print_block_with_attrs(blk
, attrs
);
1951 ast
::ExprKind
::Match(ref expr
, ref arms
) => {
1952 self.cbox(INDENT_UNIT
);
1953 self.ibox(INDENT_UNIT
);
1954 self.word_nbsp("match");
1955 self.print_expr_as_cond(expr
);
1958 self.print_inner_attributes_no_trailing_hardbreak(attrs
);
1960 self.print_arm(arm
);
1962 self.bclose(expr
.span
);
1964 ast
::ExprKind
::Closure(
1972 self.print_movability(movability
);
1973 self.print_asyncness(asyncness
);
1974 self.print_capture_clause(capture_clause
);
1976 self.print_fn_params_and_ret(decl
, true);
1978 self.print_expr(body
);
1979 self.end(); // need to close a box
1981 // a box will be closed by print_expr, but we didn't want an overall
1982 // wrapper so we closed the corresponding opening. so create an
1983 // empty box to satisfy the close.
1986 ast
::ExprKind
::Block(ref blk
, opt_label
) => {
1987 if let Some(label
) = opt_label
{
1988 self.print_ident(label
.ident
);
1989 self.word_space(":");
1991 // containing cbox, will be closed by print-block at }
1992 self.cbox(INDENT_UNIT
);
1993 // head-box, will be closed by print-block after {
1995 self.print_block_with_attrs(blk
, attrs
);
1997 ast
::ExprKind
::Async(capture_clause
, _
, ref blk
) => {
1998 self.word_nbsp("async");
1999 self.print_capture_clause(capture_clause
);
2001 // cbox/ibox in analogy to the `ExprKind::Block` arm above
2002 self.cbox(INDENT_UNIT
);
2004 self.print_block_with_attrs(blk
, attrs
);
2006 ast
::ExprKind
::Await(ref expr
) => {
2007 self.print_expr_maybe_paren(expr
, parser
::PREC_POSTFIX
);
2008 self.s
.word(".await");
2010 ast
::ExprKind
::Assign(ref lhs
, ref rhs
, _
) => {
2011 let prec
= AssocOp
::Assign
.precedence() as i8;
2012 self.print_expr_maybe_paren(lhs
, prec
+ 1);
2014 self.word_space("=");
2015 self.print_expr_maybe_paren(rhs
, prec
);
2017 ast
::ExprKind
::AssignOp(op
, ref lhs
, ref rhs
) => {
2018 let prec
= AssocOp
::Assign
.precedence() as i8;
2019 self.print_expr_maybe_paren(lhs
, prec
+ 1);
2021 self.s
.word(op
.node
.to_string());
2022 self.word_space("=");
2023 self.print_expr_maybe_paren(rhs
, prec
);
2025 ast
::ExprKind
::Field(ref expr
, ident
) => {
2026 self.print_expr_maybe_paren(expr
, parser
::PREC_POSTFIX
);
2028 self.print_ident(ident
);
2030 ast
::ExprKind
::Index(ref expr
, ref index
) => {
2031 self.print_expr_maybe_paren(expr
, parser
::PREC_POSTFIX
);
2033 self.print_expr(index
);
2036 ast
::ExprKind
::Range(ref start
, ref end
, limits
) => {
2037 // Special case for `Range`. `AssocOp` claims that `Range` has higher precedence
2038 // than `Assign`, but `x .. x = x` gives a parse error instead of `x .. (x = x)`.
2039 // Here we use a fake precedence value so that any child with lower precedence than
2040 // a "normal" binop gets parenthesized. (`LOr` is the lowest-precedence binop.)
2041 let fake_prec
= AssocOp
::LOr
.precedence() as i8;
2042 if let Some(ref e
) = *start
{
2043 self.print_expr_maybe_paren(e
, fake_prec
);
2045 if limits
== ast
::RangeLimits
::HalfOpen
{
2050 if let Some(ref e
) = *end
{
2051 self.print_expr_maybe_paren(e
, fake_prec
);
2054 ast
::ExprKind
::Underscore
=> self.s
.word("_"),
2055 ast
::ExprKind
::Path(None
, ref path
) => self.print_path(path
, true, 0),
2056 ast
::ExprKind
::Path(Some(ref qself
), ref path
) => self.print_qpath(path
, qself
, true),
2057 ast
::ExprKind
::Break(opt_label
, ref opt_expr
) => {
2058 self.s
.word("break");
2060 if let Some(label
) = opt_label
{
2061 self.print_ident(label
.ident
);
2064 if let Some(ref expr
) = *opt_expr
{
2065 self.print_expr_maybe_paren(expr
, parser
::PREC_JUMP
);
2069 ast
::ExprKind
::Continue(opt_label
) => {
2070 self.s
.word("continue");
2072 if let Some(label
) = opt_label
{
2073 self.print_ident(label
.ident
);
2077 ast
::ExprKind
::Ret(ref result
) => {
2078 self.s
.word("return");
2079 if let Some(ref expr
) = *result
{
2081 self.print_expr_maybe_paren(expr
, parser
::PREC_JUMP
);
2084 ast
::ExprKind
::InlineAsm(ref a
) => {
2087 Operand(&'a InlineAsmOperand
),
2088 Options(InlineAsmOptions
),
2091 let mut args
= vec
![];
2092 args
.push(AsmArg
::Template(InlineAsmTemplatePiece
::to_string(&a
.template
)));
2093 args
.extend(a
.operands
.iter().map(|(o
, _
)| AsmArg
::Operand(o
)));
2094 if !a
.options
.is_empty() {
2095 args
.push(AsmArg
::Options(a
.options
));
2100 self.commasep(Consistent
, &args
, |s
, arg
| match arg
{
2101 AsmArg
::Template(template
) => s
.print_string(&template
, ast
::StrStyle
::Cooked
),
2102 AsmArg
::Operand(op
) => {
2103 let print_reg_or_class
= |s
: &mut Self, r
: &InlineAsmRegOrRegClass
| match r
2105 InlineAsmRegOrRegClass
::Reg(r
) => {
2106 s
.print_symbol(*r
, ast
::StrStyle
::Cooked
)
2108 InlineAsmRegOrRegClass
::RegClass(r
) => s
.word(r
.to_string()),
2111 InlineAsmOperand
::In { reg, expr }
=> {
2114 print_reg_or_class(s
, reg
);
2119 InlineAsmOperand
::Out { reg, late, expr }
=> {
2120 s
.word(if *late { "lateout" }
else { "out" }
);
2122 print_reg_or_class(s
, reg
);
2126 Some(expr
) => s
.print_expr(expr
),
2127 None
=> s
.word("_"),
2130 InlineAsmOperand
::InOut { reg, late, expr }
=> {
2131 s
.word(if *late { "inlateout" }
else { "inout" }
);
2133 print_reg_or_class(s
, reg
);
2138 InlineAsmOperand
::SplitInOut { reg, late, in_expr, out_expr }
=> {
2139 s
.word(if *late { "inlateout" }
else { "inout" }
);
2141 print_reg_or_class(s
, reg
);
2144 s
.print_expr(in_expr
);
2148 Some(out_expr
) => s
.print_expr(out_expr
),
2149 None
=> s
.word("_"),
2152 InlineAsmOperand
::Const { expr }
=> {
2157 InlineAsmOperand
::Sym { expr }
=> {
2164 AsmArg
::Options(opts
) => {
2167 let mut options
= vec
![];
2168 if opts
.contains(InlineAsmOptions
::PURE
) {
2169 options
.push("pure");
2171 if opts
.contains(InlineAsmOptions
::NOMEM
) {
2172 options
.push("nomem");
2174 if opts
.contains(InlineAsmOptions
::READONLY
) {
2175 options
.push("readonly");
2177 if opts
.contains(InlineAsmOptions
::PRESERVES_FLAGS
) {
2178 options
.push("preserves_flags");
2180 if opts
.contains(InlineAsmOptions
::NORETURN
) {
2181 options
.push("noreturn");
2183 if opts
.contains(InlineAsmOptions
::NOSTACK
) {
2184 options
.push("nostack");
2186 if opts
.contains(InlineAsmOptions
::ATT_SYNTAX
) {
2187 options
.push("att_syntax");
2189 s
.commasep(Inconsistent
, &options
, |s
, &opt
| {
2197 ast
::ExprKind
::LlvmInlineAsm(ref a
) => {
2198 self.s
.word("llvm_asm!");
2200 self.print_symbol(a
.asm
, a
.asm_str_style
);
2201 self.word_space(":");
2203 self.commasep(Inconsistent
, &a
.outputs
, |s
, out
| {
2204 let constraint
= out
.constraint
.as_str();
2205 let mut ch
= constraint
.chars();
2207 Some('
='
) if out
.is_rw
=> {
2208 s
.print_string(&format
!("+{}", ch
.as_str()), ast
::StrStyle
::Cooked
)
2210 _
=> s
.print_string(&constraint
, ast
::StrStyle
::Cooked
),
2213 s
.print_expr(&out
.expr
);
2217 self.word_space(":");
2219 self.commasep(Inconsistent
, &a
.inputs
, |s
, &(co
, ref o
)| {
2220 s
.print_symbol(co
, ast
::StrStyle
::Cooked
);
2226 self.word_space(":");
2228 self.commasep(Inconsistent
, &a
.clobbers
, |s
, &co
| {
2229 s
.print_symbol(co
, ast
::StrStyle
::Cooked
);
2232 let mut options
= vec
![];
2234 options
.push("volatile");
2237 options
.push("alignstack");
2239 if a
.dialect
== ast
::LlvmAsmDialect
::Intel
{
2240 options
.push("intel");
2243 if !options
.is_empty() {
2245 self.word_space(":");
2246 self.commasep(Inconsistent
, &options
, |s
, &co
| {
2247 s
.print_string(co
, ast
::StrStyle
::Cooked
);
2253 ast
::ExprKind
::MacCall(ref m
) => self.print_mac(m
),
2254 ast
::ExprKind
::Paren(ref e
) => {
2256 self.print_inner_attributes_inline(attrs
);
2260 ast
::ExprKind
::Yield(ref e
) => {
2261 self.s
.word("yield");
2263 if let Some(ref expr
) = *e
{
2265 self.print_expr_maybe_paren(expr
, parser
::PREC_JUMP
);
2268 ast
::ExprKind
::Try(ref e
) => {
2269 self.print_expr_maybe_paren(e
, parser
::PREC_POSTFIX
);
2272 ast
::ExprKind
::TryBlock(ref blk
) => {
2275 self.print_block_with_attrs(blk
, attrs
)
2277 ast
::ExprKind
::Err
=> {
2279 self.s
.word("/*ERROR*/");
2283 self.ann
.post(self, AnnNode
::Expr(expr
));
2287 crate fn print_local_decl(&mut self, loc
: &ast
::Local
) {
2288 self.print_pat(&loc
.pat
);
2289 if let Some(ref ty
) = loc
.ty
{
2290 self.word_space(":");
2291 self.print_type(ty
);
2295 pub fn print_usize(&mut self, i
: usize) {
2296 self.s
.word(i
.to_string())
2299 crate fn print_name(&mut self, name
: Symbol
) {
2300 self.s
.word(name
.to_string());
2301 self.ann
.post(self, AnnNode
::Name(&name
))
2304 fn print_qpath(&mut self, path
: &ast
::Path
, qself
: &ast
::QSelf
, colons_before_params
: bool
) {
2306 self.print_type(&qself
.ty
);
2307 if qself
.position
> 0 {
2309 self.word_space("as");
2310 let depth
= path
.segments
.len() - qself
.position
;
2311 self.print_path(path
, false, depth
);
2314 for item_segment
in &path
.segments
[qself
.position
..] {
2316 self.print_ident(item_segment
.ident
);
2317 if let Some(ref args
) = item_segment
.args
{
2318 self.print_generic_args(args
, colons_before_params
)
2323 crate fn print_pat(&mut self, pat
: &ast
::Pat
) {
2324 self.maybe_print_comment(pat
.span
.lo());
2325 self.ann
.pre(self, AnnNode
::Pat(pat
));
2326 /* Pat isn't normalized, but the beauty of it
2327 is that it doesn't matter */
2329 PatKind
::Wild
=> self.s
.word("_"),
2330 PatKind
::Ident(binding_mode
, ident
, ref sub
) => {
2331 match binding_mode
{
2332 ast
::BindingMode
::ByRef(mutbl
) => {
2333 self.word_nbsp("ref");
2334 self.print_mutability(mutbl
, false);
2336 ast
::BindingMode
::ByValue(ast
::Mutability
::Not
) => {}
2337 ast
::BindingMode
::ByValue(ast
::Mutability
::Mut
) => {
2338 self.word_nbsp("mut");
2341 self.print_ident(ident
);
2342 if let Some(ref p
) = *sub
{
2344 self.s
.word_space("@");
2348 PatKind
::TupleStruct(ref path
, ref elts
) => {
2349 self.print_path(path
, true, 0);
2351 self.commasep(Inconsistent
, &elts
[..], |s
, p
| s
.print_pat(p
));
2354 PatKind
::Or(ref pats
) => {
2355 self.strsep("|", true, Inconsistent
, &pats
[..], |s
, p
| s
.print_pat(p
));
2357 PatKind
::Path(None
, ref path
) => {
2358 self.print_path(path
, true, 0);
2360 PatKind
::Path(Some(ref qself
), ref path
) => {
2361 self.print_qpath(path
, qself
, false);
2363 PatKind
::Struct(ref path
, ref fields
, etc
) => {
2364 self.print_path(path
, true, 0);
2366 self.word_space("{");
2371 s
.cbox(INDENT_UNIT
);
2372 if !f
.is_shorthand
{
2373 s
.print_ident(f
.ident
);
2376 s
.print_pat(&f
.pat
);
2382 if !fields
.is_empty() {
2383 self.word_space(",");
2390 PatKind
::Tuple(ref elts
) => {
2392 self.commasep(Inconsistent
, &elts
[..], |s
, p
| s
.print_pat(p
));
2393 if elts
.len() == 1 {
2398 PatKind
::Box(ref inner
) => {
2399 self.s
.word("box ");
2400 self.print_pat(inner
);
2402 PatKind
::Ref(ref inner
, mutbl
) => {
2404 if mutbl
== ast
::Mutability
::Mut
{
2405 self.s
.word("mut ");
2407 if let PatKind
::Ident(ast
::BindingMode
::ByValue(ast
::Mutability
::Mut
), ..) =
2411 self.print_pat(inner
);
2414 self.print_pat(inner
);
2417 PatKind
::Lit(ref e
) => self.print_expr(&**e
),
2418 PatKind
::Range(ref begin
, ref end
, Spanned { node: ref end_kind, .. }
) => {
2419 if let Some(e
) = begin
{
2424 RangeEnd
::Included(RangeSyntax
::DotDotDot
) => self.s
.word("..."),
2425 RangeEnd
::Included(RangeSyntax
::DotDotEq
) => self.s
.word("..="),
2426 RangeEnd
::Excluded
=> self.s
.word(".."),
2428 if let Some(e
) = end
{
2432 PatKind
::Slice(ref elts
) => {
2434 self.commasep(Inconsistent
, &elts
[..], |s
, p
| s
.print_pat(p
));
2437 PatKind
::Rest
=> self.s
.word(".."),
2438 PatKind
::Paren(ref inner
) => {
2440 self.print_pat(inner
);
2443 PatKind
::MacCall(ref m
) => self.print_mac(m
),
2445 self.ann
.post(self, AnnNode
::Pat(pat
))
2448 fn print_arm(&mut self, arm
: &ast
::Arm
) {
2449 // Note, I have no idea why this check is necessary, but here it is.
2450 if arm
.attrs
.is_empty() {
2453 self.cbox(INDENT_UNIT
);
2455 self.maybe_print_comment(arm
.pat
.span
.lo());
2456 self.print_outer_attributes(&arm
.attrs
);
2457 self.print_pat(&arm
.pat
);
2459 if let Some(ref e
) = arm
.guard
{
2460 self.word_space("if");
2464 self.word_space("=>");
2466 match arm
.body
.kind
{
2467 ast
::ExprKind
::Block(ref blk
, opt_label
) => {
2468 if let Some(label
) = opt_label
{
2469 self.print_ident(label
.ident
);
2470 self.word_space(":");
2473 // The block will close the pattern's ibox.
2474 self.print_block_unclosed_indent(blk
);
2476 // If it is a user-provided unsafe block, print a comma after it.
2477 if let BlockCheckMode
::Unsafe(ast
::UserProvided
) = blk
.rules
{
2482 self.end(); // Close the ibox for the pattern.
2483 self.print_expr(&arm
.body
);
2487 self.end(); // Close enclosing cbox.
2490 fn print_explicit_self(&mut self, explicit_self
: &ast
::ExplicitSelf
) {
2491 match explicit_self
.node
{
2492 SelfKind
::Value(m
) => {
2493 self.print_mutability(m
, false);
2496 SelfKind
::Region(ref lt
, m
) => {
2498 self.print_opt_lifetime(lt
);
2499 self.print_mutability(m
, false);
2502 SelfKind
::Explicit(ref typ
, m
) => {
2503 self.print_mutability(m
, false);
2504 self.s
.word("self");
2505 self.word_space(":");
2506 self.print_type(typ
)
2515 generics
: &ast
::Generics
,
2516 vis
: &ast
::Visibility
,
2517 defaultness
: ast
::Defaultness
,
2518 body
: Option
<&ast
::Block
>,
2519 attrs
: &[ast
::Attribute
],
2524 self.print_visibility(vis
);
2525 self.print_defaultness(defaultness
);
2526 self.print_fn(&sig
.decl
, sig
.header
, Some(name
), generics
);
2527 if let Some(body
) = body
{
2529 self.print_block_with_attrs(body
, attrs
);
2538 header
: ast
::FnHeader
,
2539 name
: Option
<Ident
>,
2540 generics
: &ast
::Generics
,
2542 self.print_fn_header_info(header
);
2543 if let Some(name
) = name
{
2545 self.print_ident(name
);
2547 self.print_generic_params(&generics
.params
);
2548 self.print_fn_params_and_ret(decl
, false);
2549 self.print_where_clause(&generics
.where_clause
)
2552 crate fn print_fn_params_and_ret(&mut self, decl
: &ast
::FnDecl
, is_closure
: bool
) {
2553 let (open
, close
) = if is_closure { ("|", "|") }
else { ("(", ")") }
;
2555 self.commasep(Inconsistent
, &decl
.inputs
, |s
, param
| s
.print_param(param
, is_closure
));
2557 self.print_fn_ret_ty(&decl
.output
)
2560 crate fn print_movability(&mut self, movability
: ast
::Movability
) {
2562 ast
::Movability
::Static
=> self.word_space("static"),
2563 ast
::Movability
::Movable
=> {}
2567 crate fn print_asyncness(&mut self, asyncness
: ast
::Async
) {
2568 if asyncness
.is_async() {
2569 self.word_nbsp("async");
2573 crate fn print_capture_clause(&mut self, capture_clause
: ast
::CaptureBy
) {
2574 match capture_clause
{
2575 ast
::CaptureBy
::Value
=> self.word_space("move"),
2576 ast
::CaptureBy
::Ref
=> {}
2580 pub fn print_type_bounds(&mut self, prefix
: &'
static str, bounds
: &[ast
::GenericBound
]) {
2581 if !bounds
.is_empty() {
2582 self.s
.word(prefix
);
2583 let mut first
= true;
2584 for bound
in bounds
{
2585 if !(first
&& prefix
.is_empty()) {
2591 self.word_space("+");
2595 GenericBound
::Trait(tref
, modifier
) => {
2596 if modifier
== &TraitBoundModifier
::Maybe
{
2599 self.print_poly_trait_ref(tref
);
2601 GenericBound
::Outlives(lt
) => self.print_lifetime(*lt
),
2607 crate fn print_lifetime(&mut self, lifetime
: ast
::Lifetime
) {
2608 self.print_name(lifetime
.ident
.name
)
2611 crate fn print_lifetime_bounds(
2613 lifetime
: ast
::Lifetime
,
2614 bounds
: &ast
::GenericBounds
,
2616 self.print_lifetime(lifetime
);
2617 if !bounds
.is_empty() {
2619 for (i
, bound
) in bounds
.iter().enumerate() {
2624 ast
::GenericBound
::Outlives(lt
) => self.print_lifetime(*lt
),
2631 crate fn print_generic_params(&mut self, generic_params
: &[ast
::GenericParam
]) {
2632 if generic_params
.is_empty() {
2638 self.commasep(Inconsistent
, &generic_params
, |s
, param
| {
2639 s
.print_outer_attributes_inline(¶m
.attrs
);
2642 ast
::GenericParamKind
::Lifetime
=> {
2643 let lt
= ast
::Lifetime { id: param.id, ident: param.ident }
;
2644 s
.print_lifetime_bounds(lt
, ¶m
.bounds
)
2646 ast
::GenericParamKind
::Type { ref default }
=> {
2647 s
.print_ident(param
.ident
);
2648 s
.print_type_bounds(":", ¶m
.bounds
);
2649 if let Some(ref default) = default {
2652 s
.print_type(default)
2655 ast
::GenericParamKind
::Const { ref ty, kw_span: _, ref default }
=> {
2656 s
.word_space("const");
2657 s
.print_ident(param
.ident
);
2661 s
.print_type_bounds(":", ¶m
.bounds
);
2662 if let Some(ref _default
) = default {
2663 // FIXME(const_generics_defaults): print the `default` value here
2672 crate fn print_where_clause(&mut self, where_clause
: &ast
::WhereClause
) {
2673 if where_clause
.predicates
.is_empty() && !where_clause
.has_where_token
{
2678 self.word_space("where");
2680 for (i
, predicate
) in where_clause
.predicates
.iter().enumerate() {
2682 self.word_space(",");
2686 ast
::WherePredicate
::BoundPredicate(ast
::WhereBoundPredicate
{
2687 ref bound_generic_params
,
2692 self.print_formal_generic_params(bound_generic_params
);
2693 self.print_type(bounded_ty
);
2694 self.print_type_bounds(":", bounds
);
2696 ast
::WherePredicate
::RegionPredicate(ast
::WhereRegionPredicate
{
2701 self.print_lifetime_bounds(*lifetime
, bounds
);
2703 ast
::WherePredicate
::EqPredicate(ast
::WhereEqPredicate
{
2708 self.print_type(lhs_ty
);
2710 self.word_space("=");
2711 self.print_type(rhs_ty
);
2717 crate fn print_use_tree(&mut self, tree
: &ast
::UseTree
) {
2719 ast
::UseTreeKind
::Simple(rename
, ..) => {
2720 self.print_path(&tree
.prefix
, false, 0);
2721 if let Some(rename
) = rename
{
2723 self.word_space("as");
2724 self.print_ident(rename
);
2727 ast
::UseTreeKind
::Glob
=> {
2728 if !tree
.prefix
.segments
.is_empty() {
2729 self.print_path(&tree
.prefix
, false, 0);
2734 ast
::UseTreeKind
::Nested(ref items
) => {
2735 if tree
.prefix
.segments
.is_empty() {
2738 self.print_path(&tree
.prefix
, false, 0);
2741 self.commasep(Inconsistent
, &items
[..], |this
, &(ref tree
, _
)| {
2742 this
.print_use_tree(tree
)
2749 pub fn print_mutability(&mut self, mutbl
: ast
::Mutability
, print_const
: bool
) {
2751 ast
::Mutability
::Mut
=> self.word_nbsp("mut"),
2752 ast
::Mutability
::Not
=> {
2754 self.word_nbsp("const");
2760 crate fn print_mt(&mut self, mt
: &ast
::MutTy
, print_const
: bool
) {
2761 self.print_mutability(mt
.mutbl
, print_const
);
2762 self.print_type(&mt
.ty
)
2765 crate fn print_param(&mut self, input
: &ast
::Param
, is_closure
: bool
) {
2766 self.ibox(INDENT_UNIT
);
2768 self.print_outer_attributes_inline(&input
.attrs
);
2770 match input
.ty
.kind
{
2771 ast
::TyKind
::Infer
if is_closure
=> self.print_pat(&input
.pat
),
2773 if let Some(eself
) = input
.to_self() {
2774 self.print_explicit_self(&eself
);
2776 let invalid
= if let PatKind
::Ident(_
, ident
, _
) = input
.pat
.kind
{
2777 ident
.name
== kw
::Empty
2782 self.print_pat(&input
.pat
);
2786 self.print_type(&input
.ty
);
2793 crate fn print_fn_ret_ty(&mut self, fn_ret_ty
: &ast
::FnRetTy
) {
2794 if let ast
::FnRetTy
::Ty(ty
) = fn_ret_ty
{
2795 self.space_if_not_bol();
2796 self.ibox(INDENT_UNIT
);
2797 self.word_space("->");
2798 self.print_type(ty
);
2800 self.maybe_print_comment(ty
.span
.lo());
2804 crate fn print_ty_fn(
2807 unsafety
: ast
::Unsafe
,
2809 name
: Option
<Ident
>,
2810 generic_params
: &[ast
::GenericParam
],
2812 self.ibox(INDENT_UNIT
);
2813 if !generic_params
.is_empty() {
2815 self.print_generic_params(generic_params
);
2817 let generics
= ast
::Generics
{
2819 where_clause
: ast
::WhereClause
{
2820 has_where_token
: false,
2821 predicates
: Vec
::new(),
2822 span
: rustc_span
::DUMMY_SP
,
2824 span
: rustc_span
::DUMMY_SP
,
2826 let header
= ast
::FnHeader { unsafety, ext, ..ast::FnHeader::default() }
;
2827 self.print_fn(decl
, header
, name
, &generics
);
2831 crate fn maybe_print_trailing_comment(
2833 span
: rustc_span
::Span
,
2834 next_pos
: Option
<BytePos
>,
2836 if let Some(cmnts
) = self.comments() {
2837 if let Some(cmnt
) = cmnts
.trailing_comment(span
, next_pos
) {
2838 self.print_comment(&cmnt
);
2843 crate fn print_remaining_comments(&mut self) {
2844 // If there aren't any remaining comments, then we need to manually
2845 // make sure there is a line break at the end.
2846 if self.next_comment().is_none() {
2849 while let Some(ref cmnt
) = self.next_comment() {
2850 self.print_comment(cmnt
);
2854 crate fn print_fn_header_info(&mut self, header
: ast
::FnHeader
) {
2855 self.print_constness(header
.constness
);
2856 self.print_asyncness(header
.asyncness
);
2857 self.print_unsafety(header
.unsafety
);
2860 ast
::Extern
::None
=> {}
2861 ast
::Extern
::Implicit
=> {
2862 self.word_nbsp("extern");
2864 ast
::Extern
::Explicit(abi
) => {
2865 self.word_nbsp("extern");
2866 self.print_literal(&abi
.as_lit());
2874 crate fn print_unsafety(&mut self, s
: ast
::Unsafe
) {
2876 ast
::Unsafe
::No
=> {}
2877 ast
::Unsafe
::Yes(_
) => self.word_nbsp("unsafe"),
2881 crate fn print_constness(&mut self, s
: ast
::Const
) {
2883 ast
::Const
::No
=> {}
2884 ast
::Const
::Yes(_
) => self.word_nbsp("const"),
2888 crate fn print_is_auto(&mut self, s
: ast
::IsAuto
) {
2890 ast
::IsAuto
::Yes
=> self.word_nbsp("auto"),
2891 ast
::IsAuto
::No
=> {}