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}
;
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}
;
26 pub enum MacHeader
<'a
> {
28 Keyword(&'
static str),
31 pub enum AnnNode
<'a
> {
34 Block(&'a ast
::Block
),
39 Crate(&'a ast
::Crate
),
43 fn pre(&self, _state
: &mut State
<'_
>, _node
: AnnNode
<'_
>) {}
44 fn post(&self, _state
: &mut State
<'_
>, _node
: AnnNode
<'_
>) {}
47 #[derive(Copy, Clone)]
50 impl PpAnn
for NoAnn {}
52 pub struct Comments
<'a
> {
54 comments
: Vec
<Comment
>,
58 impl<'a
> Comments
<'a
> {
59 pub fn new(sm
: &'a SourceMap
, filename
: FileName
, input
: String
) -> Comments
<'a
> {
60 let comments
= gather_comments(sm
, filename
, input
);
61 Comments { sm, comments, current: 0 }
64 pub fn next(&self) -> Option
<Comment
> {
65 self.comments
.get(self.current
).cloned()
68 pub fn trailing_comment(
70 span
: rustc_span
::Span
,
71 next_pos
: Option
<BytePos
>,
72 ) -> Option
<Comment
> {
73 if let Some(cmnt
) = self.next() {
74 if cmnt
.style
!= CommentStyle
::Trailing
{
77 let span_line
= self.sm
.lookup_char_pos(span
.hi());
78 let comment_line
= self.sm
.lookup_char_pos(cmnt
.pos
);
79 let next
= next_pos
.unwrap_or_else(|| cmnt
.pos
+ BytePos(1));
80 if span
.hi() < cmnt
.pos
&& cmnt
.pos
< next
&& span_line
.line
== comment_line
.line
{
89 pub struct State
<'a
> {
91 comments
: Option
<Comments
<'a
>>,
92 ann
: &'
a (dyn PpAnn
+ 'a
),
96 crate const INDENT_UNIT
: usize = 4;
98 /// Requires you to pass an input filename and reader so that
99 /// it can scan the input text for comments to copy forward.
100 pub fn print_crate
<'a
>(
108 has_injected_crate
: bool
,
112 comments
: Some(Comments
::new(sm
, filename
, input
)),
117 if is_expanded
&& has_injected_crate
{
118 // We need to print `#![no_std]` (and its feature gate) so that
119 // compiling pretty-printed source won't inject libstd again.
120 // However, we don't want these attributes in the AST because
121 // of the feature gate, so we fake them up here.
123 // `#![feature(prelude_import)]`
124 let pi_nested
= attr
::mk_nested_word_item(Ident
::with_dummy_span(sym
::prelude_import
));
125 let list
= attr
::mk_list_item(Ident
::with_dummy_span(sym
::feature
), vec
![pi_nested
]);
126 let fake_attr
= attr
::mk_attr_inner(list
);
127 s
.print_attribute(&fake_attr
);
129 // Currently, in Rust 2018 we don't have `extern crate std;` at the crate
130 // root, so this is not needed, and actually breaks things.
131 if edition
== Edition
::Edition2015
{
133 let no_std_meta
= attr
::mk_word_item(Ident
::with_dummy_span(sym
::no_std
));
134 let fake_attr
= attr
::mk_attr_inner(no_std_meta
);
135 s
.print_attribute(&fake_attr
);
139 s
.print_mod(&krate
.module
, &krate
.attrs
);
140 s
.print_remaining_comments();
141 s
.ann
.post(&mut s
, AnnNode
::Crate(krate
));
145 pub fn to_string(f
: impl FnOnce(&mut State
<'_
>)) -> String
{
147 State { s: pp::mk_printer(), comments: None, ann: &NoAnn, is_expanded: false }
;
152 // This makes printed token streams look slightly nicer,
153 // and also addresses some specific regressions described in #63896 and #73345.
154 fn tt_prepend_space(tt
: &TokenTree
, prev
: &TokenTree
) -> bool
{
155 if let TokenTree
::Token(token
) = prev
{
156 if let token
::DocComment(comment_kind
, ..) = token
.kind
{
157 return comment_kind
!= CommentKind
::Line
;
161 TokenTree
::Token(token
) => match token
.kind
{
162 token
::Comma
=> false,
165 TokenTree
::Delimited(_
, DelimToken
::Paren
, _
) => match prev
{
166 TokenTree
::Token(token
) => match token
.kind
{
167 token
::Ident(_
, _
) => false,
172 TokenTree
::Delimited(_
, DelimToken
::Bracket
, _
) => match prev
{
173 TokenTree
::Token(token
) => match token
.kind
{
174 token
::Pound
=> false,
179 TokenTree
::Delimited(..) => true,
183 fn binop_to_string(op
: BinOpToken
) -> &'
static str {
189 token
::Percent
=> "%",
198 fn doc_comment_to_string(
199 comment_kind
: CommentKind
,
200 attr_style
: ast
::AttrStyle
,
203 match (comment_kind
, attr_style
) {
204 (CommentKind
::Line
, ast
::AttrStyle
::Outer
) => format
!("///{}", data
),
205 (CommentKind
::Line
, ast
::AttrStyle
::Inner
) => format
!("//!{}", data
),
206 (CommentKind
::Block
, ast
::AttrStyle
::Outer
) => format
!("/**{}*/", data
),
207 (CommentKind
::Block
, ast
::AttrStyle
::Inner
) => format
!("/*!{}*/", data
),
211 pub fn literal_to_string(lit
: token
::Lit
) -> String
{
212 let token
::Lit { kind, symbol, suffix }
= lit
;
213 let mut out
= match kind
{
214 token
::Byte
=> format
!("b'{}'", symbol
),
215 token
::Char
=> format
!("'{}'", symbol
),
216 token
::Str
=> format
!("\"{}\"", symbol
),
217 token
::StrRaw(n
) => {
218 format
!("r{delim}\"{string}\"{delim}", delim
= "#".repeat(n
as usize), string
= symbol
)
220 token
::ByteStr
=> format
!("b\"{}\"", symbol
),
221 token
::ByteStrRaw(n
) => {
222 format
!("br{delim}\"{string}\"{delim}", delim
= "#".repeat(n
as usize), string
= symbol
)
224 token
::Integer
| token
::Float
| token
::Bool
| token
::Err
=> symbol
.to_string(),
227 if let Some(suffix
) = suffix
{
228 out
.push_str(&suffix
.as_str())
234 /// Print the token kind precisely, without converting `$crate` into its respective crate name.
235 pub fn token_kind_to_string(tok
: &TokenKind
) -> String
{
236 token_kind_to_string_ext(tok
, None
)
239 fn token_kind_to_string_ext(tok
: &TokenKind
, convert_dollar_crate
: Option
<Span
>) -> String
{
241 token
::Eq
=> "=".to_string(),
242 token
::Lt
=> "<".to_string(),
243 token
::Le
=> "<=".to_string(),
244 token
::EqEq
=> "==".to_string(),
245 token
::Ne
=> "!=".to_string(),
246 token
::Ge
=> ">=".to_string(),
247 token
::Gt
=> ">".to_string(),
248 token
::Not
=> "!".to_string(),
249 token
::Tilde
=> "~".to_string(),
250 token
::OrOr
=> "||".to_string(),
251 token
::AndAnd
=> "&&".to_string(),
252 token
::BinOp(op
) => binop_to_string(op
).to_string(),
253 token
::BinOpEq(op
) => format
!("{}=", binop_to_string(op
)),
255 /* Structural symbols */
256 token
::At
=> "@".to_string(),
257 token
::Dot
=> ".".to_string(),
258 token
::DotDot
=> "..".to_string(),
259 token
::DotDotDot
=> "...".to_string(),
260 token
::DotDotEq
=> "..=".to_string(),
261 token
::Comma
=> ",".to_string(),
262 token
::Semi
=> ";".to_string(),
263 token
::Colon
=> ":".to_string(),
264 token
::ModSep
=> "::".to_string(),
265 token
::RArrow
=> "->".to_string(),
266 token
::LArrow
=> "<-".to_string(),
267 token
::FatArrow
=> "=>".to_string(),
268 token
::OpenDelim(token
::Paren
) => "(".to_string(),
269 token
::CloseDelim(token
::Paren
) => ")".to_string(),
270 token
::OpenDelim(token
::Bracket
) => "[".to_string(),
271 token
::CloseDelim(token
::Bracket
) => "]".to_string(),
272 token
::OpenDelim(token
::Brace
) => "{".to_string(),
273 token
::CloseDelim(token
::Brace
) => "}".to_string(),
274 token
::OpenDelim(token
::NoDelim
) | token
::CloseDelim(token
::NoDelim
) => "".to_string(),
275 token
::Pound
=> "#".to_string(),
276 token
::Dollar
=> "$".to_string(),
277 token
::Question
=> "?".to_string(),
278 token
::SingleQuote
=> "'".to_string(),
281 token
::Literal(lit
) => literal_to_string(lit
),
283 /* Name components */
284 token
::Ident(s
, is_raw
) => IdentPrinter
::new(s
, is_raw
, convert_dollar_crate
).to_string(),
285 token
::Lifetime(s
) => s
.to_string(),
288 token
::DocComment(comment_kind
, attr_style
, data
) => {
289 doc_comment_to_string(comment_kind
, attr_style
, data
)
291 token
::Eof
=> "<eof>".to_string(),
293 token
::Interpolated(ref nt
) => nonterminal_to_string(nt
),
297 /// Print the token precisely, without converting `$crate` into its respective crate name.
298 pub fn token_to_string(token
: &Token
) -> String
{
299 token_to_string_ext(token
, false)
302 fn token_to_string_ext(token
: &Token
, convert_dollar_crate
: bool
) -> String
{
303 let convert_dollar_crate
= convert_dollar_crate
.then_some(token
.span
);
304 token_kind_to_string_ext(&token
.kind
, convert_dollar_crate
)
307 pub fn nonterminal_to_string(nt
: &Nonterminal
) -> String
{
309 token
::NtExpr(ref e
) => expr_to_string(e
),
310 token
::NtMeta(ref e
) => attr_item_to_string(e
),
311 token
::NtTy(ref e
) => ty_to_string(e
),
312 token
::NtPath(ref e
) => path_to_string(e
),
313 token
::NtItem(ref e
) => item_to_string(e
),
314 token
::NtBlock(ref e
) => block_to_string(e
),
315 token
::NtStmt(ref e
) => stmt_to_string(e
),
316 token
::NtPat(ref e
) => pat_to_string(e
),
317 token
::NtIdent(e
, is_raw
) => IdentPrinter
::for_ast_ident(e
, is_raw
).to_string(),
318 token
::NtLifetime(e
) => e
.to_string(),
319 token
::NtLiteral(ref e
) => expr_to_string(e
),
320 token
::NtTT(ref tree
) => tt_to_string(tree
),
321 token
::NtVis(ref e
) => vis_to_string(e
),
325 pub fn ty_to_string(ty
: &ast
::Ty
) -> String
{
326 to_string(|s
| s
.print_type(ty
))
329 pub fn bounds_to_string(bounds
: &[ast
::GenericBound
]) -> String
{
330 to_string(|s
| s
.print_type_bounds("", bounds
))
333 pub fn pat_to_string(pat
: &ast
::Pat
) -> String
{
334 to_string(|s
| s
.print_pat(pat
))
337 pub fn expr_to_string(e
: &ast
::Expr
) -> String
{
338 to_string(|s
| s
.print_expr(e
))
341 pub fn tt_to_string(tt
: &TokenTree
) -> String
{
342 to_string(|s
| s
.print_tt(tt
, false))
345 pub fn tts_to_string(tokens
: &TokenStream
) -> String
{
346 to_string(|s
| s
.print_tts(tokens
, false))
349 pub fn stmt_to_string(stmt
: &ast
::Stmt
) -> String
{
350 to_string(|s
| s
.print_stmt(stmt
))
353 pub fn item_to_string(i
: &ast
::Item
) -> String
{
354 to_string(|s
| s
.print_item(i
))
357 pub fn generic_params_to_string(generic_params
: &[ast
::GenericParam
]) -> String
{
358 to_string(|s
| s
.print_generic_params(generic_params
))
361 pub fn path_to_string(p
: &ast
::Path
) -> String
{
362 to_string(|s
| s
.print_path(p
, false, 0))
365 pub fn path_segment_to_string(p
: &ast
::PathSegment
) -> String
{
366 to_string(|s
| s
.print_path_segment(p
, false))
369 pub fn vis_to_string(v
: &ast
::Visibility
) -> String
{
370 to_string(|s
| s
.print_visibility(v
))
373 fn block_to_string(blk
: &ast
::Block
) -> String
{
375 // Containing cbox, will be closed by `print_block` at `}`.
377 // Head-ibox, will be closed by `print_block` after `{`.
383 pub fn meta_list_item_to_string(li
: &ast
::NestedMetaItem
) -> String
{
384 to_string(|s
| s
.print_meta_list_item(li
))
387 fn attr_item_to_string(ai
: &ast
::AttrItem
) -> String
{
388 to_string(|s
| s
.print_attr_item(ai
, ai
.path
.span
))
391 pub fn attribute_to_string(attr
: &ast
::Attribute
) -> String
{
392 to_string(|s
| s
.print_attribute(attr
))
395 pub fn param_to_string(arg
: &ast
::Param
) -> String
{
396 to_string(|s
| s
.print_param(arg
, false))
399 fn visibility_qualified(vis
: &ast
::Visibility
, s
: &str) -> String
{
400 format
!("{}{}", to_string(|s
| s
.print_visibility(vis
)), s
)
403 impl std
::ops
::Deref
for State
<'_
> {
404 type Target
= pp
::Printer
;
405 fn deref(&self) -> &Self::Target
{
410 impl std
::ops
::DerefMut
for State
<'_
> {
411 fn deref_mut(&mut self) -> &mut Self::Target
{
416 pub trait PrintState
<'a
>: std
::ops
::Deref
<Target
= pp
::Printer
> + std
::ops
::DerefMut
{
417 fn comments(&mut self) -> &mut Option
<Comments
<'a
>>;
418 fn print_ident(&mut self, ident
: Ident
);
419 fn print_generic_args(&mut self, args
: &ast
::GenericArgs
, colons_before_params
: bool
);
429 F
: FnMut(&mut Self, &T
),
432 if let Some((first
, rest
)) = elts
.split_first() {
438 self.word_space(sep
);
445 fn commasep
<T
, F
>(&mut self, b
: Breaks
, elts
: &[T
], op
: F
)
447 F
: FnMut(&mut Self, &T
),
449 self.strsep(",", false, b
, elts
, op
)
452 fn maybe_print_comment(&mut self, pos
: BytePos
) {
453 while let Some(ref cmnt
) = self.next_comment() {
455 self.print_comment(cmnt
);
462 fn print_comment(&mut self, cmnt
: &Comment
) {
464 CommentStyle
::Mixed
=> {
465 if !self.is_beginning_of_line() {
468 if let Some((last
, lines
)) = cmnt
.lines
.split_last() {
472 self.word(line
.clone());
476 self.word(last
.clone());
483 CommentStyle
::Isolated
=> {
484 self.hardbreak_if_not_bol();
485 for line
in &cmnt
.lines
{
486 // Don't print empty lines because they will end up as trailing
488 if !line
.is_empty() {
489 self.word(line
.clone());
494 CommentStyle
::Trailing
=> {
495 if !self.is_beginning_of_line() {
498 if cmnt
.lines
.len() == 1 {
499 self.word(cmnt
.lines
[0].clone());
503 for line
in &cmnt
.lines
{
504 if !line
.is_empty() {
505 self.word(line
.clone());
512 CommentStyle
::BlankLine
=> {
513 // We need to do at least one, possibly two hardbreaks.
514 let twice
= match self.last_token() {
515 pp
::Token
::String(s
) => ";" == s
,
516 pp
::Token
::Begin(_
) => true,
517 pp
::Token
::End
=> true,
526 if let Some(cmnts
) = self.comments() {
531 fn next_comment(&mut self) -> Option
<Comment
> {
532 self.comments().as_mut().and_then(|c
| c
.next())
535 fn print_literal(&mut self, lit
: &ast
::Lit
) {
536 self.maybe_print_comment(lit
.span
.lo());
537 self.word(lit
.token
.to_string())
540 fn print_string(&mut self, st
: &str, style
: ast
::StrStyle
) {
541 let st
= match style
{
542 ast
::StrStyle
::Cooked
=> (format
!("\"{}\"", st
.escape_debug())),
543 ast
::StrStyle
::Raw(n
) => {
544 format
!("r{delim}\"{string}\"{delim}", delim
= "#".repeat(n
as usize), string
= st
)
550 fn print_symbol(&mut self, sym
: Symbol
, style
: ast
::StrStyle
) {
551 self.print_string(&sym
.as_str(), style
);
554 fn print_inner_attributes(&mut self, attrs
: &[ast
::Attribute
]) {
555 self.print_either_attributes(attrs
, ast
::AttrStyle
::Inner
, false, true)
558 fn print_inner_attributes_no_trailing_hardbreak(&mut self, attrs
: &[ast
::Attribute
]) {
559 self.print_either_attributes(attrs
, ast
::AttrStyle
::Inner
, false, false)
562 fn print_outer_attributes(&mut self, attrs
: &[ast
::Attribute
]) {
563 self.print_either_attributes(attrs
, ast
::AttrStyle
::Outer
, false, true)
566 fn print_inner_attributes_inline(&mut self, attrs
: &[ast
::Attribute
]) {
567 self.print_either_attributes(attrs
, ast
::AttrStyle
::Inner
, true, true)
570 fn print_outer_attributes_inline(&mut self, attrs
: &[ast
::Attribute
]) {
571 self.print_either_attributes(attrs
, ast
::AttrStyle
::Outer
, true, true)
574 fn print_either_attributes(
576 attrs
: &[ast
::Attribute
],
577 kind
: ast
::AttrStyle
,
579 trailing_hardbreak
: bool
,
583 if attr
.style
== kind
{
584 self.print_attribute_inline(attr
, is_inline
);
591 if count
> 0 && trailing_hardbreak
&& !is_inline
{
592 self.hardbreak_if_not_bol();
596 fn print_attribute(&mut self, attr
: &ast
::Attribute
) {
597 self.print_attribute_inline(attr
, false)
600 fn print_attribute_inline(&mut self, attr
: &ast
::Attribute
, is_inline
: bool
) {
602 self.hardbreak_if_not_bol();
604 self.maybe_print_comment(attr
.span
.lo());
606 ast
::AttrKind
::Normal(ref item
) => {
608 ast
::AttrStyle
::Inner
=> self.word("#!["),
609 ast
::AttrStyle
::Outer
=> self.word("#["),
611 self.print_attr_item(&item
, attr
.span
);
614 ast
::AttrKind
::DocComment(comment_kind
, data
) => {
615 self.word(doc_comment_to_string(comment_kind
, attr
.style
, data
));
621 fn print_attr_item(&mut self, item
: &ast
::AttrItem
, span
: Span
) {
624 MacArgs
::Delimited(_
, delim
, tokens
) => self.print_mac_common(
625 Some(MacHeader
::Path(&item
.path
)),
633 MacArgs
::Empty
| MacArgs
::Eq(..) => {
634 self.print_path(&item
.path
, false, 0);
635 if let MacArgs
::Eq(_
, tokens
) = &item
.args
{
637 self.word_space("=");
638 self.print_tts(tokens
, true);
645 fn print_meta_list_item(&mut self, item
: &ast
::NestedMetaItem
) {
647 ast
::NestedMetaItem
::MetaItem(ref mi
) => self.print_meta_item(mi
),
648 ast
::NestedMetaItem
::Literal(ref lit
) => self.print_literal(lit
),
652 fn print_meta_item(&mut self, item
: &ast
::MetaItem
) {
653 self.ibox(INDENT_UNIT
);
655 ast
::MetaItemKind
::Word
=> self.print_path(&item
.path
, false, 0),
656 ast
::MetaItemKind
::NameValue(ref value
) => {
657 self.print_path(&item
.path
, false, 0);
659 self.word_space("=");
660 self.print_literal(value
);
662 ast
::MetaItemKind
::List(ref items
) => {
663 self.print_path(&item
.path
, false, 0);
665 self.commasep(Consistent
, &items
[..], |s
, i
| s
.print_meta_list_item(i
));
672 /// This doesn't deserve to be called "pretty" printing, but it should be
673 /// meaning-preserving. A quick hack that might help would be to look at the
674 /// spans embedded in the TTs to decide where to put spaces and newlines.
675 /// But it'd be better to parse these according to the grammar of the
676 /// appropriate macro, transcribe back into the grammar we just parsed from,
677 /// and then pretty-print the resulting AST nodes (so, e.g., we print
678 /// expression arguments as expressions). It can be done! I think.
679 fn print_tt(&mut self, tt
: &TokenTree
, convert_dollar_crate
: bool
) {
681 TokenTree
::Token(token
) => {
682 self.word(token_to_string_ext(&token
, convert_dollar_crate
));
683 if let token
::DocComment(..) = token
.kind
{
687 TokenTree
::Delimited(dspan
, delim
, tts
) => {
688 self.print_mac_common(
694 convert_dollar_crate
,
701 fn print_tts(&mut self, tts
: &TokenStream
, convert_dollar_crate
: bool
) {
702 let mut iter
= tts
.trees().peekable();
703 while let Some(tt
) = iter
.next() {
704 self.print_tt(&tt
, convert_dollar_crate
);
705 if let Some(next
) = iter
.peek() {
706 if tt_prepend_space(next
, &tt
) {
715 header
: Option
<MacHeader
<'_
>>,
717 ident
: Option
<Ident
>,
720 convert_dollar_crate
: bool
,
723 if delim
== DelimToken
::Brace
{
724 self.cbox(INDENT_UNIT
);
727 Some(MacHeader
::Path(path
)) => self.print_path(path
, false, 0),
728 Some(MacHeader
::Keyword(kw
)) => self.word(kw
),
734 if let Some(ident
) = ident
{
736 self.print_ident(ident
);
739 DelimToken
::Brace
=> {
740 if header
.is_some() || has_bang
|| ident
.is_some() {
748 _
=> self.word(token_kind_to_string(&token
::OpenDelim(delim
))),
751 self.print_tts(tts
, convert_dollar_crate
);
754 DelimToken
::Brace
=> self.bclose(span
),
755 _
=> self.word(token_kind_to_string(&token
::CloseDelim(delim
))),
759 fn print_path(&mut self, path
: &ast
::Path
, colons_before_params
: bool
, depth
: usize) {
760 self.maybe_print_comment(path
.span
.lo());
762 for (i
, segment
) in path
.segments
[..path
.segments
.len() - depth
].iter().enumerate() {
766 self.print_path_segment(segment
, colons_before_params
);
770 fn print_path_segment(&mut self, segment
: &ast
::PathSegment
, colons_before_params
: bool
) {
771 if segment
.ident
.name
!= kw
::PathRoot
{
772 self.print_ident(segment
.ident
);
773 if let Some(ref args
) = segment
.args
{
774 self.print_generic_args(args
, colons_before_params
);
779 fn head
<S
: Into
<Cow
<'
static, str>>>(&mut self, w
: S
) {
781 // Outer-box is consistent.
782 self.cbox(INDENT_UNIT
);
783 // Head-box is inconsistent.
784 self.ibox(w
.len() + 1);
785 // Keyword that starts the head.
791 fn bopen(&mut self) {
793 self.end(); // Close the head-box.
796 fn bclose_maybe_open(&mut self, span
: rustc_span
::Span
, close_box
: bool
) {
797 self.maybe_print_comment(span
.hi());
798 self.break_offset_if_not_bol(1, -(INDENT_UNIT
as isize));
801 self.end(); // Close the outer-box.
805 fn bclose(&mut self, span
: rustc_span
::Span
) {
806 self.bclose_maybe_open(span
, true)
809 fn break_offset_if_not_bol(&mut self, n
: usize, off
: isize) {
810 if !self.is_beginning_of_line() {
811 self.break_offset(n
, off
)
813 if off
!= 0 && self.last_token().is_hardbreak_tok() {
814 // We do something pretty sketchy here: tuck the nonzero
815 // offset-adjustment we were going to deposit along with the
816 // break into the previous hardbreak.
817 self.replace_last_token(pp
::Printer
::hardbreak_tok_offset(off
));
823 impl<'a
> PrintState
<'a
> for State
<'a
> {
824 fn comments(&mut self) -> &mut Option
<Comments
<'a
>> {
828 fn print_ident(&mut self, ident
: Ident
) {
829 self.s
.word(IdentPrinter
::for_ast_ident(ident
, ident
.is_raw_guess()).to_string());
830 self.ann
.post(self, AnnNode
::Ident(&ident
))
833 fn print_generic_args(&mut self, args
: &ast
::GenericArgs
, colons_before_params
: bool
) {
834 if colons_before_params
{
839 ast
::GenericArgs
::AngleBracketed(ref data
) => {
841 self.commasep(Inconsistent
, &data
.args
, |s
, arg
| match arg
{
842 ast
::AngleBracketedArg
::Arg(a
) => s
.print_generic_arg(a
),
843 ast
::AngleBracketedArg
::Constraint(c
) => s
.print_assoc_constraint(c
),
848 ast
::GenericArgs
::Parenthesized(ref data
) => {
850 self.commasep(Inconsistent
, &data
.inputs
, |s
, ty
| s
.print_type(ty
));
852 self.print_fn_ret_ty(&data
.output
);
859 // Synthesizes a comment that was not textually present in the original source
861 pub fn synth_comment(&mut self, text
: String
) {
869 crate fn commasep_cmnt
<T
, F
, G
>(&mut self, b
: Breaks
, elts
: &[T
], mut op
: F
, mut get_span
: G
)
871 F
: FnMut(&mut State
<'_
>, &T
),
872 G
: FnMut(&T
) -> rustc_span
::Span
,
875 let len
= elts
.len();
878 self.maybe_print_comment(get_span(elt
).hi());
883 self.maybe_print_trailing_comment(get_span(elt
), Some(get_span(&elts
[i
]).hi()));
884 self.space_if_not_bol();
890 crate fn commasep_exprs(&mut self, b
: Breaks
, exprs
: &[P
<ast
::Expr
>]) {
891 self.commasep_cmnt(b
, exprs
, |s
, e
| s
.print_expr(e
), |e
| e
.span
)
894 pub fn print_mod(&mut self, _mod
: &ast
::Mod
, attrs
: &[ast
::Attribute
]) {
895 self.print_inner_attributes(attrs
);
896 for item
in &_mod
.items
{
897 self.print_item(item
);
901 crate fn print_foreign_mod(&mut self, nmod
: &ast
::ForeignMod
, attrs
: &[ast
::Attribute
]) {
902 self.print_inner_attributes(attrs
);
903 for item
in &nmod
.items
{
904 self.print_foreign_item(item
);
908 pub fn print_opt_lifetime(&mut self, lifetime
: &Option
<ast
::Lifetime
>) {
909 if let Some(lt
) = *lifetime
{
910 self.print_lifetime(lt
);
915 pub fn print_assoc_constraint(&mut self, constraint
: &ast
::AssocTyConstraint
) {
916 self.print_ident(constraint
.ident
);
918 match &constraint
.kind
{
919 ast
::AssocTyConstraintKind
::Equality { ty }
=> {
920 self.word_space("=");
923 ast
::AssocTyConstraintKind
::Bound { bounds }
=> {
924 self.print_type_bounds(":", &*bounds
);
929 pub fn print_generic_arg(&mut self, generic_arg
: &GenericArg
) {
931 GenericArg
::Lifetime(lt
) => self.print_lifetime(*lt
),
932 GenericArg
::Type(ty
) => self.print_type(ty
),
933 GenericArg
::Const(ct
) => self.print_expr(&ct
.value
),
937 pub fn print_type(&mut self, ty
: &ast
::Ty
) {
938 self.maybe_print_comment(ty
.span
.lo());
941 ast
::TyKind
::Slice(ref ty
) => {
946 ast
::TyKind
::Ptr(ref mt
) => {
948 self.print_mt(mt
, true);
950 ast
::TyKind
::Rptr(ref lifetime
, ref mt
) => {
952 self.print_opt_lifetime(lifetime
);
953 self.print_mt(mt
, false);
955 ast
::TyKind
::Never
=> {
958 ast
::TyKind
::Tup(ref elts
) => {
960 self.commasep(Inconsistent
, &elts
[..], |s
, ty
| s
.print_type(ty
));
966 ast
::TyKind
::Paren(ref typ
) => {
968 self.print_type(typ
);
971 ast
::TyKind
::BareFn(ref f
) => {
972 self.print_ty_fn(f
.ext
, f
.unsafety
, &f
.decl
, None
, &f
.generic_params
);
974 ast
::TyKind
::Path(None
, ref path
) => {
975 self.print_path(path
, false, 0);
977 ast
::TyKind
::Path(Some(ref qself
), ref path
) => self.print_qpath(path
, qself
, false),
978 ast
::TyKind
::TraitObject(ref bounds
, syntax
) => {
979 let prefix
= if syntax
== ast
::TraitObjectSyntax
::Dyn { "dyn" }
else { "" }
;
980 self.print_type_bounds(prefix
, &bounds
[..]);
982 ast
::TyKind
::ImplTrait(_
, ref bounds
) => {
983 self.print_type_bounds("impl", &bounds
[..]);
985 ast
::TyKind
::Array(ref ty
, ref length
) => {
989 self.print_expr(&length
.value
);
992 ast
::TyKind
::Typeof(ref e
) => {
993 self.s
.word("typeof(");
994 self.print_expr(&e
.value
);
997 ast
::TyKind
::Infer
=> {
1000 ast
::TyKind
::Err
=> {
1002 self.s
.word("/*ERROR*/");
1005 ast
::TyKind
::ImplicitSelf
=> {
1006 self.s
.word("Self");
1008 ast
::TyKind
::MacCall(ref m
) => {
1011 ast
::TyKind
::CVarArgs
=> {
1018 crate fn print_foreign_item(&mut self, item
: &ast
::ForeignItem
) {
1019 let ast
::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ }
= *item
;
1020 self.ann
.pre(self, AnnNode
::SubItem(id
));
1021 self.hardbreak_if_not_bol();
1022 self.maybe_print_comment(span
.lo());
1023 self.print_outer_attributes(attrs
);
1025 ast
::ForeignItemKind
::Fn(def
, sig
, gen
, body
) => {
1026 self.print_fn_full(sig
, ident
, gen
, vis
, *def
, body
.as_deref(), attrs
);
1028 ast
::ForeignItemKind
::Static(ty
, mutbl
, body
) => {
1029 let def
= ast
::Defaultness
::Final
;
1030 self.print_item_const(ident
, Some(*mutbl
), ty
, body
.as_deref(), vis
, def
);
1032 ast
::ForeignItemKind
::TyAlias(def
, generics
, bounds
, ty
) => {
1033 self.print_associated_type(ident
, generics
, bounds
, ty
.as_deref(), vis
, *def
);
1035 ast
::ForeignItemKind
::MacCall(m
) => {
1037 if m
.args
.need_semicolon() {
1042 self.ann
.post(self, AnnNode
::SubItem(id
))
1045 fn print_item_const(
1048 mutbl
: Option
<ast
::Mutability
>,
1050 body
: Option
<&ast
::Expr
>,
1051 vis
: &ast
::Visibility
,
1052 defaultness
: ast
::Defaultness
,
1055 self.print_visibility(vis
);
1056 self.print_defaultness(defaultness
);
1057 let leading
= match mutbl
{
1059 Some(ast
::Mutability
::Not
) => "static",
1060 Some(ast
::Mutability
::Mut
) => "static mut",
1062 self.word_space(leading
);
1063 self.print_ident(ident
);
1064 self.word_space(":");
1065 self.print_type(ty
);
1067 self.end(); // end the head-ibox
1068 if let Some(body
) = body
{
1069 self.word_space("=");
1070 self.print_expr(body
);
1073 self.end(); // end the outer cbox
1076 fn print_associated_type(
1079 generics
: &ast
::Generics
,
1080 bounds
: &ast
::GenericBounds
,
1081 ty
: Option
<&ast
::Ty
>,
1082 vis
: &ast
::Visibility
,
1083 defaultness
: ast
::Defaultness
,
1086 self.print_visibility(vis
);
1087 self.print_defaultness(defaultness
);
1088 self.word_space("type");
1089 self.print_ident(ident
);
1090 self.print_generic_params(&generics
.params
);
1091 self.print_type_bounds(":", bounds
);
1092 self.print_where_clause(&generics
.where_clause
);
1093 if let Some(ty
) = ty
{
1095 self.word_space("=");
1096 self.print_type(ty
);
1099 self.end(); // end inner head-block
1100 self.end(); // end outer head-block
1103 /// Pretty-prints an item.
1104 crate fn print_item(&mut self, item
: &ast
::Item
) {
1105 self.hardbreak_if_not_bol();
1106 self.maybe_print_comment(item
.span
.lo());
1107 self.print_outer_attributes(&item
.attrs
);
1108 self.ann
.pre(self, AnnNode
::Item(item
));
1110 ast
::ItemKind
::ExternCrate(orig_name
) => {
1111 self.head(visibility_qualified(&item
.vis
, "extern crate"));
1112 if let Some(orig_name
) = orig_name
{
1113 self.print_name(orig_name
);
1118 self.print_ident(item
.ident
);
1120 self.end(); // end inner head-block
1121 self.end(); // end outer head-block
1123 ast
::ItemKind
::Use(ref tree
) => {
1124 self.head(visibility_qualified(&item
.vis
, "use"));
1125 self.print_use_tree(tree
);
1127 self.end(); // end inner head-block
1128 self.end(); // end outer head-block
1130 ast
::ItemKind
::Static(ref ty
, mutbl
, ref body
) => {
1131 let def
= ast
::Defaultness
::Final
;
1132 self.print_item_const(item
.ident
, Some(mutbl
), ty
, body
.as_deref(), &item
.vis
, def
);
1134 ast
::ItemKind
::Const(def
, ref ty
, ref body
) => {
1135 self.print_item_const(item
.ident
, None
, ty
, body
.as_deref(), &item
.vis
, def
);
1137 ast
::ItemKind
::Fn(def
, ref sig
, ref gen
, ref body
) => {
1138 let body
= body
.as_deref();
1139 self.print_fn_full(sig
, item
.ident
, gen
, &item
.vis
, def
, body
, &item
.attrs
);
1141 ast
::ItemKind
::Mod(ref _mod
) => {
1142 self.head(to_string(|s
| {
1143 s
.print_visibility(&item
.vis
);
1144 s
.print_unsafety(_mod
.unsafety
);
1147 self.print_ident(item
.ident
);
1149 if _mod
.inline
|| self.is_expanded
{
1152 self.print_mod(_mod
, &item
.attrs
);
1153 self.bclose(item
.span
);
1156 self.end(); // end inner head-block
1157 self.end(); // end outer head-block
1160 ast
::ItemKind
::ForeignMod(ref nmod
) => {
1161 self.head(to_string(|s
| {
1162 s
.print_unsafety(nmod
.unsafety
);
1165 if let Some(abi
) = nmod
.abi
{
1166 self.print_literal(&abi
.as_lit());
1170 self.print_foreign_mod(nmod
, &item
.attrs
);
1171 self.bclose(item
.span
);
1173 ast
::ItemKind
::GlobalAsm(ref ga
) => {
1174 self.head(visibility_qualified(&item
.vis
, "global_asm!"));
1175 self.s
.word(ga
.asm
.to_string());
1178 ast
::ItemKind
::TyAlias(def
, ref generics
, ref bounds
, ref ty
) => {
1179 let ty
= ty
.as_deref();
1180 self.print_associated_type(item
.ident
, generics
, bounds
, ty
, &item
.vis
, def
);
1182 ast
::ItemKind
::Enum(ref enum_definition
, ref params
) => {
1183 self.print_enum_def(enum_definition
, params
, item
.ident
, item
.span
, &item
.vis
);
1185 ast
::ItemKind
::Struct(ref struct_def
, ref generics
) => {
1186 self.head(visibility_qualified(&item
.vis
, "struct"));
1187 self.print_struct(struct_def
, generics
, item
.ident
, item
.span
, true);
1189 ast
::ItemKind
::Union(ref struct_def
, ref generics
) => {
1190 self.head(visibility_qualified(&item
.vis
, "union"));
1191 self.print_struct(struct_def
, generics
, item
.ident
, item
.span
, true);
1193 ast
::ItemKind
::Impl
{
1204 self.print_visibility(&item
.vis
);
1205 self.print_defaultness(defaultness
);
1206 self.print_unsafety(unsafety
);
1207 self.word_nbsp("impl");
1208 self.print_constness(constness
);
1210 if !generics
.params
.is_empty() {
1211 self.print_generic_params(&generics
.params
);
1215 if let ast
::ImplPolarity
::Negative(_
) = polarity
{
1219 if let Some(ref t
) = *of_trait
{
1220 self.print_trait_ref(t
);
1222 self.word_space("for");
1225 self.print_type(self_ty
);
1226 self.print_where_clause(&generics
.where_clause
);
1230 self.print_inner_attributes(&item
.attrs
);
1231 for impl_item
in items
{
1232 self.print_assoc_item(impl_item
);
1234 self.bclose(item
.span
);
1236 ast
::ItemKind
::Trait(is_auto
, unsafety
, ref generics
, ref bounds
, ref trait_items
) => {
1238 self.print_visibility(&item
.vis
);
1239 self.print_unsafety(unsafety
);
1240 self.print_is_auto(is_auto
);
1241 self.word_nbsp("trait");
1242 self.print_ident(item
.ident
);
1243 self.print_generic_params(&generics
.params
);
1244 let mut real_bounds
= Vec
::with_capacity(bounds
.len());
1245 for b
in bounds
.iter() {
1246 if let GenericBound
::Trait(ref ptr
, ast
::TraitBoundModifier
::Maybe
) = *b
{
1248 self.word_space("for ?");
1249 self.print_trait_ref(&ptr
.trait_ref
);
1251 real_bounds
.push(b
.clone());
1254 self.print_type_bounds(":", &real_bounds
[..]);
1255 self.print_where_clause(&generics
.where_clause
);
1258 self.print_inner_attributes(&item
.attrs
);
1259 for trait_item
in trait_items
{
1260 self.print_assoc_item(trait_item
);
1262 self.bclose(item
.span
);
1264 ast
::ItemKind
::TraitAlias(ref generics
, ref bounds
) => {
1266 self.print_visibility(&item
.vis
);
1267 self.word_nbsp("trait");
1268 self.print_ident(item
.ident
);
1269 self.print_generic_params(&generics
.params
);
1270 let mut real_bounds
= Vec
::with_capacity(bounds
.len());
1271 // FIXME(durka) this seems to be some quite outdated syntax
1272 for b
in bounds
.iter() {
1273 if let GenericBound
::Trait(ref ptr
, ast
::TraitBoundModifier
::Maybe
) = *b
{
1275 self.word_space("for ?");
1276 self.print_trait_ref(&ptr
.trait_ref
);
1278 real_bounds
.push(b
.clone());
1282 self.print_type_bounds("=", &real_bounds
[..]);
1283 self.print_where_clause(&generics
.where_clause
);
1286 ast
::ItemKind
::MacCall(ref mac
) => {
1287 self.print_mac(mac
);
1288 if mac
.args
.need_semicolon() {
1292 ast
::ItemKind
::MacroDef(ref macro_def
) => {
1293 let (kw
, has_bang
) = if macro_def
.macro_rules
{
1294 ("macro_rules", true)
1296 self.print_visibility(&item
.vis
);
1299 self.print_mac_common(
1300 Some(MacHeader
::Keyword(kw
)),
1303 macro_def
.body
.delim(),
1304 ¯o_def
.body
.inner_tokens(),
1310 self.ann
.post(self, AnnNode
::Item(item
))
1313 fn print_trait_ref(&mut self, t
: &ast
::TraitRef
) {
1314 self.print_path(&t
.path
, false, 0)
1317 fn print_formal_generic_params(&mut self, generic_params
: &[ast
::GenericParam
]) {
1318 if !generic_params
.is_empty() {
1320 self.print_generic_params(generic_params
);
1325 fn print_poly_trait_ref(&mut self, t
: &ast
::PolyTraitRef
) {
1326 self.print_formal_generic_params(&t
.bound_generic_params
);
1327 self.print_trait_ref(&t
.trait_ref
)
1330 crate fn print_enum_def(
1332 enum_definition
: &ast
::EnumDef
,
1333 generics
: &ast
::Generics
,
1335 span
: rustc_span
::Span
,
1336 visibility
: &ast
::Visibility
,
1338 self.head(visibility_qualified(visibility
, "enum"));
1339 self.print_ident(ident
);
1340 self.print_generic_params(&generics
.params
);
1341 self.print_where_clause(&generics
.where_clause
);
1343 self.print_variants(&enum_definition
.variants
, span
)
1346 crate fn print_variants(&mut self, variants
: &[ast
::Variant
], span
: rustc_span
::Span
) {
1349 self.space_if_not_bol();
1350 self.maybe_print_comment(v
.span
.lo());
1351 self.print_outer_attributes(&v
.attrs
);
1352 self.ibox(INDENT_UNIT
);
1353 self.print_variant(v
);
1356 self.maybe_print_trailing_comment(v
.span
, None
);
1361 crate fn print_visibility(&mut self, vis
: &ast
::Visibility
) {
1363 ast
::VisibilityKind
::Public
=> self.word_nbsp("pub"),
1364 ast
::VisibilityKind
::Crate(sugar
) => match sugar
{
1365 ast
::CrateSugar
::PubCrate
=> self.word_nbsp("pub(crate)"),
1366 ast
::CrateSugar
::JustCrate
=> self.word_nbsp("crate"),
1368 ast
::VisibilityKind
::Restricted { ref path, .. }
=> {
1369 let path
= to_string(|s
| s
.print_path(path
, false, 0));
1370 if path
== "self" || path
== "super" {
1371 self.word_nbsp(format
!("pub({})", path
))
1373 self.word_nbsp(format
!("pub(in {})", path
))
1376 ast
::VisibilityKind
::Inherited
=> {}
1380 crate fn print_defaultness(&mut self, defaultness
: ast
::Defaultness
) {
1381 if let ast
::Defaultness
::Default(_
) = defaultness
{
1382 self.word_nbsp("default");
1386 crate fn print_struct(
1388 struct_def
: &ast
::VariantData
,
1389 generics
: &ast
::Generics
,
1391 span
: rustc_span
::Span
,
1392 print_finalizer
: bool
,
1394 self.print_ident(ident
);
1395 self.print_generic_params(&generics
.params
);
1397 ast
::VariantData
::Tuple(..) | ast
::VariantData
::Unit(..) => {
1398 if let ast
::VariantData
::Tuple(..) = struct_def
{
1400 self.commasep(Inconsistent
, struct_def
.fields(), |s
, field
| {
1401 s
.maybe_print_comment(field
.span
.lo());
1402 s
.print_outer_attributes(&field
.attrs
);
1403 s
.print_visibility(&field
.vis
);
1404 s
.print_type(&field
.ty
)
1408 self.print_where_clause(&generics
.where_clause
);
1409 if print_finalizer
{
1413 self.end(); // Close the outer-box.
1415 ast
::VariantData
::Struct(..) => {
1416 self.print_where_clause(&generics
.where_clause
);
1419 self.hardbreak_if_not_bol();
1421 for field
in struct_def
.fields() {
1422 self.hardbreak_if_not_bol();
1423 self.maybe_print_comment(field
.span
.lo());
1424 self.print_outer_attributes(&field
.attrs
);
1425 self.print_visibility(&field
.vis
);
1426 self.print_ident(field
.ident
.unwrap());
1427 self.word_nbsp(":");
1428 self.print_type(&field
.ty
);
1437 crate fn print_variant(&mut self, v
: &ast
::Variant
) {
1439 self.print_visibility(&v
.vis
);
1440 let generics
= ast
::Generics
::default();
1441 self.print_struct(&v
.data
, &generics
, v
.ident
, v
.span
, false);
1442 if let Some(ref d
) = v
.disr_expr
{
1444 self.word_space("=");
1445 self.print_expr(&d
.value
)
1449 crate fn print_assoc_item(&mut self, item
: &ast
::AssocItem
) {
1450 let ast
::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ }
= *item
;
1451 self.ann
.pre(self, AnnNode
::SubItem(id
));
1452 self.hardbreak_if_not_bol();
1453 self.maybe_print_comment(span
.lo());
1454 self.print_outer_attributes(attrs
);
1456 ast
::AssocItemKind
::Fn(def
, sig
, gen
, body
) => {
1457 self.print_fn_full(sig
, ident
, gen
, vis
, *def
, body
.as_deref(), attrs
);
1459 ast
::AssocItemKind
::Const(def
, ty
, body
) => {
1460 self.print_item_const(ident
, None
, ty
, body
.as_deref(), vis
, *def
);
1462 ast
::AssocItemKind
::TyAlias(def
, generics
, bounds
, ty
) => {
1463 self.print_associated_type(ident
, generics
, bounds
, ty
.as_deref(), vis
, *def
);
1465 ast
::AssocItemKind
::MacCall(m
) => {
1467 if m
.args
.need_semicolon() {
1472 self.ann
.post(self, AnnNode
::SubItem(id
))
1475 crate fn print_stmt(&mut self, st
: &ast
::Stmt
) {
1476 self.maybe_print_comment(st
.span
.lo());
1478 ast
::StmtKind
::Local(ref loc
) => {
1479 self.print_outer_attributes(&loc
.attrs
);
1480 self.space_if_not_bol();
1481 self.ibox(INDENT_UNIT
);
1482 self.word_nbsp("let");
1484 self.ibox(INDENT_UNIT
);
1485 self.print_local_decl(loc
);
1487 if let Some(ref init
) = loc
.init
{
1489 self.word_space("=");
1490 self.print_expr(init
);
1495 ast
::StmtKind
::Item(ref item
) => self.print_item(item
),
1496 ast
::StmtKind
::Expr(ref expr
) => {
1497 self.space_if_not_bol();
1498 self.print_expr_outer_attr_style(expr
, false);
1499 if classify
::expr_requires_semi_to_be_stmt(expr
) {
1503 ast
::StmtKind
::Semi(ref expr
) => {
1504 self.space_if_not_bol();
1505 self.print_expr_outer_attr_style(expr
, false);
1508 ast
::StmtKind
::Empty
=> {
1509 self.space_if_not_bol();
1512 ast
::StmtKind
::MacCall(ref mac
) => {
1513 self.space_if_not_bol();
1514 self.print_outer_attributes(&mac
.attrs
);
1515 self.print_mac(&mac
.mac
);
1516 if mac
.style
== ast
::MacStmtStyle
::Semicolon
{
1521 self.maybe_print_trailing_comment(st
.span
, None
)
1524 crate fn print_block(&mut self, blk
: &ast
::Block
) {
1525 self.print_block_with_attrs(blk
, &[])
1528 crate fn print_block_unclosed_indent(&mut self, blk
: &ast
::Block
) {
1529 self.print_block_maybe_unclosed(blk
, &[], false)
1532 crate fn print_block_with_attrs(&mut self, blk
: &ast
::Block
, attrs
: &[ast
::Attribute
]) {
1533 self.print_block_maybe_unclosed(blk
, attrs
, true)
1536 crate fn print_block_maybe_unclosed(
1539 attrs
: &[ast
::Attribute
],
1543 BlockCheckMode
::Unsafe(..) => self.word_space("unsafe"),
1544 BlockCheckMode
::Default
=> (),
1546 self.maybe_print_comment(blk
.span
.lo());
1547 self.ann
.pre(self, AnnNode
::Block(blk
));
1550 self.print_inner_attributes(attrs
);
1552 for (i
, st
) in blk
.stmts
.iter().enumerate() {
1554 ast
::StmtKind
::Expr(ref expr
) if i
== blk
.stmts
.len() - 1 => {
1555 self.maybe_print_comment(st
.span
.lo());
1556 self.space_if_not_bol();
1557 self.print_expr_outer_attr_style(expr
, false);
1558 self.maybe_print_trailing_comment(expr
.span
, Some(blk
.span
.hi()));
1560 _
=> self.print_stmt(st
),
1564 self.bclose_maybe_open(blk
.span
, close_box
);
1565 self.ann
.post(self, AnnNode
::Block(blk
))
1568 /// Print a `let pat = scrutinee` expression.
1569 crate fn print_let(&mut self, pat
: &ast
::Pat
, scrutinee
: &ast
::Expr
) {
1570 self.s
.word("let ");
1572 self.print_pat(pat
);
1575 self.word_space("=");
1576 self.print_expr_cond_paren(
1578 Self::cond_needs_par(scrutinee
)
1579 || parser
::needs_par_as_let_scrutinee(scrutinee
.precedence().order()),
1583 fn print_else(&mut self, els
: Option
<&ast
::Expr
>) {
1584 if let Some(_else
) = els
{
1586 // Another `else if` block.
1587 ast
::ExprKind
::If(ref i
, ref then
, ref e
) => {
1588 self.cbox(INDENT_UNIT
- 1);
1590 self.s
.word(" else if ");
1591 self.print_expr_as_cond(i
);
1593 self.print_block(then
);
1594 self.print_else(e
.as_deref())
1596 // Final `else` block.
1597 ast
::ExprKind
::Block(ref b
, _
) => {
1598 self.cbox(INDENT_UNIT
- 1);
1600 self.s
.word(" else ");
1603 // Constraints would be great here!
1605 panic
!("print_if saw if with weird alternative");
1611 crate fn print_if(&mut self, test
: &ast
::Expr
, blk
: &ast
::Block
, elseopt
: Option
<&ast
::Expr
>) {
1614 self.print_expr_as_cond(test
);
1617 self.print_block(blk
);
1618 self.print_else(elseopt
)
1621 crate fn print_mac(&mut self, m
: &ast
::MacCall
) {
1622 self.print_mac_common(
1623 Some(MacHeader
::Path(&m
.path
)),
1627 &m
.args
.inner_tokens(),
1633 fn print_call_post(&mut self, args
: &[P
<ast
::Expr
>]) {
1635 self.commasep_exprs(Inconsistent
, args
);
1639 crate fn print_expr_maybe_paren(&mut self, expr
: &ast
::Expr
, prec
: i8) {
1640 self.print_expr_cond_paren(expr
, expr
.precedence().order() < prec
)
1643 /// Prints an expr using syntax that's acceptable in a condition position, such as the `cond` in
1644 /// `if cond { ... }`.
1645 crate fn print_expr_as_cond(&mut self, expr
: &ast
::Expr
) {
1646 self.print_expr_cond_paren(expr
, Self::cond_needs_par(expr
))
1649 /// Does `expr` need parenthesis when printed in a condition position?
1650 fn cond_needs_par(expr
: &ast
::Expr
) -> bool
{
1652 // These cases need parens due to the parse error observed in #26461: `if return {}`
1653 // parses as the erroneous construct `if (return {})`, not `if (return) {}`.
1654 ast
::ExprKind
::Closure(..) | ast
::ExprKind
::Ret(..) | ast
::ExprKind
::Break(..) => true,
1656 _
=> parser
::contains_exterior_struct_lit(expr
),
1660 /// Prints `expr` or `(expr)` when `needs_par` holds.
1661 fn print_expr_cond_paren(&mut self, expr
: &ast
::Expr
, needs_par
: bool
) {
1665 self.print_expr(expr
);
1671 fn print_expr_vec(&mut self, exprs
: &[P
<ast
::Expr
>], attrs
: &[ast
::Attribute
]) {
1672 self.ibox(INDENT_UNIT
);
1674 self.print_inner_attributes_inline(attrs
);
1675 self.commasep_exprs(Inconsistent
, &exprs
[..]);
1680 fn print_expr_repeat(
1682 element
: &ast
::Expr
,
1683 count
: &ast
::AnonConst
,
1684 attrs
: &[ast
::Attribute
],
1686 self.ibox(INDENT_UNIT
);
1688 self.print_inner_attributes_inline(attrs
);
1689 self.print_expr(element
);
1690 self.word_space(";");
1691 self.print_expr(&count
.value
);
1696 fn print_expr_struct(
1699 fields
: &[ast
::Field
],
1700 wth
: &Option
<P
<ast
::Expr
>>,
1701 attrs
: &[ast
::Attribute
],
1703 self.print_path(path
, true, 0);
1705 self.print_inner_attributes_inline(attrs
);
1710 s
.print_outer_attributes(&field
.attrs
);
1711 s
.ibox(INDENT_UNIT
);
1712 if !field
.is_shorthand
{
1713 s
.print_ident(field
.ident
);
1716 s
.print_expr(&field
.expr
);
1723 self.ibox(INDENT_UNIT
);
1724 if !fields
.is_empty() {
1729 self.print_expr(expr
);
1733 if !fields
.is_empty() {
1741 fn print_expr_tup(&mut self, exprs
: &[P
<ast
::Expr
>], attrs
: &[ast
::Attribute
]) {
1743 self.print_inner_attributes_inline(attrs
);
1744 self.commasep_exprs(Inconsistent
, &exprs
[..]);
1745 if exprs
.len() == 1 {
1751 fn print_expr_call(&mut self, func
: &ast
::Expr
, args
: &[P
<ast
::Expr
>]) {
1752 let prec
= match func
.kind
{
1753 ast
::ExprKind
::Field(..) => parser
::PREC_FORCE_PAREN
,
1754 _
=> parser
::PREC_POSTFIX
,
1757 self.print_expr_maybe_paren(func
, prec
);
1758 self.print_call_post(args
)
1761 fn print_expr_method_call(&mut self, segment
: &ast
::PathSegment
, args
: &[P
<ast
::Expr
>]) {
1762 let base_args
= &args
[1..];
1763 self.print_expr_maybe_paren(&args
[0], parser
::PREC_POSTFIX
);
1765 self.print_ident(segment
.ident
);
1766 if let Some(ref args
) = segment
.args
{
1767 self.print_generic_args(args
, true);
1769 self.print_call_post(base_args
)
1772 fn print_expr_binary(&mut self, op
: ast
::BinOp
, lhs
: &ast
::Expr
, rhs
: &ast
::Expr
) {
1773 let assoc_op
= AssocOp
::from_ast_binop(op
.node
);
1774 let prec
= assoc_op
.precedence() as i8;
1775 let fixity
= assoc_op
.fixity();
1777 let (left_prec
, right_prec
) = match fixity
{
1778 Fixity
::Left
=> (prec
, prec
+ 1),
1779 Fixity
::Right
=> (prec
+ 1, prec
),
1780 Fixity
::None
=> (prec
+ 1, prec
+ 1),
1783 let left_prec
= match (&lhs
.kind
, op
.node
) {
1784 // These cases need parens: `x as i32 < y` has the parser thinking that `i32 < y` is
1785 // the beginning of a path type. It starts trying to parse `x as (i32 < y ...` instead
1786 // of `(x as i32) < ...`. We need to convince it _not_ to do that.
1787 (&ast
::ExprKind
::Cast { .. }
, ast
::BinOpKind
::Lt
| ast
::BinOpKind
::Shl
) => {
1788 parser
::PREC_FORCE_PAREN
1790 // We are given `(let _ = a) OP b`.
1792 // - When `OP <= LAnd` we should print `let _ = a OP b` to avoid redundant parens
1793 // as the parser will interpret this as `(let _ = a) OP b`.
1795 // - Otherwise, e.g. when we have `(let a = b) < c` in AST,
1796 // parens are required since the parser would interpret `let a = b < c` as
1797 // `let a = (b < c)`. To achieve this, we force parens.
1798 (&ast
::ExprKind
::Let { .. }
, _
) if !parser
::needs_par_as_let_scrutinee(prec
) => {
1799 parser
::PREC_FORCE_PAREN
1804 self.print_expr_maybe_paren(lhs
, left_prec
);
1806 self.word_space(op
.node
.to_string());
1807 self.print_expr_maybe_paren(rhs
, right_prec
)
1810 fn print_expr_unary(&mut self, op
: ast
::UnOp
, expr
: &ast
::Expr
) {
1811 self.s
.word(ast
::UnOp
::to_string(op
));
1812 self.print_expr_maybe_paren(expr
, parser
::PREC_PREFIX
)
1815 fn print_expr_addr_of(
1817 kind
: ast
::BorrowKind
,
1818 mutability
: ast
::Mutability
,
1823 ast
::BorrowKind
::Ref
=> self.print_mutability(mutability
, false),
1824 ast
::BorrowKind
::Raw
=> {
1825 self.word_nbsp("raw");
1826 self.print_mutability(mutability
, true);
1829 self.print_expr_maybe_paren(expr
, parser
::PREC_PREFIX
)
1832 pub fn print_expr(&mut self, expr
: &ast
::Expr
) {
1833 self.print_expr_outer_attr_style(expr
, true)
1836 fn print_expr_outer_attr_style(&mut self, expr
: &ast
::Expr
, is_inline
: bool
) {
1837 self.maybe_print_comment(expr
.span
.lo());
1839 let attrs
= &expr
.attrs
;
1841 self.print_outer_attributes_inline(attrs
);
1843 self.print_outer_attributes(attrs
);
1846 self.ibox(INDENT_UNIT
);
1847 self.ann
.pre(self, AnnNode
::Expr(expr
));
1849 ast
::ExprKind
::Box(ref expr
) => {
1850 self.word_space("box");
1851 self.print_expr_maybe_paren(expr
, parser
::PREC_PREFIX
);
1853 ast
::ExprKind
::Array(ref exprs
) => {
1854 self.print_expr_vec(&exprs
[..], attrs
);
1856 ast
::ExprKind
::Repeat(ref element
, ref count
) => {
1857 self.print_expr_repeat(element
, count
, attrs
);
1859 ast
::ExprKind
::Struct(ref path
, ref fields
, ref wth
) => {
1860 self.print_expr_struct(path
, &fields
[..], wth
, attrs
);
1862 ast
::ExprKind
::Tup(ref exprs
) => {
1863 self.print_expr_tup(&exprs
[..], attrs
);
1865 ast
::ExprKind
::Call(ref func
, ref args
) => {
1866 self.print_expr_call(func
, &args
[..]);
1868 ast
::ExprKind
::MethodCall(ref segment
, ref args
, _
) => {
1869 self.print_expr_method_call(segment
, &args
[..]);
1871 ast
::ExprKind
::Binary(op
, ref lhs
, ref rhs
) => {
1872 self.print_expr_binary(op
, lhs
, rhs
);
1874 ast
::ExprKind
::Unary(op
, ref expr
) => {
1875 self.print_expr_unary(op
, expr
);
1877 ast
::ExprKind
::AddrOf(k
, m
, ref expr
) => {
1878 self.print_expr_addr_of(k
, m
, expr
);
1880 ast
::ExprKind
::Lit(ref lit
) => {
1881 self.print_literal(lit
);
1883 ast
::ExprKind
::Cast(ref expr
, ref ty
) => {
1884 let prec
= AssocOp
::As
.precedence() as i8;
1885 self.print_expr_maybe_paren(expr
, prec
);
1887 self.word_space("as");
1888 self.print_type(ty
);
1890 ast
::ExprKind
::Type(ref expr
, ref ty
) => {
1891 let prec
= AssocOp
::Colon
.precedence() as i8;
1892 self.print_expr_maybe_paren(expr
, prec
);
1893 self.word_space(":");
1894 self.print_type(ty
);
1896 ast
::ExprKind
::Let(ref pat
, ref scrutinee
) => {
1897 self.print_let(pat
, scrutinee
);
1899 ast
::ExprKind
::If(ref test
, ref blk
, ref elseopt
) => {
1900 self.print_if(test
, blk
, elseopt
.as_deref())
1902 ast
::ExprKind
::While(ref test
, ref blk
, opt_label
) => {
1903 if let Some(label
) = opt_label
{
1904 self.print_ident(label
.ident
);
1905 self.word_space(":");
1908 self.print_expr_as_cond(test
);
1910 self.print_block_with_attrs(blk
, attrs
);
1912 ast
::ExprKind
::ForLoop(ref pat
, ref iter
, ref blk
, opt_label
) => {
1913 if let Some(label
) = opt_label
{
1914 self.print_ident(label
.ident
);
1915 self.word_space(":");
1918 self.print_pat(pat
);
1920 self.word_space("in");
1921 self.print_expr_as_cond(iter
);
1923 self.print_block_with_attrs(blk
, attrs
);
1925 ast
::ExprKind
::Loop(ref blk
, opt_label
) => {
1926 if let Some(label
) = opt_label
{
1927 self.print_ident(label
.ident
);
1928 self.word_space(":");
1932 self.print_block_with_attrs(blk
, attrs
);
1934 ast
::ExprKind
::Match(ref expr
, ref arms
) => {
1935 self.cbox(INDENT_UNIT
);
1936 self.ibox(INDENT_UNIT
);
1937 self.word_nbsp("match");
1938 self.print_expr_as_cond(expr
);
1941 self.print_inner_attributes_no_trailing_hardbreak(attrs
);
1943 self.print_arm(arm
);
1945 self.bclose(expr
.span
);
1947 ast
::ExprKind
::Closure(
1955 self.print_movability(movability
);
1956 self.print_asyncness(asyncness
);
1957 self.print_capture_clause(capture_clause
);
1959 self.print_fn_params_and_ret(decl
, true);
1961 self.print_expr(body
);
1962 self.end(); // need to close a box
1964 // a box will be closed by print_expr, but we didn't want an overall
1965 // wrapper so we closed the corresponding opening. so create an
1966 // empty box to satisfy the close.
1969 ast
::ExprKind
::Block(ref blk
, opt_label
) => {
1970 if let Some(label
) = opt_label
{
1971 self.print_ident(label
.ident
);
1972 self.word_space(":");
1974 // containing cbox, will be closed by print-block at }
1975 self.cbox(INDENT_UNIT
);
1976 // head-box, will be closed by print-block after {
1978 self.print_block_with_attrs(blk
, attrs
);
1980 ast
::ExprKind
::Async(capture_clause
, _
, ref blk
) => {
1981 self.word_nbsp("async");
1982 self.print_capture_clause(capture_clause
);
1984 // cbox/ibox in analogy to the `ExprKind::Block` arm above
1985 self.cbox(INDENT_UNIT
);
1987 self.print_block_with_attrs(blk
, attrs
);
1989 ast
::ExprKind
::Await(ref expr
) => {
1990 self.print_expr_maybe_paren(expr
, parser
::PREC_POSTFIX
);
1991 self.s
.word(".await");
1993 ast
::ExprKind
::Assign(ref lhs
, ref rhs
, _
) => {
1994 let prec
= AssocOp
::Assign
.precedence() as i8;
1995 self.print_expr_maybe_paren(lhs
, prec
+ 1);
1997 self.word_space("=");
1998 self.print_expr_maybe_paren(rhs
, prec
);
2000 ast
::ExprKind
::AssignOp(op
, ref lhs
, ref rhs
) => {
2001 let prec
= AssocOp
::Assign
.precedence() as i8;
2002 self.print_expr_maybe_paren(lhs
, prec
+ 1);
2004 self.s
.word(op
.node
.to_string());
2005 self.word_space("=");
2006 self.print_expr_maybe_paren(rhs
, prec
);
2008 ast
::ExprKind
::Field(ref expr
, ident
) => {
2009 self.print_expr_maybe_paren(expr
, parser
::PREC_POSTFIX
);
2011 self.print_ident(ident
);
2013 ast
::ExprKind
::Index(ref expr
, ref index
) => {
2014 self.print_expr_maybe_paren(expr
, parser
::PREC_POSTFIX
);
2016 self.print_expr(index
);
2019 ast
::ExprKind
::Range(ref start
, ref end
, limits
) => {
2020 // Special case for `Range`. `AssocOp` claims that `Range` has higher precedence
2021 // than `Assign`, but `x .. x = x` gives a parse error instead of `x .. (x = x)`.
2022 // Here we use a fake precedence value so that any child with lower precedence than
2023 // a "normal" binop gets parenthesized. (`LOr` is the lowest-precedence binop.)
2024 let fake_prec
= AssocOp
::LOr
.precedence() as i8;
2025 if let Some(ref e
) = *start
{
2026 self.print_expr_maybe_paren(e
, fake_prec
);
2028 if limits
== ast
::RangeLimits
::HalfOpen
{
2033 if let Some(ref e
) = *end
{
2034 self.print_expr_maybe_paren(e
, fake_prec
);
2037 ast
::ExprKind
::Path(None
, ref path
) => self.print_path(path
, true, 0),
2038 ast
::ExprKind
::Path(Some(ref qself
), ref path
) => self.print_qpath(path
, qself
, true),
2039 ast
::ExprKind
::Break(opt_label
, ref opt_expr
) => {
2040 self.s
.word("break");
2042 if let Some(label
) = opt_label
{
2043 self.print_ident(label
.ident
);
2046 if let Some(ref expr
) = *opt_expr
{
2047 self.print_expr_maybe_paren(expr
, parser
::PREC_JUMP
);
2051 ast
::ExprKind
::Continue(opt_label
) => {
2052 self.s
.word("continue");
2054 if let Some(label
) = opt_label
{
2055 self.print_ident(label
.ident
);
2059 ast
::ExprKind
::Ret(ref result
) => {
2060 self.s
.word("return");
2061 if let Some(ref expr
) = *result
{
2063 self.print_expr_maybe_paren(expr
, parser
::PREC_JUMP
);
2066 ast
::ExprKind
::InlineAsm(ref a
) => {
2069 Operand(&'a InlineAsmOperand
),
2070 Options(InlineAsmOptions
),
2073 let mut args
= vec
![];
2074 args
.push(AsmArg
::Template(InlineAsmTemplatePiece
::to_string(&a
.template
)));
2075 args
.extend(a
.operands
.iter().map(|(o
, _
)| AsmArg
::Operand(o
)));
2076 if !a
.options
.is_empty() {
2077 args
.push(AsmArg
::Options(a
.options
));
2082 self.commasep(Consistent
, &args
, |s
, arg
| match arg
{
2083 AsmArg
::Template(template
) => s
.print_string(&template
, ast
::StrStyle
::Cooked
),
2084 AsmArg
::Operand(op
) => {
2085 let print_reg_or_class
= |s
: &mut Self, r
: &InlineAsmRegOrRegClass
| match r
2087 InlineAsmRegOrRegClass
::Reg(r
) => {
2088 s
.print_symbol(*r
, ast
::StrStyle
::Cooked
)
2090 InlineAsmRegOrRegClass
::RegClass(r
) => s
.word(r
.to_string()),
2093 InlineAsmOperand
::In { reg, expr }
=> {
2096 print_reg_or_class(s
, reg
);
2101 InlineAsmOperand
::Out { reg, late, expr }
=> {
2102 s
.word(if *late { "lateout" }
else { "out" }
);
2104 print_reg_or_class(s
, reg
);
2108 Some(expr
) => s
.print_expr(expr
),
2109 None
=> s
.word("_"),
2112 InlineAsmOperand
::InOut { reg, late, expr }
=> {
2113 s
.word(if *late { "inlateout" }
else { "inout" }
);
2115 print_reg_or_class(s
, reg
);
2120 InlineAsmOperand
::SplitInOut { reg, late, in_expr, out_expr }
=> {
2121 s
.word(if *late { "inlateout" }
else { "inout" }
);
2123 print_reg_or_class(s
, reg
);
2126 s
.print_expr(in_expr
);
2130 Some(out_expr
) => s
.print_expr(out_expr
),
2131 None
=> s
.word("_"),
2134 InlineAsmOperand
::Const { expr }
=> {
2139 InlineAsmOperand
::Sym { expr }
=> {
2146 AsmArg
::Options(opts
) => {
2149 let mut options
= vec
![];
2150 if opts
.contains(InlineAsmOptions
::PURE
) {
2151 options
.push("pure");
2153 if opts
.contains(InlineAsmOptions
::NOMEM
) {
2154 options
.push("nomem");
2156 if opts
.contains(InlineAsmOptions
::READONLY
) {
2157 options
.push("readonly");
2159 if opts
.contains(InlineAsmOptions
::PRESERVES_FLAGS
) {
2160 options
.push("preserves_flags");
2162 if opts
.contains(InlineAsmOptions
::NORETURN
) {
2163 options
.push("noreturn");
2165 if opts
.contains(InlineAsmOptions
::NOSTACK
) {
2166 options
.push("nostack");
2168 if opts
.contains(InlineAsmOptions
::ATT_SYNTAX
) {
2169 options
.push("att_syntax");
2171 s
.commasep(Inconsistent
, &options
, |s
, &opt
| {
2179 ast
::ExprKind
::LlvmInlineAsm(ref a
) => {
2180 self.s
.word("llvm_asm!");
2182 self.print_symbol(a
.asm
, a
.asm_str_style
);
2183 self.word_space(":");
2185 self.commasep(Inconsistent
, &a
.outputs
, |s
, out
| {
2186 let constraint
= out
.constraint
.as_str();
2187 let mut ch
= constraint
.chars();
2189 Some('
='
) if out
.is_rw
=> {
2190 s
.print_string(&format
!("+{}", ch
.as_str()), ast
::StrStyle
::Cooked
)
2192 _
=> s
.print_string(&constraint
, ast
::StrStyle
::Cooked
),
2195 s
.print_expr(&out
.expr
);
2199 self.word_space(":");
2201 self.commasep(Inconsistent
, &a
.inputs
, |s
, &(co
, ref o
)| {
2202 s
.print_symbol(co
, ast
::StrStyle
::Cooked
);
2208 self.word_space(":");
2210 self.commasep(Inconsistent
, &a
.clobbers
, |s
, &co
| {
2211 s
.print_symbol(co
, ast
::StrStyle
::Cooked
);
2214 let mut options
= vec
![];
2216 options
.push("volatile");
2219 options
.push("alignstack");
2221 if a
.dialect
== ast
::LlvmAsmDialect
::Intel
{
2222 options
.push("intel");
2225 if !options
.is_empty() {
2227 self.word_space(":");
2228 self.commasep(Inconsistent
, &options
, |s
, &co
| {
2229 s
.print_string(co
, ast
::StrStyle
::Cooked
);
2235 ast
::ExprKind
::MacCall(ref m
) => self.print_mac(m
),
2236 ast
::ExprKind
::Paren(ref e
) => {
2238 self.print_inner_attributes_inline(attrs
);
2242 ast
::ExprKind
::Yield(ref e
) => {
2243 self.s
.word("yield");
2245 if let Some(ref expr
) = *e
{
2247 self.print_expr_maybe_paren(expr
, parser
::PREC_JUMP
);
2250 ast
::ExprKind
::Try(ref e
) => {
2251 self.print_expr_maybe_paren(e
, parser
::PREC_POSTFIX
);
2254 ast
::ExprKind
::TryBlock(ref blk
) => {
2257 self.print_block_with_attrs(blk
, attrs
)
2259 ast
::ExprKind
::Err
=> {
2261 self.s
.word("/*ERROR*/");
2265 self.ann
.post(self, AnnNode
::Expr(expr
));
2269 crate fn print_local_decl(&mut self, loc
: &ast
::Local
) {
2270 self.print_pat(&loc
.pat
);
2271 if let Some(ref ty
) = loc
.ty
{
2272 self.word_space(":");
2273 self.print_type(ty
);
2277 pub fn print_usize(&mut self, i
: usize) {
2278 self.s
.word(i
.to_string())
2281 crate fn print_name(&mut self, name
: Symbol
) {
2282 self.s
.word(name
.to_string());
2283 self.ann
.post(self, AnnNode
::Name(&name
))
2286 fn print_qpath(&mut self, path
: &ast
::Path
, qself
: &ast
::QSelf
, colons_before_params
: bool
) {
2288 self.print_type(&qself
.ty
);
2289 if qself
.position
> 0 {
2291 self.word_space("as");
2292 let depth
= path
.segments
.len() - qself
.position
;
2293 self.print_path(path
, false, depth
);
2297 let item_segment
= path
.segments
.last().unwrap();
2298 self.print_ident(item_segment
.ident
);
2299 if let Some(ref args
) = item_segment
.args
{
2300 self.print_generic_args(args
, colons_before_params
)
2304 crate fn print_pat(&mut self, pat
: &ast
::Pat
) {
2305 self.maybe_print_comment(pat
.span
.lo());
2306 self.ann
.pre(self, AnnNode
::Pat(pat
));
2307 /* Pat isn't normalized, but the beauty of it
2308 is that it doesn't matter */
2310 PatKind
::Wild
=> self.s
.word("_"),
2311 PatKind
::Ident(binding_mode
, ident
, ref sub
) => {
2312 match binding_mode
{
2313 ast
::BindingMode
::ByRef(mutbl
) => {
2314 self.word_nbsp("ref");
2315 self.print_mutability(mutbl
, false);
2317 ast
::BindingMode
::ByValue(ast
::Mutability
::Not
) => {}
2318 ast
::BindingMode
::ByValue(ast
::Mutability
::Mut
) => {
2319 self.word_nbsp("mut");
2322 self.print_ident(ident
);
2323 if let Some(ref p
) = *sub
{
2325 self.s
.word_space("@");
2329 PatKind
::TupleStruct(ref path
, ref elts
) => {
2330 self.print_path(path
, true, 0);
2332 self.commasep(Inconsistent
, &elts
[..], |s
, p
| s
.print_pat(p
));
2335 PatKind
::Or(ref pats
) => {
2336 self.strsep("|", true, Inconsistent
, &pats
[..], |s
, p
| s
.print_pat(p
));
2338 PatKind
::Path(None
, ref path
) => {
2339 self.print_path(path
, true, 0);
2341 PatKind
::Path(Some(ref qself
), ref path
) => {
2342 self.print_qpath(path
, qself
, false);
2344 PatKind
::Struct(ref path
, ref fields
, etc
) => {
2345 self.print_path(path
, true, 0);
2347 self.word_space("{");
2352 s
.cbox(INDENT_UNIT
);
2353 if !f
.is_shorthand
{
2354 s
.print_ident(f
.ident
);
2357 s
.print_pat(&f
.pat
);
2363 if !fields
.is_empty() {
2364 self.word_space(",");
2371 PatKind
::Tuple(ref elts
) => {
2373 self.commasep(Inconsistent
, &elts
[..], |s
, p
| s
.print_pat(p
));
2374 if elts
.len() == 1 {
2379 PatKind
::Box(ref inner
) => {
2380 self.s
.word("box ");
2381 self.print_pat(inner
);
2383 PatKind
::Ref(ref inner
, mutbl
) => {
2385 if mutbl
== ast
::Mutability
::Mut
{
2386 self.s
.word("mut ");
2388 self.print_pat(inner
);
2390 PatKind
::Lit(ref e
) => self.print_expr(&**e
),
2391 PatKind
::Range(ref begin
, ref end
, Spanned { node: ref end_kind, .. }
) => {
2392 if let Some(e
) = begin
{
2397 RangeEnd
::Included(RangeSyntax
::DotDotDot
) => self.s
.word("..."),
2398 RangeEnd
::Included(RangeSyntax
::DotDotEq
) => self.s
.word("..="),
2399 RangeEnd
::Excluded
=> self.s
.word(".."),
2401 if let Some(e
) = end
{
2405 PatKind
::Slice(ref elts
) => {
2407 self.commasep(Inconsistent
, &elts
[..], |s
, p
| s
.print_pat(p
));
2410 PatKind
::Rest
=> self.s
.word(".."),
2411 PatKind
::Paren(ref inner
) => {
2413 self.print_pat(inner
);
2416 PatKind
::MacCall(ref m
) => self.print_mac(m
),
2418 self.ann
.post(self, AnnNode
::Pat(pat
))
2421 fn print_arm(&mut self, arm
: &ast
::Arm
) {
2422 // Note, I have no idea why this check is necessary, but here it is.
2423 if arm
.attrs
.is_empty() {
2426 self.cbox(INDENT_UNIT
);
2428 self.maybe_print_comment(arm
.pat
.span
.lo());
2429 self.print_outer_attributes(&arm
.attrs
);
2430 self.print_pat(&arm
.pat
);
2432 if let Some(ref e
) = arm
.guard
{
2433 self.word_space("if");
2437 self.word_space("=>");
2439 match arm
.body
.kind
{
2440 ast
::ExprKind
::Block(ref blk
, opt_label
) => {
2441 if let Some(label
) = opt_label
{
2442 self.print_ident(label
.ident
);
2443 self.word_space(":");
2446 // The block will close the pattern's ibox.
2447 self.print_block_unclosed_indent(blk
);
2449 // If it is a user-provided unsafe block, print a comma after it.
2450 if let BlockCheckMode
::Unsafe(ast
::UserProvided
) = blk
.rules
{
2455 self.end(); // Close the ibox for the pattern.
2456 self.print_expr(&arm
.body
);
2460 self.end(); // Close enclosing cbox.
2463 fn print_explicit_self(&mut self, explicit_self
: &ast
::ExplicitSelf
) {
2464 match explicit_self
.node
{
2465 SelfKind
::Value(m
) => {
2466 self.print_mutability(m
, false);
2469 SelfKind
::Region(ref lt
, m
) => {
2471 self.print_opt_lifetime(lt
);
2472 self.print_mutability(m
, false);
2475 SelfKind
::Explicit(ref typ
, m
) => {
2476 self.print_mutability(m
, false);
2477 self.s
.word("self");
2478 self.word_space(":");
2479 self.print_type(typ
)
2488 generics
: &ast
::Generics
,
2489 vis
: &ast
::Visibility
,
2490 defaultness
: ast
::Defaultness
,
2491 body
: Option
<&ast
::Block
>,
2492 attrs
: &[ast
::Attribute
],
2497 self.print_visibility(vis
);
2498 self.print_defaultness(defaultness
);
2499 self.print_fn(&sig
.decl
, sig
.header
, Some(name
), generics
);
2500 if let Some(body
) = body
{
2502 self.print_block_with_attrs(body
, attrs
);
2511 header
: ast
::FnHeader
,
2512 name
: Option
<Ident
>,
2513 generics
: &ast
::Generics
,
2515 self.print_fn_header_info(header
);
2516 if let Some(name
) = name
{
2518 self.print_ident(name
);
2520 self.print_generic_params(&generics
.params
);
2521 self.print_fn_params_and_ret(decl
, false);
2522 self.print_where_clause(&generics
.where_clause
)
2525 crate fn print_fn_params_and_ret(&mut self, decl
: &ast
::FnDecl
, is_closure
: bool
) {
2526 let (open
, close
) = if is_closure { ("|", "|") }
else { ("(", ")") }
;
2528 self.commasep(Inconsistent
, &decl
.inputs
, |s
, param
| s
.print_param(param
, is_closure
));
2530 self.print_fn_ret_ty(&decl
.output
)
2533 crate fn print_movability(&mut self, movability
: ast
::Movability
) {
2535 ast
::Movability
::Static
=> self.word_space("static"),
2536 ast
::Movability
::Movable
=> {}
2540 crate fn print_asyncness(&mut self, asyncness
: ast
::Async
) {
2541 if asyncness
.is_async() {
2542 self.word_nbsp("async");
2546 crate fn print_capture_clause(&mut self, capture_clause
: ast
::CaptureBy
) {
2547 match capture_clause
{
2548 ast
::CaptureBy
::Value
=> self.word_space("move"),
2549 ast
::CaptureBy
::Ref
=> {}
2553 pub fn print_type_bounds(&mut self, prefix
: &'
static str, bounds
: &[ast
::GenericBound
]) {
2554 if !bounds
.is_empty() {
2555 self.s
.word(prefix
);
2556 let mut first
= true;
2557 for bound
in bounds
{
2558 if !(first
&& prefix
.is_empty()) {
2564 self.word_space("+");
2568 GenericBound
::Trait(tref
, modifier
) => {
2569 if modifier
== &TraitBoundModifier
::Maybe
{
2572 self.print_poly_trait_ref(tref
);
2574 GenericBound
::Outlives(lt
) => self.print_lifetime(*lt
),
2580 crate fn print_lifetime(&mut self, lifetime
: ast
::Lifetime
) {
2581 self.print_name(lifetime
.ident
.name
)
2584 crate fn print_lifetime_bounds(
2586 lifetime
: ast
::Lifetime
,
2587 bounds
: &ast
::GenericBounds
,
2589 self.print_lifetime(lifetime
);
2590 if !bounds
.is_empty() {
2592 for (i
, bound
) in bounds
.iter().enumerate() {
2597 ast
::GenericBound
::Outlives(lt
) => self.print_lifetime(*lt
),
2604 crate fn print_generic_params(&mut self, generic_params
: &[ast
::GenericParam
]) {
2605 if generic_params
.is_empty() {
2611 self.commasep(Inconsistent
, &generic_params
, |s
, param
| {
2612 s
.print_outer_attributes_inline(¶m
.attrs
);
2615 ast
::GenericParamKind
::Lifetime
=> {
2616 let lt
= ast
::Lifetime { id: param.id, ident: param.ident }
;
2617 s
.print_lifetime_bounds(lt
, ¶m
.bounds
)
2619 ast
::GenericParamKind
::Type { ref default }
=> {
2620 s
.print_ident(param
.ident
);
2621 s
.print_type_bounds(":", ¶m
.bounds
);
2622 if let Some(ref default) = default {
2625 s
.print_type(default)
2628 ast
::GenericParamKind
::Const { ref ty, kw_span: _ }
=> {
2629 s
.word_space("const");
2630 s
.print_ident(param
.ident
);
2634 s
.print_type_bounds(":", ¶m
.bounds
)
2642 crate fn print_where_clause(&mut self, where_clause
: &ast
::WhereClause
) {
2643 if where_clause
.predicates
.is_empty() && !where_clause
.has_where_token
{
2648 self.word_space("where");
2650 for (i
, predicate
) in where_clause
.predicates
.iter().enumerate() {
2652 self.word_space(",");
2656 ast
::WherePredicate
::BoundPredicate(ast
::WhereBoundPredicate
{
2657 ref bound_generic_params
,
2662 self.print_formal_generic_params(bound_generic_params
);
2663 self.print_type(bounded_ty
);
2664 self.print_type_bounds(":", bounds
);
2666 ast
::WherePredicate
::RegionPredicate(ast
::WhereRegionPredicate
{
2671 self.print_lifetime_bounds(*lifetime
, bounds
);
2673 ast
::WherePredicate
::EqPredicate(ast
::WhereEqPredicate
{
2678 self.print_type(lhs_ty
);
2680 self.word_space("=");
2681 self.print_type(rhs_ty
);
2687 crate fn print_use_tree(&mut self, tree
: &ast
::UseTree
) {
2689 ast
::UseTreeKind
::Simple(rename
, ..) => {
2690 self.print_path(&tree
.prefix
, false, 0);
2691 if let Some(rename
) = rename
{
2693 self.word_space("as");
2694 self.print_ident(rename
);
2697 ast
::UseTreeKind
::Glob
=> {
2698 if !tree
.prefix
.segments
.is_empty() {
2699 self.print_path(&tree
.prefix
, false, 0);
2704 ast
::UseTreeKind
::Nested(ref items
) => {
2705 if tree
.prefix
.segments
.is_empty() {
2708 self.print_path(&tree
.prefix
, false, 0);
2711 self.commasep(Inconsistent
, &items
[..], |this
, &(ref tree
, _
)| {
2712 this
.print_use_tree(tree
)
2719 pub fn print_mutability(&mut self, mutbl
: ast
::Mutability
, print_const
: bool
) {
2721 ast
::Mutability
::Mut
=> self.word_nbsp("mut"),
2722 ast
::Mutability
::Not
=> {
2724 self.word_nbsp("const");
2730 crate fn print_mt(&mut self, mt
: &ast
::MutTy
, print_const
: bool
) {
2731 self.print_mutability(mt
.mutbl
, print_const
);
2732 self.print_type(&mt
.ty
)
2735 crate fn print_param(&mut self, input
: &ast
::Param
, is_closure
: bool
) {
2736 self.ibox(INDENT_UNIT
);
2738 self.print_outer_attributes_inline(&input
.attrs
);
2740 match input
.ty
.kind
{
2741 ast
::TyKind
::Infer
if is_closure
=> self.print_pat(&input
.pat
),
2743 if let Some(eself
) = input
.to_self() {
2744 self.print_explicit_self(&eself
);
2746 let invalid
= if let PatKind
::Ident(_
, ident
, _
) = input
.pat
.kind
{
2747 ident
.name
== kw
::Invalid
2752 self.print_pat(&input
.pat
);
2756 self.print_type(&input
.ty
);
2763 crate fn print_fn_ret_ty(&mut self, fn_ret_ty
: &ast
::FnRetTy
) {
2764 if let ast
::FnRetTy
::Ty(ty
) = fn_ret_ty
{
2765 self.space_if_not_bol();
2766 self.ibox(INDENT_UNIT
);
2767 self.word_space("->");
2768 self.print_type(ty
);
2770 self.maybe_print_comment(ty
.span
.lo());
2774 crate fn print_ty_fn(
2777 unsafety
: ast
::Unsafe
,
2779 name
: Option
<Ident
>,
2780 generic_params
: &[ast
::GenericParam
],
2782 self.ibox(INDENT_UNIT
);
2783 if !generic_params
.is_empty() {
2785 self.print_generic_params(generic_params
);
2787 let generics
= ast
::Generics
{
2789 where_clause
: ast
::WhereClause
{
2790 has_where_token
: false,
2791 predicates
: Vec
::new(),
2792 span
: rustc_span
::DUMMY_SP
,
2794 span
: rustc_span
::DUMMY_SP
,
2796 let header
= ast
::FnHeader { unsafety, ext, ..ast::FnHeader::default() }
;
2797 self.print_fn(decl
, header
, name
, &generics
);
2801 crate fn maybe_print_trailing_comment(
2803 span
: rustc_span
::Span
,
2804 next_pos
: Option
<BytePos
>,
2806 if let Some(cmnts
) = self.comments() {
2807 if let Some(cmnt
) = cmnts
.trailing_comment(span
, next_pos
) {
2808 self.print_comment(&cmnt
);
2813 crate fn print_remaining_comments(&mut self) {
2814 // If there aren't any remaining comments, then we need to manually
2815 // make sure there is a line break at the end.
2816 if self.next_comment().is_none() {
2819 while let Some(ref cmnt
) = self.next_comment() {
2820 self.print_comment(cmnt
);
2824 crate fn print_fn_header_info(&mut self, header
: ast
::FnHeader
) {
2825 self.print_constness(header
.constness
);
2826 self.print_asyncness(header
.asyncness
);
2827 self.print_unsafety(header
.unsafety
);
2830 ast
::Extern
::None
=> {}
2831 ast
::Extern
::Implicit
=> {
2832 self.word_nbsp("extern");
2834 ast
::Extern
::Explicit(abi
) => {
2835 self.word_nbsp("extern");
2836 self.print_literal(&abi
.as_lit());
2844 crate fn print_unsafety(&mut self, s
: ast
::Unsafe
) {
2846 ast
::Unsafe
::No
=> {}
2847 ast
::Unsafe
::Yes(_
) => self.word_nbsp("unsafe"),
2851 crate fn print_constness(&mut self, s
: ast
::Const
) {
2853 ast
::Const
::No
=> {}
2854 ast
::Const
::Yes(_
) => self.word_nbsp("const"),
2858 crate fn print_is_auto(&mut self, s
: ast
::IsAuto
) {
2860 ast
::IsAuto
::Yes
=> self.word_nbsp("auto"),
2861 ast
::IsAuto
::No
=> {}